OSDN Git Service

2007-06-04 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 85881c0..4a9ea8c 100644 (file)
@@ -3,7 +3,7 @@
    building RTL.  These routines are used both during actual parsing
    and during the instantiation of template functions.
 
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
    Written by Mark Mitchell (mmitchell@usa.net) based on code found
    formerly in parse.y and pt.c.
@@ -96,7 +96,7 @@ static tree finalize_nrv_r (tree *, int *, void *);
 
    2. When a declaration such as a type, or a variable, is encountered,
       the function `perform_or_defer_access_check' is called.  It
-      maintains a TREE_LIST of all deferred checks.
+      maintains a VEC of all deferred checks.
 
    3. The global `current_class_type' or `current_function_decl' is then
       setup by the parser.  `enforce_access' relies on these information
@@ -104,7 +104,7 @@ static tree finalize_nrv_r (tree *, int *, void *);
 
    4. Upon exiting the context mentioned in step 1,
       `perform_deferred_access_checks' is called to check all declaration
-      stored in the TREE_LIST.   `pop_deferring_access_checks' is then
+      stored in the VEC. `pop_deferring_access_checks' is then
       called to restore the previous access checking mode.
 
       In case of parsing error, we simply call `pop_deferring_access_checks'
@@ -112,7 +112,7 @@ static tree finalize_nrv_r (tree *, int *, void *);
 
 typedef struct deferred_access GTY(())
 {
-  /* A TREE_LIST representing name-lookups for which we have deferred
+  /* A VEC representing name-lookups for which we have deferred
      checking access controls.  We cannot check the accessibility of
      names used in a decl-specifier-seq until we know what is being
      declared because code like:
@@ -124,12 +124,8 @@ typedef struct deferred_access GTY(())
 
        A::B* A::f() { return 0; }
 
-     is valid, even though `A::B' is not generally accessible.
-
-     The TREE_PURPOSE of each node is the scope used to qualify the
-     name being looked up; the TREE_VALUE is the DECL to which the
-     name was resolved.  */
-  tree deferred_access_checks;
+     is valid, even though `A::B' is not generally accessible.  */
+  VEC (deferred_access_check,gc)* GTY(()) deferred_access_checks;
 
   /* The current mode of access checks.  */
   enum deferring_kind deferring_access_checks_kind;
@@ -157,7 +153,7 @@ push_deferring_access_checks (deferring_kind deferring)
       deferred_access *ptr;
 
       ptr = VEC_safe_push (deferred_access, gc, deferred_access_stack, NULL);
-      ptr->deferred_access_checks = NULL_TREE;
+      ptr->deferred_access_checks = NULL;
       ptr->deferring_access_checks_kind = deferring;
     }
 }
@@ -200,7 +196,7 @@ pop_deferring_access_checks (void)
    access occurred; the TREE_VALUE is the declaration named.
    */
 
-tree
+VEC (deferred_access_check,gc)*
 get_deferred_access_checks (void)
 {
   if (deferred_access_no_check)
@@ -221,7 +217,7 @@ pop_to_parent_deferring_access_checks (void)
     deferred_access_no_check--;
   else
     {
-      tree checks;
+      VEC (deferred_access_check,gc) *checks;
       deferred_access *ptr;
 
       checks = (VEC_last (deferred_access, deferred_access_stack)
@@ -232,29 +228,31 @@ pop_to_parent_deferring_access_checks (void)
       if (ptr->deferring_access_checks_kind == dk_no_deferred)
        {
          /* Check access.  */
-         for (; checks; checks = TREE_CHAIN (checks))
-           enforce_access (TREE_PURPOSE (checks),
-                           TREE_VALUE (checks));
+         perform_access_checks (checks);
        }
       else
        {
          /* Merge with parent.  */
-         tree next;
-         tree original = ptr->deferred_access_checks;
+         int i, j;
+         deferred_access_check *chk, *probe;
 
-         for (; checks; checks = next)
+         for (i = 0 ;
+              VEC_iterate (deferred_access_check, checks, i, chk) ;
+              ++i)
            {
-             tree probe;
-
-             next = TREE_CHAIN (checks);
-
-             for (probe = original; probe; probe = TREE_CHAIN (probe))
-               if (TREE_VALUE (probe) == TREE_VALUE (checks)
-                   && TREE_PURPOSE (probe) == TREE_PURPOSE (checks))
-                 goto found;
+             for (j = 0 ;
+                  VEC_iterate (deferred_access_check,
+                               ptr->deferred_access_checks, j, probe) ;
+                  ++j)
+               {
+                 if (probe->binfo == chk->binfo &&
+                     probe->decl == chk->decl &&
+                     probe->diag_decl == chk->diag_decl)
+                   goto found;
+               }
              /* Insert into parent's checks.  */
-             TREE_CHAIN (checks) = ptr->deferred_access_checks;
-             ptr->deferred_access_checks = checks;
+             VEC_safe_push (deferred_access_check, gc,
+                            ptr->deferred_access_checks, chk);
            found:;
            }
        }
@@ -266,14 +264,16 @@ pop_to_parent_deferring_access_checks (void)
    DECL node stored in the TREE_VALUE of the node.  */
 
 void
-perform_access_checks (tree checks)
+perform_access_checks (VEC (deferred_access_check,gc)* checks)
 {
-  while (checks)
-    {
-      enforce_access (TREE_PURPOSE (checks),
-                     TREE_VALUE (checks));
-      checks = TREE_CHAIN (checks);
-    }
+  int i;
+  deferred_access_check *chk;
+
+  if (!checks)
+    return;
+
+  for (i = 0 ; VEC_iterate (deferred_access_check, checks, i, chk) ; ++i)
+    enforce_access (chk->binfo, chk->decl, chk->diag_decl);
 }
 
 /* Perform the deferred access checks.
@@ -299,13 +299,16 @@ perform_deferred_access_checks (void)
 }
 
 /* Defer checking the accessibility of DECL, when looked up in
-   BINFO.  */
+   BINFO. DIAG_DECL is the declaration to use to print diagnostics.  */
 
 void
-perform_or_defer_access_check (tree binfo, tree decl)
+perform_or_defer_access_check (tree binfo, tree decl, tree diag_decl)
 {
-  tree check;
+  int i;
   deferred_access *ptr;
+  deferred_access_check *chk;
+  deferred_access_check *new_access;
+
 
   /* Exit if we are in a context that no access checking is performed.
      */
@@ -319,19 +322,29 @@ perform_or_defer_access_check (tree binfo, tree decl)
   /* If we are not supposed to defer access checks, just check now.  */
   if (ptr->deferring_access_checks_kind == dk_no_deferred)
     {
-      enforce_access (binfo, decl);
+      enforce_access (binfo, decl, diag_decl);
       return;
     }
 
   /* See if we are already going to perform this check.  */
-  for (check = ptr->deferred_access_checks;
-       check;
-       check = TREE_CHAIN (check))
-    if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo)
-      return;
+  for (i = 0 ;
+       VEC_iterate (deferred_access_check,
+                   ptr->deferred_access_checks, i, chk) ;
+       ++i)
+    {
+      if (chk->decl == decl && chk->binfo == binfo &&
+         chk->diag_decl == diag_decl)
+       {
+         return;
+       }
+    }
   /* If not, record the check.  */
-  ptr->deferred_access_checks
-    = tree_cons (binfo, decl, ptr->deferred_access_checks);
+  new_access =
+    VEC_safe_push (deferred_access_check, gc,
+                  ptr->deferred_access_checks, 0);
+  new_access->binfo = binfo;
+  new_access->decl = decl;
+  new_access->diag_decl = diag_decl;
 }
 
 /* Returns nonzero if the current statement is a full expression,
@@ -496,6 +509,8 @@ finish_cond (tree *cond_p, tree expr)
       tree cond = pop_stmt_list (*cond_p);
       if (TREE_CODE (cond) == DECL_EXPR)
        expr = cond;
+
+      check_for_bare_parameter_packs (expr);
     }
   *cond_p = expr;
 }
@@ -574,6 +589,16 @@ maybe_convert_cond (tree cond)
 
   /* Do the conversion.  */
   cond = convert_from_reference (cond);
+
+  if (TREE_CODE (cond) == MODIFY_EXPR
+      && !TREE_NO_WARNING (cond)
+      && warn_parentheses)
+    {
+      warning (OPT_Wparentheses,
+              "suggest parentheses around assignment used as truth value");
+      TREE_NO_WARNING (cond) = 1;
+    }
+
   return condition_conversion (cond);
 }
 
@@ -595,6 +620,8 @@ finish_expr_stmt (tree expr)
       else if (!type_dependent_expression_p (expr))
        convert_to_void (build_non_dependent_expr (expr), "statement");
 
+      check_for_bare_parameter_packs (expr);
+
       /* Simplification of inner statement expressions, compound exprs,
         etc can result in us already having an EXPR_STMT.  */
       if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
@@ -674,7 +701,7 @@ finish_if_stmt (tree if_stmt)
   TREE_CHAIN (if_stmt) = NULL;
   add_stmt (do_poplevel (scope));
   finish_stmt ();
-  empty_body_warning (THEN_CLAUSE (if_stmt), ELSE_CLAUSE (if_stmt));
+  empty_if_body_warning (THEN_CLAUSE (if_stmt), ELSE_CLAUSE (if_stmt));
 }
 
 /* Begin a while-statement.  Returns a newly created WHILE_STMT if
@@ -727,7 +754,14 @@ begin_do_stmt (void)
 void
 finish_do_body (tree do_stmt)
 {
-  DO_BODY (do_stmt) = pop_stmt_list (DO_BODY (do_stmt));
+  tree body = DO_BODY (do_stmt) = pop_stmt_list (DO_BODY (do_stmt));
+
+  if (TREE_CODE (body) == STATEMENT_LIST && STATEMENT_LIST_TAIL (body))
+    body = STATEMENT_LIST_TAIL (body)->stmt;
+
+  if (IS_EMPTY_STMT (body))
+    warning (OPT_Wempty_body,
+            "suggest explicit braces around empty body in %<do%> statement");
 }
 
 /* Finish a do-statement, which may be given by DO_STMT, and whose
@@ -843,6 +877,7 @@ finish_for_expr (tree expr, tree for_stmt)
   else if (!type_dependent_expression_p (expr))
     convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
   expr = maybe_cleanup_point_expr_void (expr);
+  check_for_bare_parameter_packs (expr);
   FOR_EXPR (for_stmt) = expr;
 }
 
@@ -943,6 +978,7 @@ finish_switch_cond (tree cond, tree switch_stmt)
   add_stmt (switch_stmt);
   push_switch (switch_stmt);
   SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
+  check_for_bare_parameter_packs (cond);
 }
 
 /* Finish the body of a switch-statement, which may be given by
@@ -1223,7 +1259,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                     effectively const.  */
                  || (CLASS_TYPE_P (TREE_TYPE (operand))
                      && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
-           readonly_error (operand, "assignment (via 'asm' output)", 0);
+           readonly_error (operand, "assignment (via 'asm' output)");
 
          constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
          oconstraints[i] = constraint;
@@ -1293,6 +1329,10 @@ tree
 finish_label_stmt (tree name)
 {
   tree decl = define_label (input_location, name);
+
+  if (decl  == error_mark_node)
+    return error_mark_node;
+
   return add_stmt (build_stmt (LABEL_EXPR, decl));
 }
 
@@ -1335,7 +1375,22 @@ finish_mem_initializers (tree mem_inits)
   mem_inits = nreverse (mem_inits);
 
   if (processing_template_decl)
-    add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
+    {
+      tree mem;
+
+      for (mem = mem_inits; mem; mem = TREE_CHAIN (mem))
+        {
+          /* If the TREE_PURPOSE is a TYPE_PACK_EXPANSION, skip the
+             check for bare parameter packs in the TREE_VALUE, because
+             any parameter packs in the TREE_VALUE have already been
+             bound as part of the TREE_PURPOSE.  See
+             make_pack_expansion for more information.  */
+          if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
+            check_for_bare_parameter_packs (TREE_VALUE (mem));
+        }
+
+      add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
+    }
   else
     emit_mem_initializers (mem_inits);
 }
@@ -1428,7 +1483,8 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
                                     DECL_NAME (decl),
                                     /*template_p=*/false);
 
-      perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
+      perform_or_defer_access_check (TYPE_BINFO (access_type), decl,
+                                    decl);
 
       /* If the data member was named `C::M', convert `*this' to `C'
         first.  */
@@ -1502,10 +1558,13 @@ check_accessibility_of_qualified_id (tree decl,
        its bases.  */
     qualifying_type = currently_open_derived_class (scope);
 
-  if (qualifying_type && IS_AGGR_TYPE_CODE (TREE_CODE (qualifying_type)))
-    /* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
-       or similar in a default argument value.  */
-    perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl);
+  if (qualifying_type 
+      /* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
+        or similar in a default argument value.  */
+      && CLASS_TYPE_P (qualifying_type)
+      && !dependent_type_p (qualifying_type))
+    perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl,
+                                  decl);
 }
 
 /* EXPR is the result of a qualified-id.  The QUALIFYING_CLASS was the
@@ -1600,76 +1659,57 @@ tree
 finish_stmt_expr_expr (tree expr, tree stmt_expr)
 {
   if (error_operand_p (expr))
-    return error_mark_node;
+    {
+      /* The type of the statement-expression is the type of the last
+         expression.  */
+      TREE_TYPE (stmt_expr) = error_mark_node;
+      return error_mark_node;
+    }
 
   /* If the last statement does not have "void" type, then the value
      of the last statement is the value of the entire expression.  */
   if (expr)
     {
-      tree type;
-      type = TREE_TYPE (expr);
-      if (!dependent_type_p (type) && !VOID_TYPE_P (type))
+      tree type = TREE_TYPE (expr);
+
+      if (processing_template_decl)
        {
-         expr = decay_conversion (expr);
+         expr = build_stmt (EXPR_STMT, expr);
+         expr = add_stmt (expr);
+         /* Mark the last statement so that we can recognize it as such at
+            template-instantiation time.  */
+         EXPR_STMT_STMT_EXPR_RESULT (expr) = 1;
+       }
+      else if (VOID_TYPE_P (type))
+       {
+         /* Just treat this like an ordinary statement.  */
+         expr = finish_expr_stmt (expr);
+       }
+      else
+       {
+         /* It actually has a value we need to deal with.  First, force it
+            to be an rvalue so that we won't need to build up a copy
+            constructor call later when we try to assign it to something.  */
+         expr = force_rvalue (expr);
          if (error_operand_p (expr))
            return error_mark_node;
+
+         /* Update for array-to-pointer decay.  */
          type = TREE_TYPE (expr);
+
+         /* Wrap it in a CLEANUP_POINT_EXPR and add it to the list like a
+            normal statement, but don't convert to void or actually add
+            the EXPR_STMT.  */
+         if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
+           expr = maybe_cleanup_point_expr (expr);
+         add_stmt (expr);
        }
+
       /* The type of the statement-expression is the type of the last
         expression.  */
       TREE_TYPE (stmt_expr) = type;
-      /* We must take particular care if TYPE is a class type.  In
-        particular if EXPR creates a temporary of class type, then it
-        must be destroyed at the semicolon terminating the last
-        statement -- but we must make a copy before that happens.
-
-        This problem is solved by using a TARGET_EXPR to initialize a
-        new temporary variable.  The TARGET_EXPR itself is placed
-        outside the statement-expression.  However, the last
-        statement in the statement-expression is transformed from
-        EXPR to (approximately) T = EXPR, where T is the new
-        temporary variable.  Thus, the lifetime of the new temporary
-        extends to the full-expression surrounding the
-        statement-expression.  */
-      if (!processing_template_decl && !VOID_TYPE_P (type))
-       {
-         tree target_expr;
-         if (CLASS_TYPE_P (type)
-             && !TYPE_HAS_TRIVIAL_INIT_REF (type))
-           {
-             target_expr = build_target_expr_with_type (expr, type);
-             expr = TARGET_EXPR_INITIAL (target_expr);
-           }
-         else
-           {
-             /* Normally, build_target_expr will not create a
-                TARGET_EXPR for scalars.  However, we need the
-                temporary here, in order to solve the scoping
-                problem described above.  */
-             target_expr = force_target_expr (type, expr);
-             expr = TARGET_EXPR_INITIAL (target_expr);
-             expr = build2 (INIT_EXPR,
-                            type,
-                            TARGET_EXPR_SLOT (target_expr),
-                            expr);
-           }
-         TARGET_EXPR_INITIAL (target_expr) = NULL_TREE;
-         /* Save away the TARGET_EXPR in the TREE_TYPE field of the
-            STATEMENT_EXPR.  We will retrieve it in
-            finish_stmt_expr.  */
-         TREE_TYPE (stmt_expr) = target_expr;
-       }
     }
 
-  /* Having modified EXPR to reflect the extra initialization, we now
-     treat it just like an ordinary statement.  */
-  expr = finish_expr_stmt (expr);
-
-  /* Mark the last statement so that we can recognize it as such at
-     template-instantiation time.  */
-  if (expr && processing_template_decl)
-    EXPR_STMT_STMT_EXPR_RESULT (expr) = 1;
-
   return stmt_expr;
 }
 
@@ -1690,6 +1730,7 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
 
   type = TREE_TYPE (stmt_expr);
   result = pop_stmt_list (stmt_expr);
+  TREE_TYPE (result) = type;
 
   if (processing_template_decl)
     {
@@ -1697,12 +1738,13 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
       TREE_SIDE_EFFECTS (result) = 1;
       STMT_EXPR_NO_SCOPE (result) = has_no_scope;
     }
-  else if (!TYPE_P (type))
+  else if (CLASS_TYPE_P (type))
     {
-      gcc_assert (TREE_CODE (type) == TARGET_EXPR);
-      TARGET_EXPR_INITIAL (type) = result;
-      TREE_TYPE (result) = void_type_node;
-      result = type;
+      /* Wrap the statement-expression in a TARGET_EXPR so that the
+        temporary object created by the final expression is destroyed at
+        the end of the full-expression containing the
+        statement-expression.  */
+      result = force_target_expr (type, result);
     }
 
   return result;
@@ -1770,6 +1812,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 
   /* ARGS should be a list of arguments.  */
   gcc_assert (!args || TREE_CODE (args) == TREE_LIST);
+  gcc_assert (!TYPE_P (fn));
 
   orig_fn = fn;
   orig_args = args;
@@ -1779,7 +1822,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
       if (type_dependent_expression_p (fn)
          || any_type_dependent_arguments_p (args))
        {
-         result = build_nt (CALL_EXPR, fn, args, NULL_TREE);
+         result = build_nt_call_list (fn, args);
          KOENIG_LOOKUP_P (result) = koenig_p;
          return result;
        }
@@ -1790,26 +1833,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
       args = build_non_dependent_args (orig_args);
     }
 
-  /* A reference to a member function will appear as an overloaded
-     function (rather than a BASELINK) if an unqualified name was used
-     to refer to it.  */
-  if (!BASELINK_P (fn) && is_overloaded_fn (fn))
-    {
-      tree f = fn;
-
-      if (TREE_CODE (f) == TEMPLATE_ID_EXPR)
-       f = TREE_OPERAND (f, 0);
-      f = get_first_fn (f);
-      if (DECL_FUNCTION_MEMBER_P (f))
-       {
-         tree type = currently_open_derived_class (DECL_CONTEXT (f));
-         if (!type)
-           type = DECL_CONTEXT (f);
-         fn = build_baselink (TYPE_BINFO (type),
-                              TYPE_BINFO (type),
-                              fn, /*optype=*/NULL_TREE);
-       }
-    }
+  if (is_overloaded_fn (fn))
+    fn = baselink_for_fns (fn);
 
   result = NULL_TREE;
   if (BASELINK_P (fn))
@@ -1854,7 +1879,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
       if (processing_template_decl)
        {
          if (type_dependent_expression_p (object))
-           return build_nt (CALL_EXPR, orig_fn, orig_args, NULL_TREE);
+           return build_nt_call_list (orig_fn, orig_args);
          object = build_non_dependent_expr (object);
        }
 
@@ -1898,8 +1923,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 
   if (processing_template_decl)
     {
-      result = build3 (CALL_EXPR, TREE_TYPE (result), orig_fn,
-                      orig_args, NULL_TREE);
+      result = build_call_list (TREE_TYPE (result), orig_fn, orig_args);
       KOENIG_LOOKUP_P (result) = koenig_p;
     }
   return result;
@@ -1964,6 +1988,13 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
          error ("invalid qualifying scope in pseudo-destructor name");
          return error_mark_node;
        }
+      if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
+       {
+         error ("qualified type %qT does not match destructor name ~%qT",
+                scope, destructor);
+         return error_mark_node;
+       }
+
 
       /* [expr.pseudo] says both:
 
@@ -2008,7 +2039,9 @@ finish_unary_op_expr (enum tree_code code, tree expr)
       result = copy_node (result);
       TREE_NEGATED_INT (result) = 1;
     }
-  overflow_warning (result);
+  if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
+    overflow_warning (result);
+
   return result;
 }
 
@@ -2052,7 +2085,7 @@ finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
       DECL_NAME (var) = make_anon_name ();
     }
   /* We must call pushdecl, since the gimplifier complains if the
-     variable hase been declared via a BIND_EXPR.  */
+     variable has not been declared via a BIND_EXPR.  */
   pushdecl (var);
   /* Initialize the variable as we would any other variable with a
      brace-enclosed initializer.  */
@@ -2137,19 +2170,8 @@ check_template_template_default_arg (tree argument)
       && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
     {
       if (TREE_CODE (argument) == TYPE_DECL)
-       {
-         tree t = TREE_TYPE (argument);
-
-         /* Try to emit a slightly smarter error message if we detect
-            that the user is using a template instantiation.  */
-         if (CLASSTYPE_TEMPLATE_INFO (t)
-             && CLASSTYPE_TEMPLATE_INSTANTIATION (t))
-           error ("invalid use of type %qT as a default value for a "
-                  "template template-parameter", t);
-         else
-           error ("invalid use of %qD as a default value for a template "
-                  "template-parameter", argument);
-       }
+       error ("invalid use of type %qT as a default value for a template "
+              "template-parameter", TREE_TYPE (argument));
       else
        error ("invalid default argument for a template template parameter");
       return error_mark_node;
@@ -2161,7 +2183,7 @@ check_template_template_default_arg (tree argument)
 /* Begin a class definition, as indicated by T.  */
 
 tree
-begin_class_definition (tree t)
+begin_class_definition (tree t, tree attributes)
 {
   if (t == error_mark_node)
     return error_mark_node;
@@ -2200,6 +2222,9 @@ begin_class_definition (tree t)
   maybe_process_partial_specialization (t);
   pushclass (t);
   TYPE_BEING_DEFINED (t) = 1;
+
+  cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+
   if (flag_pack_struct)
     {
       tree v;
@@ -2215,7 +2240,7 @@ begin_class_definition (tree t)
      before.  */
   if (! TYPE_ANONYMOUS_P (t))
     {
-      struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
+      struct c_fileinfo *finfo = get_fileinfo (input_filename);
       CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
       SET_CLASSTYPE_INTERFACE_UNKNOWN_X
        (t, finfo->interface_unknown);
@@ -2258,6 +2283,11 @@ finish_member_declaration (tree decl)
   /* Mark the DECL as a member of the current class.  */
   DECL_CONTEXT (decl) = current_class_type;
 
+  /* Check for bare parameter packs in the member variable declaration.  */
+  if (TREE_CODE (decl) == FIELD_DECL
+      && !check_for_bare_parameter_packs (TREE_TYPE (decl)))
+    TREE_TYPE (decl) = error_mark_node;
+
   /* [dcl.link]
 
      A C language linkage is ignored for the names of class members
@@ -2332,8 +2362,9 @@ note_decl_for_pch (tree decl)
 
   /* There's a good chance that we'll have to mangle names at some
      point, even if only for emission in debugging information.  */
-  if (TREE_CODE (decl) == VAR_DECL
-      || TREE_CODE (decl) == FUNCTION_DECL)
+  if ((TREE_CODE (decl) == VAR_DECL
+       || TREE_CODE (decl) == FUNCTION_DECL)
+      && !processing_template_decl)
     mangle_decl (decl);
 }
 
@@ -2428,6 +2459,35 @@ qualified_name_lookup_error (tree scope, tree name, tree decl)
     error ("%<::%D%> has not been declared", name);
 }
 
+/* If FNS is a member function, a set of member functions, or a
+   template-id referring to one or more member functions, return a
+   BASELINK for FNS, incorporating the current access context.
+   Otherwise, return FNS unchanged.  */
+
+tree
+baselink_for_fns (tree fns)
+{
+  tree fn;
+  tree cl;
+
+  if (BASELINK_P (fns) 
+      || error_operand_p (fns))
+    return fns;
+  
+  fn = fns;
+  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+    fn = TREE_OPERAND (fn, 0);
+  fn = get_first_fn (fn);
+  if (!DECL_FUNCTION_MEMBER_P (fn))
+    return fns;
+
+  cl = currently_open_derived_class (DECL_CONTEXT (fn));
+  if (!cl)
+    cl = DECL_CONTEXT (fn);
+  cl = TYPE_BINFO (cl);
+  return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
+}
+
 /* ID_EXPRESSION is a representation of parsed, but unprocessed,
    id-expression.  (See cp_parser_id_expression for details.)  SCOPE,
    if non-NULL, is the type or namespace used to explicitly qualify
@@ -2590,7 +2650,10 @@ finish_id_expression (tree id_expression,
     {
       *idk = CP_ID_KIND_NONE;
       if (!processing_template_decl)
-       return DECL_INITIAL (decl);
+       {
+         used_types_insert (TREE_TYPE (decl));
+         return DECL_INITIAL (decl);
+       }
       return decl;
     }
   else
@@ -2813,8 +2876,12 @@ finish_id_expression (tree id_expression,
        }
       else if (is_overloaded_fn (decl))
        {
-         tree first_fn = OVL_CURRENT (decl);
+         tree first_fn;
 
+         first_fn = decl;
+         if (TREE_CODE (first_fn) == TEMPLATE_ID_EXPR)
+           first_fn = TREE_OPERAND (first_fn, 0);
+         first_fn = get_first_fn (first_fn);
          if (TREE_CODE (first_fn) == TEMPLATE_DECL)
            first_fn = DECL_TEMPLATE_RESULT (first_fn);
 
@@ -2831,6 +2898,8 @@ finish_id_expression (tree id_expression,
              return finish_class_member_access_expr (decl, id_expression,
                                                      /*template_p=*/false);
            }
+
+         decl = baselink_for_fns (decl);
        }
       else
        {
@@ -2841,7 +2910,7 @@ finish_id_expression (tree id_expression,
              tree path;
 
              path = currently_open_derived_class (DECL_CONTEXT (decl));
-             perform_or_defer_access_check (TYPE_BINFO (path), decl);
+             perform_or_defer_access_check (TYPE_BINFO (path), decl, decl);
            }
 
          decl = convert_from_reference (decl);
@@ -2870,7 +2939,7 @@ finish_typeof (tree expr)
       return type;
     }
 
-  type = TREE_TYPE (expr);
+  type = unlowered_expr_type (expr);
 
   if (!type || type == unknown_type_node)
     {
@@ -2897,11 +2966,13 @@ finish_offsetof (tree expr)
       || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
       || TREE_CODE (TREE_TYPE (expr)) == UNKNOWN_TYPE)
     {
-      error ("cannot apply %<offsetof%> to member function %qD",
-            TREE_OPERAND (expr, 1));
+      if (TREE_CODE (expr) == COMPONENT_REF
+         || TREE_CODE (expr) == COMPOUND_EXPR)
+       expr = TREE_OPERAND (expr, 1);
+      error ("cannot apply %<offsetof%> to member function %qD", expr);
       return error_mark_node;
     }
-  return fold_offsetof (expr);
+  return fold_offsetof (expr, NULL_TREE);
 }
 
 /* Called from expand_body via walk_tree.  Replace all AGGR_INIT_EXPRs
@@ -2942,9 +3013,8 @@ simplify_aggr_init_expr (tree *tp)
   tree aggr_init_expr = *tp;
 
   /* Form an appropriate CALL_EXPR.  */
-  tree fn = TREE_OPERAND (aggr_init_expr, 0);
-  tree args = TREE_OPERAND (aggr_init_expr, 1);
-  tree slot = TREE_OPERAND (aggr_init_expr, 2);
+  tree fn = AGGR_INIT_EXPR_FN (aggr_init_expr);
+  tree slot = AGGR_INIT_EXPR_SLOT (aggr_init_expr);
   tree type = TREE_TYPE (slot);
 
   tree call_expr;
@@ -2962,23 +3032,20 @@ simplify_aggr_init_expr (tree *tp)
       style = arg;
     }
 
+  call_expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
+                               fn,
+                               aggr_init_expr_nargs (aggr_init_expr),
+                               AGGR_INIT_EXPR_ARGP (aggr_init_expr));
+
   if (style == ctor)
     {
       /* Replace the first argument to the ctor with the address of the
         slot.  */
-      tree addr;
-
-      args = TREE_CHAIN (args);
       cxx_mark_addressable (slot);
-      addr = build1 (ADDR_EXPR, build_pointer_type (type), slot);
-      args = tree_cons (NULL_TREE, addr, args);
+      CALL_EXPR_ARG (call_expr, 0) =
+       build1 (ADDR_EXPR, build_pointer_type (type), slot);
     }
-
-  call_expr = build3 (CALL_EXPR,
-                     TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
-                     fn, args, NULL_TREE);
-
-  if (style == arg)
+  else if (style == arg)
     {
       /* Just mark it addressable here, and leave the rest to
         expand_call{,_inline}.  */
@@ -3066,7 +3133,7 @@ expand_body (tree fn)
      generating trees for a function.  */
   gcc_assert (function_depth == 0);
 
-  tree_rest_of_compilation (fn);
+  c_expand_body (fn);
 
   current_function_decl = saved_function;
 
@@ -3126,18 +3193,6 @@ expand_or_defer_fn (tree fn)
       return;
     }
 
-  /* If this function is marked with the constructor attribute, add it
-     to the list of functions to be called along with constructors
-     from static duration objects.  */
-  if (DECL_STATIC_CONSTRUCTOR (fn))
-    static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
-
-  /* If this function is marked with the destructor attribute, add it
-     to the list of functions to be called along with destructors from
-     static duration objects.  */
-  if (DECL_STATIC_DESTRUCTOR (fn))
-    static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
-
   /* We make a decision about linkage for these functions at the end
      of the compilation.  Until that point, we do not want the back
      end to output them -- but we do want it to see the bodies of
@@ -3573,7 +3628,8 @@ finish_omp_clauses (tree clauses)
         Save the results, because later we won't be in the right context
         for making these queries.  */
       if (CLASS_TYPE_P (inner_type)
-         && (need_default_ctor || need_copy_ctor || need_copy_assignment))
+         && (need_default_ctor || need_copy_ctor || need_copy_assignment)
+         && !type_dependent_expression_p (t))
        {
          int save_errorcount = errorcount;
          tree info;
@@ -3834,24 +3890,28 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond,
 void
 finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
 {
-  /* If either of the operands are dependent, we can't do semantic
-     processing yet.  Stuff the values away for now.  We cheat a bit
-     and use the same tree code for this, even though the operands
-     are of totally different form, thus we need to remember which
-     statements are which, thus the lang_flag bit.  */
-  /* ??? We ought to be using type_dependent_expression_p, but the
-     invocation of build_modify_expr in c_finish_omp_atomic can result
-     in the creation of CONVERT_EXPRs, which are not handled by
-     tsubst_copy_and_build.  */
-  if (uses_template_parms (lhs) || uses_template_parms (rhs))
-    {
-      tree stmt = build2 (OMP_ATOMIC, void_type_node, lhs, rhs);
-      OMP_ATOMIC_DEPENDENT_P (stmt) = 1;
-      OMP_ATOMIC_CODE (stmt) = code;
-      add_stmt (stmt);
-    }
+  tree stmt;
+
+  if (processing_template_decl
+      && (type_dependent_expression_p (lhs) 
+         || type_dependent_expression_p (rhs)))
+    stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
+                  build2 (code, void_type_node, lhs, rhs));
   else
-    c_finish_omp_atomic (code, lhs, rhs);
+    {
+      /* Even in a template, we can detect invalid uses of the atomic
+         pragma if neither LHS nor RHS is type-dependent.  */
+      if (processing_template_decl)
+       {
+         lhs = build_non_dependent_expr (lhs);
+         rhs = build_non_dependent_expr (rhs);
+       }
+
+      stmt = c_finish_omp_atomic (code, lhs, rhs);
+    }
+    
+  if (stmt != error_mark_node)
+    add_stmt (stmt);
 }
 
 void
@@ -3896,5 +3956,243 @@ void
 init_cp_semantics (void)
 {
 }
+\f
+/* Build a STATIC_ASSERT for a static assertion with the condition
+   CONDITION and the message text MESSAGE.  LOCATION is the location
+   of the static assertion in the source code.  When MEMBER_P, this
+   static assertion is a member of a class.  */
+void 
+finish_static_assert (tree condition, tree message, location_t location, 
+                      bool member_p)
+{
+  if (type_dependent_expression_p (condition) 
+      || value_dependent_expression_p (condition))
+    {
+      /* We're in a template; build a STATIC_ASSERT and put it in
+         the right place. */
+      tree assertion;
+
+      assertion = make_node (STATIC_ASSERT);
+      STATIC_ASSERT_CONDITION (assertion) = condition;
+      STATIC_ASSERT_MESSAGE (assertion) = message;
+      STATIC_ASSERT_SOURCE_LOCATION (assertion) = location;
+
+      if (member_p)
+        maybe_add_class_template_decl_list (current_class_type, 
+                                            assertion,
+                                            /*friend_p=*/0);
+      else
+        add_stmt (assertion);
+
+      return;
+    }
+
+  /* Fold the expression and convert it to a boolean value. */
+  condition = fold_non_dependent_expr (condition);
+  condition = cp_convert (boolean_type_node, condition);
+
+  if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
+    /* Do nothing; the condition is satisfied. */
+    ;
+  else 
+    {
+      location_t saved_loc = input_location;
+
+      input_location = location;
+      if (TREE_CODE (condition) == INTEGER_CST 
+          && integer_zerop (condition))
+        /* Report the error. */
+        error ("static assertion failed: %E", message);
+      else if (condition && condition != error_mark_node)
+        error ("non-constant condition for static assertion");
+      input_location = saved_loc;
+    }
+}
+
+/* Called from trait_expr_value to evaluate either __has_nothrow_assign or 
+   __has_nothrow_copy, depending on assign_p.  */
+
+static bool
+classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p)
+{
+  tree fns;
+
+  if (assign_p)
+    {
+      int ix;
+      ix = lookup_fnfields_1 (type, ansi_assopname (NOP_EXPR));
+      if (ix < 0)
+       return false;
+      fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+    } 
+  else if (TYPE_HAS_INIT_REF (type))
+    {
+      /* If construction of the copy constructor was postponed, create
+        it now.  */
+      if (CLASSTYPE_LAZY_COPY_CTOR (type))
+       lazily_declare_fn (sfk_copy_constructor, type);
+      fns = CLASSTYPE_CONSTRUCTORS (type);
+    }
+  else
+    return false;
+
+  for (; fns; fns = OVL_NEXT (fns))
+    if (!TREE_NOTHROW (OVL_CURRENT (fns)))
+      return false;
+
+  return true;
+}
+
+/* Actually evaluates the trait.  */
+
+static bool
+trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
+{
+  enum tree_code type_code1;
+  tree t;
+
+  type_code1 = TREE_CODE (type1);
+
+  switch (kind)
+    {
+    case CPTK_HAS_NOTHROW_ASSIGN:
+      return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
+             && (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2)
+                 || (CLASS_TYPE_P (type1)
+                     && classtype_has_nothrow_assign_or_copy_p (type1,
+                                                                true))));
+
+    case CPTK_HAS_TRIVIAL_ASSIGN:
+      return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
+             && (pod_type_p (type1)
+                   || (CLASS_TYPE_P (type1)
+                       && TYPE_HAS_TRIVIAL_ASSIGN_REF (type1))));
+
+    case CPTK_HAS_NOTHROW_CONSTRUCTOR:
+      type1 = strip_array_types (type1);
+      return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) 
+             || (CLASS_TYPE_P (type1)
+                 && (t = locate_ctor (type1, NULL)) && TREE_NOTHROW (t)));
+
+    case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
+      type1 = strip_array_types (type1);
+      return (pod_type_p (type1)
+             || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1)));
+
+    case CPTK_HAS_NOTHROW_COPY:
+      return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2)
+             || (CLASS_TYPE_P (type1)
+                 && classtype_has_nothrow_assign_or_copy_p (type1, false)));
+
+    case CPTK_HAS_TRIVIAL_COPY:
+      return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE
+             || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_INIT_REF (type1)));
+
+    case CPTK_HAS_TRIVIAL_DESTRUCTOR:
+      type1 = strip_array_types (type1);
+      return (pod_type_p (type1)
+             || (CLASS_TYPE_P (type1)
+                 && TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
+
+    case CPTK_HAS_VIRTUAL_DESTRUCTOR:
+      return (CLASS_TYPE_P (type1)
+             && (t = locate_dtor (type1, NULL)) && DECL_VIRTUAL_P (t));
+
+    case CPTK_IS_ABSTRACT:
+      return (CLASS_TYPE_P (type1) && CLASSTYPE_PURE_VIRTUALS (type1));
+
+    case CPTK_IS_BASE_OF:
+      return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
+             && DERIVED_FROM_P (type1, type2));
+
+    case CPTK_IS_CLASS:
+      return (NON_UNION_CLASS_TYPE_P (type1));
+
+    case CPTK_IS_CONVERTIBLE_TO:
+      /* TODO  */
+      return false;
+
+    case CPTK_IS_EMPTY:
+      return (NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1));
+
+    case CPTK_IS_ENUM:
+      return (type_code1 == ENUMERAL_TYPE);
+
+    case CPTK_IS_POD:
+      return (pod_type_p (type1));
+
+    case CPTK_IS_POLYMORPHIC:
+      return (CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1));
+
+    case CPTK_IS_UNION:
+      return (type_code1 == UNION_TYPE);
+
+    default:
+      gcc_unreachable ();
+      return false;
+    }
+}
+
+/* Process a trait expression.  */
+
+tree
+finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
+{
+  gcc_assert (kind == CPTK_HAS_NOTHROW_ASSIGN
+             || kind == CPTK_HAS_NOTHROW_CONSTRUCTOR
+             || kind == CPTK_HAS_NOTHROW_COPY
+             || kind == CPTK_HAS_TRIVIAL_ASSIGN
+             || kind == CPTK_HAS_TRIVIAL_CONSTRUCTOR
+             || kind == CPTK_HAS_TRIVIAL_COPY
+             || kind == CPTK_HAS_TRIVIAL_DESTRUCTOR
+             || kind == CPTK_HAS_VIRTUAL_DESTRUCTOR          
+             || kind == CPTK_IS_ABSTRACT
+             || kind == CPTK_IS_BASE_OF
+             || kind == CPTK_IS_CLASS
+             || kind == CPTK_IS_CONVERTIBLE_TO
+             || kind == CPTK_IS_EMPTY
+             || kind == CPTK_IS_ENUM
+             || kind == CPTK_IS_POD
+             || kind == CPTK_IS_POLYMORPHIC
+             || kind == CPTK_IS_UNION);
+
+  if (kind == CPTK_IS_CONVERTIBLE_TO)
+    {
+      sorry ("__is_convertible_to");
+      return error_mark_node;
+    }
+
+  if (type1 == error_mark_node
+      || ((kind == CPTK_IS_BASE_OF || kind == CPTK_IS_CONVERTIBLE_TO)
+         && type2 == error_mark_node))
+    return error_mark_node;
+
+  if (processing_template_decl)
+    {
+      tree trait_expr = make_node (TRAIT_EXPR);
+      TREE_TYPE (trait_expr) = boolean_type_node;
+      TRAIT_EXPR_TYPE1 (trait_expr) = type1;
+      TRAIT_EXPR_TYPE2 (trait_expr) = type2;
+      TRAIT_EXPR_KIND (trait_expr) = kind;
+      return trait_expr;
+    }
+
+  complete_type (type1);
+  if (type2)
+    complete_type (type2);
+
+  /* The only required diagnostic.  */
+  if (kind == CPTK_IS_BASE_OF
+      && NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
+      && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
+      && !COMPLETE_TYPE_P (type2))
+    {
+      error ("incomplete type %qT not allowed", type2);
+      return error_mark_node;
+    }
+
+  return (trait_expr_value (kind, type1, type2)
+         ? boolean_true_node : boolean_false_node);
+}
 
 #include "gt-cp-semantics.h"