OSDN Git Service

2006-08-17 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index a36a631..fb4ea0a 100644 (file)
@@ -1,12 +1,12 @@
 /* Perform the semantic phase of parsing, i.e., the process of
    building tree structure, checking semantic consistency, and
    building RTL.  These routines are used both during actual parsing
-   and during the instantiation of template functions. 
+   and during the instantiation of template functions.
 
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Written by Mark Mitchell (mmitchell@usa.net) based on code found
-   formerly in parse.y and pt.c.  
+   formerly in parse.y and pt.c.
 
    This file is part of GCC.
 
    under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
    any later version.
-   
+
    GCC is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
 /* There routines provide a modular interface to perform many parsing
    operations.  They may therefore be used during actual parsing, or
    during template instantiation, which may be regarded as a
-   degenerate form of parsing.  Since the current g++ parser is
-   lacking in several respects, and will be reimplemented, we are
-   attempting to move most code that is not directly related to
-   parsing into this file; that will make implementing the new parser
-   much easier since it will be able to make use of these routines.  */
+   degenerate form of parsing.  */
 
 static tree maybe_convert_cond (tree);
 static tree simplify_aggr_init_exprs_r (tree *, int *, void *);
@@ -75,9 +71,9 @@ static tree finalize_nrv_r (tree *, int *, void *);
    example:
 
      class A {
-         typedef int X;
+        typedef int X;
        public:
-         X f();
+        X f();
      };
 
      A::X A::f();
@@ -91,7 +87,7 @@ static tree finalize_nrv_r (tree *, int *, void *);
    instantiations.
 
    Typical use of access checking functions is described here:
-   
+
    1. When we enter a context that requires certain access checking
       mode, the function `push_deferring_access_checks' is called with
       DEFERRING argument specifying the desired mode.  Access checking
@@ -121,28 +117,29 @@ typedef struct deferred_access GTY(())
      names used in a decl-specifier-seq until we know what is being
      declared because code like:
 
-       class A { 
-         class B {};
-         B* f();
+       class A {
+        class B {};
+        B* f();
        }
 
        A::B* A::f() { return 0; }
 
-     is valid, even though `A::B' is not generally accessible.  
+     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;
-  
+
   /* The current mode of access checks.  */
   enum deferring_kind deferring_access_checks_kind;
-  
+
 } deferred_access;
-DEF_VEC_GC_O (deferred_access);
+DEF_VEC_O (deferred_access);
+DEF_VEC_ALLOC_O (deferred_access,gc);
 
 /* Data for deferred access checking.  */
-static GTY(()) VEC (deferred_access) *deferred_access_stack;
+static GTY(()) VEC(deferred_access,gc) *deferred_access_stack;
 static GTY(()) unsigned deferred_access_no_check;
 
 /* Save the current deferred access states and start deferred
@@ -159,7 +156,7 @@ push_deferring_access_checks (deferring_kind deferring)
     {
       deferred_access *ptr;
 
-      ptr = VEC_safe_push (deferred_access, deferred_access_stack, NULL);
+      ptr = VEC_safe_push (deferred_access, gc, deferred_access_stack, NULL);
       ptr->deferred_access_checks = NULL_TREE;
       ptr->deferring_access_checks_kind = deferring;
     }
@@ -198,8 +195,8 @@ pop_deferring_access_checks (void)
     VEC_pop (deferred_access, deferred_access_stack);
 }
 
-/* Returns a TREE_LIST representing the deferred checks.  
-   The TREE_PURPOSE of each node is the type through which the 
+/* Returns a TREE_LIST representing the deferred checks.
+   The TREE_PURPOSE of each node is the type through which the
    access occurred; the TREE_VALUE is the declaration named.
    */
 
@@ -235,8 +232,8 @@ 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), 
+         for (; checks; checks = TREE_CHAIN (checks))
+           enforce_access (TREE_PURPOSE (checks),
                            TREE_VALUE (checks));
        }
       else
@@ -244,11 +241,11 @@ pop_to_parent_deferring_access_checks (void)
          /* Merge with parent.  */
          tree next;
          tree original = ptr->deferred_access_checks;
-         
+
          for (; checks; checks = next)
            {
              tree probe;
-             
+
              next = TREE_CHAIN (checks);
 
              for (probe = original; probe; probe = TREE_CHAIN (probe))
@@ -264,6 +261,21 @@ pop_to_parent_deferring_access_checks (void)
     }
 }
 
+/* Perform the access checks in CHECKS.  The TREE_PURPOSE of each node
+   is the BINFO indicating the qualifying scope used to access the
+   DECL node stored in the TREE_VALUE of the node.  */
+
+void
+perform_access_checks (tree checks)
+{
+  while (checks)
+    {
+      enforce_access (TREE_PURPOSE (checks),
+                     TREE_VALUE (checks));
+      checks = TREE_CHAIN (checks);
+    }
+}
+
 /* Perform the deferred access checks.
 
    After performing the checks, we still have to keep the list
@@ -283,15 +295,7 @@ pop_to_parent_deferring_access_checks (void)
 void
 perform_deferred_access_checks (void)
 {
-  tree deferred_check;
-
-  for (deferred_check = (VEC_last (deferred_access, deferred_access_stack)
-                        ->deferred_access_checks);
-       deferred_check;
-       deferred_check = TREE_CHAIN (deferred_check))
-    /* Check access.  */
-    enforce_access (TREE_PURPOSE (deferred_check), 
-                   TREE_VALUE (deferred_check));
+  perform_access_checks (get_deferred_access_checks ());
 }
 
 /* Defer checking the accessibility of DECL, when looked up in
@@ -307,18 +311,18 @@ perform_or_defer_access_check (tree binfo, tree decl)
      */
   if (deferred_access_no_check)
     return;
-  
+
   gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
 
   ptr = VEC_last (deferred_access, deferred_access_stack);
-  
+
   /* 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);
       return;
     }
-  
+
   /* See if we are already going to perform this check.  */
   for (check = ptr->deferred_access_checks;
        check;
@@ -340,6 +344,32 @@ stmts_are_full_exprs_p (void)
   return current_stmt_tree ()->stmts_are_full_exprs_p;
 }
 
+/* T is a statement.  Add it to the statement-tree.  This is the C++
+   version.  The C/ObjC frontends have a slightly different version of
+   this function.  */
+
+tree
+add_stmt (tree t)
+{
+  enum tree_code code = TREE_CODE (t);
+
+  if (EXPR_P (t) && code != LABEL_EXPR)
+    {
+      if (!EXPR_HAS_LOCATION (t))
+       SET_EXPR_LOCATION (t, input_location);
+
+      /* When we expand a statement-tree, we must know whether or not the
+        statements are full-expressions.  We record that fact here.  */
+      STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
+    }
+
+  /* Add T to the statement-tree.  Non-side-effect statements need to be
+     recorded during statement expressions.  */
+  append_to_statement_list_force (t, &cur_stmt_list);
+
+  return t;
+}
+
 /* Returns the stmt_tree (if any) to which statements are currently
    being added.  If there is no active statement-tree, NULL is
    returned.  */
@@ -347,8 +377,8 @@ stmts_are_full_exprs_p (void)
 stmt_tree
 current_stmt_tree (void)
 {
-  return (cfun 
-         ? &cfun->language->base.x_stmt_tree 
+  return (cfun
+         ? &cfun->language->base.x_stmt_tree
          : &scope_chain->x_stmt_tree);
 }
 
@@ -410,7 +440,7 @@ do_poplevel (tree stmt_list)
     block = poplevel (kept_level_p (), 1, 0);
 
   stmt_list = pop_stmt_list (stmt_list);
-  
+
   if (!processing_template_decl)
     {
       stmt_list = c_build_bind_expr (block, stmt_list);
@@ -420,7 +450,7 @@ do_poplevel (tree stmt_list)
   return stmt_list;
 }
 
-/* Begin a new scope.  */ 
+/* Begin a new scope.  */
 
 static tree
 do_pushlevel (scope_kind sk)
@@ -472,14 +502,14 @@ finish_cond (tree *cond_p, tree expr)
 
 /* If *COND_P specifies a conditional with a declaration, transform the
    loop such that
-            while (A x = 42) { }
-            for (; A x = 42;) { }
+           while (A x = 42) { }
+           for (; A x = 42;) { }
    becomes
-            while (true) { A x = 42; if (!x) break; }
-            for (;;) { A x = 42; if (!x) break; }
+           while (true) { A x = 42; if (!x) break; }
+           for (;;) { A x = 42; if (!x) break; }
    The statement list for BODY will be empty if the conditional did
    not declare anything.  */
-                                                                                
+
 static void
 simplify_loop_decl_cond (tree *cond_p, tree body)
 {
@@ -490,7 +520,7 @@ simplify_loop_decl_cond (tree *cond_p, tree body)
 
   cond = *cond_p;
   *cond_p = boolean_true_node;
-   
+
   if_stmt = begin_if_stmt ();
   cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
   finish_if_stmt_cond (cond, if_stmt);
@@ -522,7 +552,7 @@ finish_goto_stmt (tree destination)
         addresses, or some such.  */
       DECL_UNINLINABLE (current_function_decl) = 1;
     }
-  
+
   check_goto (destination);
 
   return add_stmt (build_stmt (GOTO_EXPR, destination));
@@ -600,7 +630,7 @@ begin_if_stmt (void)
 /* Process the COND of an if-statement, which may be given by
    IF_STMT.  */
 
-void 
+void
 finish_if_stmt_cond (tree cond, tree if_stmt)
 {
   finish_cond (&IF_COND (if_stmt), maybe_convert_cond (cond));
@@ -637,13 +667,14 @@ finish_else_clause (tree if_stmt)
 
 /* Finish an if-statement.  */
 
-void 
+void
 finish_if_stmt (tree if_stmt)
 {
   tree scope = TREE_CHAIN (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));
 }
 
 /* Begin a while-statement.  Returns a newly created WHILE_STMT if
@@ -663,7 +694,7 @@ begin_while_stmt (void)
 /* Process the COND of a while-statement, which may be given by
    WHILE_STMT.  */
 
-void 
+void
 finish_while_stmt_cond (tree cond, tree while_stmt)
 {
   finish_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond));
@@ -672,7 +703,7 @@ finish_while_stmt_cond (tree cond, tree while_stmt)
 
 /* Finish a while-statement, which may be given by WHILE_STMT.  */
 
-void 
+void
 finish_while_stmt (tree while_stmt)
 {
   WHILE_BODY (while_stmt) = do_poplevel (WHILE_BODY (while_stmt));
@@ -717,12 +748,16 @@ tree
 finish_return_stmt (tree expr)
 {
   tree r;
+  bool no_warning;
 
-  expr = check_return_expr (expr);
+  expr = check_return_expr (expr, &no_warning);
+
+  if (flag_openmp && !check_omp_return ())
+    return error_mark_node;
   if (!processing_template_decl)
     {
       if (DECL_DESTRUCTOR_P (current_function_decl)
-         || (DECL_CONSTRUCTOR_P (current_function_decl) 
+         || (DECL_CONSTRUCTOR_P (current_function_decl)
              && targetm.cxx.cdtor_returns_this ()))
        {
          /* Similarly, all destructors must run destructors for
@@ -734,6 +769,7 @@ finish_return_stmt (tree expr)
     }
 
   r = build_stmt (RETURN_EXPR, expr);
+  TREE_NO_WARNING (r) |= no_warning;
   r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
   finish_stmt ();
@@ -748,7 +784,7 @@ begin_for_stmt (void)
 {
   tree r;
 
-  r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, 
+  r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
                  NULL_TREE, NULL_TREE);
 
   if (flag_new_for_scope > 0)
@@ -801,7 +837,7 @@ finish_for_expr (tree expr, tree for_stmt)
   if (!processing_template_decl)
     {
       if (warn_sequence_point)
-        verify_sequence_points (expr);
+       verify_sequence_points (expr);
       expr = convert_to_void (expr, "3rd expression in for");
     }
   else if (!type_dependent_expression_p (expr))
@@ -827,7 +863,7 @@ finish_for_stmt (tree for_stmt)
       add_stmt (do_poplevel (scope));
     }
 
-  finish_stmt (); 
+  finish_stmt ();
 }
 
 /* Finish a break-statement.  */
@@ -835,7 +871,7 @@ finish_for_stmt (tree for_stmt)
 tree
 finish_break_stmt (void)
 {
-  return add_stmt (build_break_stmt ());
+  return add_stmt (build_stmt (BREAK_STMT));
 }
 
 /* Finish a continue-statement.  */
@@ -843,7 +879,7 @@ finish_break_stmt (void)
 tree
 finish_continue_stmt (void)
 {
-  return add_stmt (build_continue_stmt ());
+  return add_stmt (build_stmt (CONTINUE_STMT));
 }
 
 /* Begin a switch-statement.  Returns a new SWITCH_STMT if
@@ -858,7 +894,7 @@ begin_switch_stmt (void)
 
   scope = do_pushlevel (sk_block);
   TREE_CHAIN (r) = scope;
-  begin_cond (&SWITCH_COND (r));
+  begin_cond (&SWITCH_STMT_COND (r));
 
   return r;
 }
@@ -902,11 +938,11 @@ finish_switch_cond (tree cond, tree switch_stmt)
            cond = index;
        }
     }
-  finish_cond (&SWITCH_COND (switch_stmt), cond);
-  SWITCH_TYPE (switch_stmt) = orig_type;
+  finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
+  SWITCH_STMT_TYPE (switch_stmt) = orig_type;
   add_stmt (switch_stmt);
   push_switch (switch_stmt);
-  SWITCH_BODY (switch_stmt) = push_stmt_list ();
+  SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
 }
 
 /* Finish the body of a switch-statement, which may be given by
@@ -917,8 +953,9 @@ finish_switch_stmt (tree switch_stmt)
 {
   tree scope;
 
-  SWITCH_BODY (switch_stmt) = pop_stmt_list (SWITCH_BODY (switch_stmt));
-  pop_switch (); 
+  SWITCH_STMT_BODY (switch_stmt) =
+    pop_stmt_list (SWITCH_STMT_BODY (switch_stmt));
+  pop_switch ();
   finish_stmt ();
 
   scope = TREE_CHAIN (switch_stmt);
@@ -938,12 +975,18 @@ begin_try_block (void)
   return r;
 }
 
-/* Likewise, for a function-try-block.  */
+/* Likewise, for a function-try-block.  The block returned in
+   *COMPOUND_STMT is an artificial outer scope, containing the
+   function-try-block.  */
 
 tree
-begin_function_try_block (void)
+begin_function_try_block (tree *compound_stmt)
 {
-  tree r = begin_try_block ();
+  tree r;
+  /* This outer scope does not exist in the C++ standard, but we need
+     a place to put __FUNCTION__ and similar variables.  */
+  *compound_stmt = begin_compound_stmt (0);
+  r = begin_try_block ();
   FN_TRY_BLOCK_P (r) = 1;
   return r;
 }
@@ -997,13 +1040,16 @@ finish_handler_sequence (tree try_block)
   check_handlers (TRY_HANDLERS (try_block));
 }
 
-/* Likewise, for a function-try-block.  */
+/* Finish the handler-seq for a function-try-block, given by
+   TRY_BLOCK.  COMPOUND_STMT is the outer block created by
+   begin_function_try_block.  */
 
 void
-finish_function_handler_sequence (tree try_block)
+finish_function_handler_sequence (tree try_block, tree compound_stmt)
 {
   in_function_try_handler = 0;
   finish_handler_sequence (try_block);
+  finish_compound_stmt (compound_stmt);
 }
 
 /* Begin a handler.  Returns a HANDLER if appropriate.  */
@@ -1043,7 +1089,6 @@ finish_handler_parms (tree decl, tree handler)
     }
   else
     type = expand_start_catch_block (decl);
-
   HANDLER_TYPE (handler) = type;
   if (!processing_template_decl && type)
     mark_used (eh_type_info (type));
@@ -1063,7 +1108,7 @@ finish_handler (tree handler)
 /* Begin a compound statement.  FLAGS contains some bits that control the
    behavior and context.  If BCS_NO_SCOPE is set, the compound statement
    does not define a scope.  If BCS_FN_BODY is set, this is the outermost
-   block of a function.  If BCS_TRY_BLOCK is set, this is the block 
+   block of a function.  If BCS_TRY_BLOCK is set, this is the block
    created on behalf of a TRY statement.  Returns a token to be passed to
    finish_compound_stmt.  */
 
@@ -1080,7 +1125,7 @@ begin_compound_stmt (unsigned int flags)
       /* Normally, we try hard to keep the BLOCK for a statement-expression.
         But, if it's a statement-expression with a scopeless block, there's
         nothing to keep, and we don't want to accidentally keep a block
-        *inside* the scopeless block.  */ 
+        *inside* the scopeless block.  */
       keep_next_level (false);
     }
   else
@@ -1136,72 +1181,108 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
 {
   tree r;
   tree t;
+  int ninputs = list_length (input_operands);
+  int noutputs = list_length (output_operands);
 
   if (!processing_template_decl)
     {
+      const char *constraint;
+      const char **oconstraints;
+      bool allows_mem, allows_reg, is_inout;
+      tree operand;
       int i;
-      int ninputs;
-      int noutputs;
 
-      for (t = input_operands; t; t = TREE_CHAIN (t))
+      oconstraints = (const char **) alloca (noutputs * sizeof (char *));
+
+      string = resolve_asm_operand_names (string, output_operands,
+                                         input_operands);
+
+      for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i)
        {
-         tree converted_operand 
-           = decay_conversion (TREE_VALUE (t)); 
-         
-         /* If the type of the operand hasn't been determined (e.g.,
-            because it involves an overloaded function), then issue
-            an error message.  There's no context available to
-            resolve the overloading.  */
-         if (TREE_TYPE (converted_operand) == unknown_type_node)
+         operand = TREE_VALUE (t);
+
+         /* ??? Really, this should not be here.  Users should be using a
+            proper lvalue, dammit.  But there's a long history of using
+            casts in the output operands.  In cases like longlong.h, this
+            becomes a primitive form of typechecking -- if the cast can be
+            removed, then the output operand had a type of the proper width;
+            otherwise we'll get an error.  Gross, but ...  */
+         STRIP_NOPS (operand);
+
+         if (!lvalue_or_else (operand, lv_asm))
+           operand = error_mark_node;
+
+         if (operand != error_mark_node
+             && (TREE_READONLY (operand)
+                 || CP_TYPE_CONST_P (TREE_TYPE (operand))
+                 /* Functions are not modifiable, even though they are
+                    lvalues.  */
+                 || TREE_CODE (TREE_TYPE (operand)) == FUNCTION_TYPE
+                 || TREE_CODE (TREE_TYPE (operand)) == METHOD_TYPE
+                 /* If it's an aggregate and any field is const, then it is
+                    effectively const.  */
+                 || (CLASS_TYPE_P (TREE_TYPE (operand))
+                     && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
+           readonly_error (operand, "assignment (via 'asm' output)", 0);
+
+         constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
+         oconstraints[i] = constraint;
+
+         if (parse_output_constraint (&constraint, i, ninputs, noutputs,
+                                      &allows_mem, &allows_reg, &is_inout))
            {
-             error ("type of asm operand %qE could not be determined", 
-                     TREE_VALUE (t));
-             converted_operand = error_mark_node;
+             /* If the operand is going to end up in memory,
+                mark it addressable.  */
+             if (!allows_reg && !cxx_mark_addressable (operand))
+               operand = error_mark_node;
            }
-         TREE_VALUE (t) = converted_operand;
-       }
+         else
+           operand = error_mark_node;
 
-      ninputs = list_length (input_operands);
-      noutputs = list_length (output_operands);
+         TREE_VALUE (t) = operand;
+       }
 
-      for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i)
+      for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t))
        {
-         bool allows_mem;
-         bool allows_reg;
-         bool is_inout;
-         const char *constraint;
-         tree operand;
-
          constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
-         operand = TREE_VALUE (t);
+         operand = decay_conversion (TREE_VALUE (t));
+
+         /* If the type of the operand hasn't been determined (e.g.,
+            because it involves an overloaded function), then issue
+            an error message.  There's no context available to
+            resolve the overloading.  */
+         if (TREE_TYPE (operand) == unknown_type_node)
+           {
+             error ("type of asm operand %qE could not be determined",
+                    TREE_VALUE (t));
+             operand = error_mark_node;
+           }
 
-         if (!parse_output_constraint (&constraint,
-                                       i, ninputs, noutputs,
-                                       &allows_mem,
-                                       &allows_reg,
-                                       &is_inout))
+         if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
+                                     oconstraints, &allows_mem, &allows_reg))
            {
-             /* By marking this operand as erroneous, we will not try
-                to process this operand again in expand_asm_operands.  */
-             TREE_VALUE (t) = error_mark_node;
-             continue;
+             /* If the operand is going to end up in memory,
+                mark it addressable.  */
+             if (!allows_reg && allows_mem)
+               {
+                 /* Strip the nops as we allow this case.  FIXME, this really
+                    should be rejected or made deprecated.  */
+                 STRIP_NOPS (operand);
+                 if (!cxx_mark_addressable (operand))
+                   operand = error_mark_node;
+               }
            }
+         else
+           operand = error_mark_node;
 
-         /* If the operand is a DECL that is going to end up in
-            memory, assume it is addressable.  This is a bit more
-            conservative than it would ideally be; the exact test is
-            buried deep in expand_asm_operands and depends on the
-            DECL_RTL for the OPERAND -- which we don't have at this
-            point.  */
-         if (!allows_reg && DECL_P (operand))
-           cxx_mark_addressable (operand);
+         TREE_VALUE (t) = operand;
        }
     }
 
   r = build_stmt (ASM_EXPR, string,
                  output_operands, input_operands,
                  clobbers);
-  ASM_VOLATILE_P (r) = volatile_p;
+  ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
   r = maybe_cleanup_point_expr_void (r);
   return add_stmt (r);
 }
@@ -1212,6 +1293,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));
 }
 
@@ -1228,7 +1313,7 @@ finish_label_decl (tree name)
 
 /* When DECL goes out of scope, make sure that CLEANUP is executed.  */
 
-void 
+void
 finish_decl_cleanup (tree decl, tree cleanup)
 {
   push_cleanup (decl, cleanup, false);
@@ -1272,6 +1357,10 @@ finish_parenthesized_expr (tree expr)
     /* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be
        enclosed in parentheses.  */
     PTRMEM_OK_P (expr) = 0;
+
+  if (TREE_CODE (expr) == STRING_CST)
+    PAREN_STRING_LITERAL_P (expr) = 1;
+
   return expr;
 }
 
@@ -1285,12 +1374,11 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 
   if (!object)
     {
-      if (current_function_decl 
+      if (current_function_decl
          && DECL_STATIC_FUNCTION_P (current_function_decl))
-       cp_error_at ("invalid use of member %qD in static member function",
-                    decl);
+       error ("invalid use of member %q+D in static member function", decl);
       else
-       cp_error_at ("invalid use of non-static data member %qD", decl);
+       error ("invalid use of non-static data member %q+D", decl);
       error ("from this location");
 
       return error_mark_node;
@@ -1306,21 +1394,21 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
        {
          /* Set the cv qualifiers.  */
          int quals = cp_type_quals (TREE_TYPE (current_class_ref));
-         
+
          if (DECL_MUTABLE_P (decl))
            quals &= ~TYPE_QUAL_CONST;
 
          quals |= cp_type_quals (TREE_TYPE (decl));
          type = cp_build_qualified_type (type, quals);
        }
-      
+
       return build_min (COMPONENT_REF, type, object, decl, NULL_TREE);
     }
   else
     {
       tree access_type = TREE_TYPE (object);
       tree lookup_context = context_for_name_lookup (decl);
-      
+
       while (!DERIVED_FROM_P (lookup_context, access_type))
        {
          access_type = TYPE_CONTEXT (access_type);
@@ -1329,7 +1417,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 
          if (!access_type)
            {
-             cp_error_at ("object missing in reference to %qD", decl);
+             error ("object missing in reference to %q+D", decl);
              error ("from this location");
              return error_mark_node;
            }
@@ -1339,8 +1427,10 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
         QUALIFYING_SCOPE is also non-null.  Wrap this in a SCOPE_REF
         for now.  */
       if (processing_template_decl)
-       return build_min (SCOPE_REF, TREE_TYPE (decl),
-                         qualifying_scope, DECL_NAME (decl));
+       return build_qualified_name (TREE_TYPE (decl),
+                                    qualifying_scope,
+                                    DECL_NAME (decl),
+                                    /*template_p=*/false);
 
       perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
 
@@ -1366,8 +1456,8 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
    `A::B' then NESTED_NAME_SPECIFIER is `A'.  */
 
 void
-check_accessibility_of_qualified_id (tree decl, 
-                                    tree object_type, 
+check_accessibility_of_qualified_id (tree decl,
+                                    tree object_type,
                                     tree nested_name_specifier)
 {
   tree scope;
@@ -1376,21 +1466,21 @@ check_accessibility_of_qualified_id (tree decl,
   /* If we're not checking, return immediately.  */
   if (deferred_access_no_check)
     return;
-  
+
   /* Determine the SCOPE of DECL.  */
   scope = context_for_name_lookup (decl);
   /* If the SCOPE is not a type, then DECL is not a member.  */
   if (!TYPE_P (scope))
     return;
   /* Compute the scope through which DECL is being accessed.  */
-  if (object_type 
+  if (object_type
       /* OBJECT_TYPE might not be a class type; consider:
 
           class A { typedef int I; };
           I *p;
           p->A::I::~I();
 
-         In this case, we will have "A::I" as the DECL, but "I" as the
+        In this case, we will have "A::I" as the DECL, but "I" as the
         OBJECT_TYPE.  */
       && CLASS_TYPE_P (object_type)
       && DERIVED_FROM_P (scope, object_type))
@@ -1416,9 +1506,11 @@ 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.  */
+  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);
 }
 
@@ -1426,27 +1518,47 @@ check_accessibility_of_qualified_id (tree decl,
    class named to the left of the "::" operator.  DONE is true if this
    expression is a complete postfix-expression; it is false if this
    expression is followed by '->', '[', '(', etc.  ADDRESS_P is true
-   iff this expression is the operand of '&'.  */
+   iff this expression is the operand of '&'.  TEMPLATE_P is true iff
+   the qualified-id was of the form "A::template B".  TEMPLATE_ARG_P
+   is true iff this qualified name appears as a template argument.  */
 
 tree
-finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
-                         bool address_p)
+finish_qualified_id_expr (tree qualifying_class,
+                         tree expr,
+                         bool done,
+                         bool address_p,
+                         bool template_p,
+                         bool template_arg_p)
 {
+  gcc_assert (TYPE_P (qualifying_class));
+
   if (error_operand_p (expr))
     return error_mark_node;
 
+  if (DECL_P (expr) || BASELINK_P (expr))
+    mark_used (expr);
+
+  if (template_p)
+    check_template_keyword (expr);
+
   /* If EXPR occurs as the operand of '&', use special handling that
      permits a pointer-to-member.  */
   if (address_p && done)
     {
       if (TREE_CODE (expr) == SCOPE_REF)
        expr = TREE_OPERAND (expr, 1);
-      expr = build_offset_ref (qualifying_class, expr, 
+      expr = build_offset_ref (qualifying_class, expr,
                               /*address_p=*/true);
       return expr;
     }
 
-  if (TREE_CODE (expr) == FIELD_DECL)
+  /* Within the scope of a class, turn references to non-static
+     members into expression of the form "this->...".  */
+  if (template_arg_p)
+    /* But, within a template argument, we do not want make the
+       transformation, as there is no "this" pointer.  */
+    ;
+  else if (TREE_CODE (expr) == FIELD_DECL)
     expr = finish_non_static_data_member (expr, current_class_ref,
                                          qualifying_class);
   else if (BASELINK_P (expr) && !processing_template_decl)
@@ -1460,9 +1572,9 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
       /* If so, the expression may be relative to the current
         class.  */
       if (!shared_member_p (fns)
-         && current_class_type 
+         && current_class_type
          && DERIVED_FROM_P (qualifying_class, current_class_type))
-       expr = (build_class_member_access_expr 
+       expr = (build_class_member_access_expr
                (maybe_dummy_object (qualifying_class, NULL),
                 expr,
                 BASELINK_ACCESS_BINFO (expr),
@@ -1479,124 +1591,111 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
 /* Begin a statement-expression.  The value returned must be passed to
    finish_stmt_expr.  */
 
-tree 
+tree
 begin_stmt_expr (void)
 {
   return push_stmt_list ();
 }
 
 /* Process the final expression of a statement expression. EXPR can be
-   NULL, if the final expression is empty.  Build up a TARGET_EXPR so
-   that the result value can be safely returned to the enclosing
-   expression.  */
+   NULL, if the final expression is empty.  Return a STATEMENT_LIST
+   containing all the statements in the statement-expression, or
+   ERROR_MARK_NODE if there was an error.  */
 
 tree
 finish_stmt_expr_expr (tree expr, tree stmt_expr)
 {
-  tree result = NULL_TREE;
+  if (error_operand_p (expr))
+    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)
     {
-      if (!processing_template_decl && !VOID_TYPE_P (TREE_TYPE (expr)))
+      tree type;
+      type = TREE_TYPE (expr);
+      if (!dependent_type_p (type) && !VOID_TYPE_P (type))
        {
-         tree type = TREE_TYPE (expr);
-
-         if (TREE_CODE (type) == ARRAY_TYPE
-             || TREE_CODE (type) == FUNCTION_TYPE)
-           expr = decay_conversion (expr);
-
-         expr = convert_from_reference (expr);
-         expr = require_complete_type (expr);
-
+         expr = decay_conversion (expr);
+         if (error_operand_p (expr))
+           return error_mark_node;
          type = TREE_TYPE (expr);
-
-         /* Build a TARGET_EXPR for this aggregate.  finish_stmt_expr
-            will then pull it apart so the lifetime of the target is
-            within the scope of the expression containing this statement
-            expression.  */
-         if (TREE_CODE (expr) == TARGET_EXPR)
-           ;
-         else if (!IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_INIT_REF (type))
-           expr = build_target_expr_with_type (expr, type);
+       }
+      /* 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
            {
-             /* Copy construct.  */
-             expr = build_special_member_call
-               (NULL_TREE, complete_ctor_identifier,
-                build_tree_list (NULL_TREE, expr),
-                type, LOOKUP_NORMAL);
-             expr = build_cplus_new (type, expr);
-             gcc_assert (TREE_CODE (expr) == TARGET_EXPR);
+             /* 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);
            }
-       }
-
-      if (expr != error_mark_node)
-       {
-         result = build_stmt (EXPR_STMT, expr);
-         EXPR_STMT_STMT_EXPR_RESULT (result) = 1;
-         add_stmt (result);
+         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;
        }
     }
-  
-  finish_stmt ();
 
-  /* Remember the last expression so that finish_stmt_expr
-     can pull it apart.  */
-  TREE_TYPE (stmt_expr) = result;
-  
-  return result;
+  /* 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;
 }
 
 /* Finish a statement-expression.  EXPR should be the value returned
    by the previous begin_stmt_expr.  Returns an expression
    representing the statement-expression.  */
 
-tree 
+tree
 finish_stmt_expr (tree stmt_expr, bool has_no_scope)
 {
-  tree result, result_stmt, type;
-  tree *result_stmt_p = NULL;
+  tree type;
+  tree result;
 
-  result_stmt = TREE_TYPE (stmt_expr);
-  TREE_TYPE (stmt_expr) = void_type_node;
-  result = pop_stmt_list (stmt_expr);
+  if (error_operand_p (stmt_expr))
+    return error_mark_node;
 
-  if (!result_stmt || VOID_TYPE_P (result_stmt))
-    type = void_type_node;
-  else
-    {
-      /* We need to search the statement expression for the result_stmt,
-        since we'll need to replace it entirely.  */
-      tree t;
-      result_stmt_p = &result;
-      while (1)
-       {
-         t = *result_stmt_p;
-         if (t == result_stmt)
-           break;
+  gcc_assert (TREE_CODE (stmt_expr) == STATEMENT_LIST);
 
-         switch (TREE_CODE (t))
-           {
-           case STATEMENT_LIST:
-             {
-               tree_stmt_iterator i = tsi_last (t);
-               result_stmt_p = tsi_stmt_ptr (i);
-               break;
-             }
-           case BIND_EXPR:
-             result_stmt_p = &BIND_EXPR_BODY (t);
-             break;
-           case TRY_FINALLY_EXPR:
-           case TRY_CATCH_EXPR:
-           case CLEANUP_STMT:
-             result_stmt_p = &TREE_OPERAND (t, 0);
-             break;
-           default:
-             gcc_unreachable ();
-           }
-       }
-      type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt));
-    }
+  type = TREE_TYPE (stmt_expr);
+  result = pop_stmt_list (stmt_expr);
 
   if (processing_template_decl)
     {
@@ -1604,43 +1703,12 @@ 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 (!VOID_TYPE_P (type))
+  else if (!TYPE_P (type))
     {
-      /* Pull out the TARGET_EXPR that is the final expression. Put
-        the target's init_expr as the final expression and then put
-        the statement expression itself as the target's init
-        expr. Finally, return the target expression.  */
-      tree init, target_expr = EXPR_STMT_EXPR (result_stmt);
-      gcc_assert (TREE_CODE (target_expr) == TARGET_EXPR);
-
-      /* The initializer will be void if the initialization is done by
-        AGGR_INIT_EXPR; propagate that out to the statement-expression as
-        a whole.  */
-      init = TREE_OPERAND (target_expr, 1);
-      type = TREE_TYPE (init);
-
-      init = maybe_cleanup_point_expr (init);
-      *result_stmt_p = init;
-
-      if (VOID_TYPE_P (type))
-       /* No frobbing needed.  */;
-      else if (TREE_CODE (result) == BIND_EXPR)
-       {
-         /* The BIND_EXPR created in finish_compound_stmt is void; if we're
-            returning a value directly, give it the appropriate type.  */
-         if (VOID_TYPE_P (TREE_TYPE (result)))
-           TREE_TYPE (result) = type;
-         else
-           gcc_assert (same_type_p (TREE_TYPE (result), type));
-       }
-      else if (TREE_CODE (result) == STATEMENT_LIST)
-       /* We need to wrap a STATEMENT_LIST in a BIND_EXPR so it can have a
-          type other than void.  FIXME why can't we just return a value
-          from STATEMENT_LIST?  */
-       result = build3 (BIND_EXPR, type, NULL, result, NULL);
-
-      TREE_OPERAND (target_expr, 1) = result;
-      result = target_expr;
+      gcc_assert (TREE_CODE (type) == TARGET_EXPR);
+      TARGET_EXPR_INITIAL (type) = result;
+      TREE_TYPE (result) = void_type_node;
+      result = type;
     }
 
   return result;
@@ -1682,8 +1750,6 @@ perform_koenig_lookup (tree fn, tree args)
        /* The unqualified name could not be resolved.  */
        fn = unqualified_fn_lookup_error (identifier);
     }
-  else
-    fn = identifier;
 
   return fn;
 }
@@ -1698,7 +1764,7 @@ perform_koenig_lookup (tree fn, tree args)
 
    Returns code for the call.  */
 
-tree 
+tree
 finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 {
   tree result;
@@ -1763,18 +1829,18 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
           function call is transformed into a qualified function call
           using (*this) as the postfix-expression to the left of the
           . operator.... [Otherwise] a contrived object of type T
-          becomes the implied object argument.  
+          becomes the implied object argument.
 
-        This paragraph is unclear about this situation:
+       This paragraph is unclear about this situation:
 
          struct A { void f(); };
          struct B : public A {};
          struct C : public A { void g() { B::f(); }};
 
        In particular, for `B::f', this paragraph does not make clear
-       whether "the class of that member function" refers to `A' or 
+       whether "the class of that member function" refers to `A' or
        to `B'.  We believe it refers to `B'.  */
-      if (current_class_type 
+      if (current_class_type
          && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
                             current_class_type)
          && current_class_ref)
@@ -1799,12 +1865,22 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
        }
 
       result = build_new_method_call (object, fn, args, NULL_TREE,
-                                     (disallow_virtual 
-                                      ? LOOKUP_NONVIRTUAL : 0));
+                                     (disallow_virtual
+                                      ? LOOKUP_NONVIRTUAL : 0),
+                                     /*fn_p=*/NULL);
     }
   else if (is_overloaded_fn (fn))
-    /* A call to a namespace-scope function.  */
-    result = build_new_function_call (fn, args);
+    {
+      /* If the function is an overloaded builtin, resolve it.  */
+      if (TREE_CODE (fn) == FUNCTION_DECL
+         && (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+             || DECL_BUILT_IN_CLASS (fn) == BUILT_IN_MD))
+       result = resolve_overloaded_builtin (fn, args);
+
+      if (!result)
+       /* A call to a namespace-scope function.  */
+       result = build_new_function_call (fn, args, koenig_p);
+    }
   else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
     {
       if (args)
@@ -1821,6 +1897,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
        have an overloaded `operator ()'.  */
     result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE,
                           /*overloaded_p=*/NULL);
+
   if (!result)
     /* A call where the function is unknown.  */
     result = build_function_call (fn, args);
@@ -1838,15 +1915,15 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
    is indicated by CODE, which should be POSTINCREMENT_EXPR or
    POSTDECREMENT_EXPR.)  */
 
-tree 
+tree
 finish_increment_expr (tree expr, enum tree_code code)
 {
-  return build_x_unary_op (code, expr);  
+  return build_x_unary_op (code, expr);
 }
 
 /* Finish a use of `this'.  Returns an expression for `this'.  */
 
-tree 
+tree
 finish_this_expr (void)
 {
   tree result;
@@ -1878,7 +1955,7 @@ finish_this_expr (void)
    the TYPE for the type given.  If SCOPE is non-NULL, the expression
    was of the form `OBJECT.SCOPE::~DESTRUCTOR'.  */
 
-tree 
+tree
 finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
 {
   if (destructor == error_mark_node)
@@ -1893,21 +1970,21 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
          error ("invalid qualifying scope in pseudo-destructor name");
          return error_mark_node;
        }
-      
+
       /* [expr.pseudo] says both:
 
-           The type designated by the pseudo-destructor-name shall be
+          The type designated by the pseudo-destructor-name shall be
           the same as the object type.
 
-         and:
+        and:
 
-           The cv-unqualified versions of the object type and of the
+          The cv-unqualified versions of the object type and of the
           type designated by the pseudo-destructor-name shall be the
           same type.
 
-         We implement the more generous second sentence, since that is
-         what most other compilers do.  */
-      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object), 
+        We implement the more generous second sentence, since that is
+        what most other compilers do.  */
+      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
                                                      destructor))
        {
          error ("%qE is not of type %qT", object, destructor);
@@ -1931,7 +2008,12 @@ finish_unary_op_expr (enum tree_code code, tree expr)
       && TREE_CODE (result) == INTEGER_CST
       && !TYPE_UNSIGNED (TREE_TYPE (result))
       && INT_CST_LT (result, integer_zero_node))
-    TREE_NEGATED_INT (result) = 1;
+    {
+      /* RESULT may be a cached INTEGER_CST, so we must copy it before
+        setting TREE_NEGATED_INT.  */
+      result = copy_node (result);
+      TREE_NEGATED_INT (result) = 1;
+    }
   overflow_warning (result);
   return result;
 }
@@ -1940,31 +2022,51 @@ finish_unary_op_expr (enum tree_code code, tree expr)
    the INITIALIZER_LIST is being cast.  */
 
 tree
-finish_compound_literal (tree type, tree initializer_list)
+finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
 {
+  tree var;
   tree compound_literal;
 
+  if (!TYPE_OBJ_P (type))
+    {
+      error ("compound literal of non-object type %qT", type);
+      return error_mark_node;
+    }
+
   /* Build a CONSTRUCTOR for the INITIALIZER_LIST.  */
   compound_literal = build_constructor (NULL_TREE, initializer_list);
-  /* Mark it as a compound-literal.  */
-  TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
   if (processing_template_decl)
-    TREE_TYPE (compound_literal) = type;
-  else
     {
-      /* Check the initialization.  */
-      compound_literal = digest_init (type, compound_literal, NULL);
-      /* If the TYPE was an array type with an unknown bound, then we can
-        figure out the dimension now.  For example, something like:
-
-          `(int []) { 2, 3 }'
-
-        implies that the array has two elements.  */
-      if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
-       complete_array_type (type, compound_literal, 1);
-    }
-
-  return compound_literal;
+      TREE_TYPE (compound_literal) = type;
+      /* Mark the expression as a compound literal.  */
+      TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
+      return compound_literal;
+    }
+
+  /* Create a temporary variable to represent the compound literal.  */
+  var = create_temporary_var (type);
+  if (!current_function_decl)
+    {
+      /* If this compound-literal appears outside of a function, then
+        the corresponding variable has static storage duration, just
+        like the variable in whose initializer it appears.  */
+      TREE_STATIC (var) = 1;
+      /* The variable has internal linkage, since there is no need to
+        reference it from another translation unit.  */
+      TREE_PUBLIC (var) = 0;
+      /* It must have a name, so that the name mangler can mangle it.  */
+      DECL_NAME (var) = make_anon_name ();
+    }
+  /* We must call pushdecl, since the gimplifier complains if the
+     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.  */
+  cp_finish_decl (var, compound_literal,
+                 /*init_const_expr_p=*/false,
+                 /*asmspec_tree=*/NULL_TREE,
+                 LOOKUP_ONLYCONVERTING);
+  return var;
 }
 
 /* Return the declaration for the function-name variable indicated by
@@ -1974,7 +2076,7 @@ tree
 finish_fname (tree id)
 {
   tree decl;
-  
+
   decl = fname_decl (C_RID_CODE (id), id);
   if (processing_template_decl)
     decl = DECL_NAME (decl);
@@ -1983,7 +2085,7 @@ finish_fname (tree id)
 
 /* Finish a translation unit.  */
 
-void 
+void
 finish_translation_unit (void)
 {
   /* In case there were missing closebraces,
@@ -1999,7 +2101,7 @@ finish_translation_unit (void)
 /* Finish a template type parameter, specified as AGGR IDENTIFIER.
    Returns the parameter.  */
 
-tree 
+tree
 finish_template_type_parm (tree aggr, tree identifier)
 {
   if (aggr != class_type_node)
@@ -2014,7 +2116,7 @@ finish_template_type_parm (tree aggr, tree identifier)
 /* Finish a template template parameter, specified as AGGR IDENTIFIER.
    Returns the parameter.  */
 
-tree 
+tree
 finish_template_template_parm (tree aggr, tree identifier)
 {
   tree decl = build_decl (TYPE_DECL, identifier, NULL_TREE);
@@ -2041,19 +2143,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;
@@ -2065,7 +2156,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;
@@ -2078,7 +2169,7 @@ begin_class_definition (tree t)
   /* A non-implicit typename comes from code like:
 
        template <typename T> struct A {
-         template <typename U> struct A<T>::B ...
+        template <typename U> struct A<T>::B ...
 
      This is erroneous.  */
   else if (TREE_CODE (t) == TYPENAME_TYPE)
@@ -2090,29 +2181,23 @@ begin_class_definition (tree t)
   if (t == error_mark_node || ! IS_AGGR_TYPE (t))
     {
       t = make_aggr_type (RECORD_TYPE);
-      pushtag (make_anon_name (), t, 0);
-    }
-
-  /* If this type was already complete, and we see another definition,
-     that's an error.  */
-  if (COMPLETE_TYPE_P (t))
-    {
-      error ("redefinition of %q#T", t);
-      cp_error_at ("previous definition of %q#T", t);
-      return error_mark_node;
+      pushtag (make_anon_name (), t, /*tag_scope=*/ts_current);
     }
 
   /* Update the location of the decl.  */
   DECL_SOURCE_LOCATION (TYPE_NAME (t)) = input_location;
-  
+
   if (TYPE_BEING_DEFINED (t))
     {
       t = make_aggr_type (TREE_CODE (t));
-      pushtag (TYPE_IDENTIFIER (t), t, 0);
+      pushtag (TYPE_IDENTIFIER (t), t, /*tag_scope=*/ts_current);
     }
   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;
@@ -2134,7 +2219,7 @@ begin_class_definition (tree t)
        (t, finfo->interface_unknown);
     }
   reset_specialization();
-  
+
   /* Make a declaration for this class in its own scope.  */
   build_self_reference ();
 
@@ -2158,9 +2243,9 @@ finish_member_declaration (tree decl)
   gcc_assert (TREE_CHAIN (decl) == NULL_TREE);
 
   /* Set up access control for DECL.  */
-  TREE_PRIVATE (decl) 
+  TREE_PRIVATE (decl)
     = (current_access_specifier == access_private_node);
-  TREE_PROTECTED (decl) 
+  TREE_PROTECTED (decl)
     = (current_access_specifier == access_protected_node);
   if (TREE_CODE (decl) == TEMPLATE_DECL)
     {
@@ -2181,21 +2266,22 @@ finish_member_declaration (tree decl)
   /* Put functions on the TYPE_METHODS list and everything else on the
      TYPE_FIELDS list.  Note that these are built up in reverse order.
      We reverse them (to obtain declaration order) in finish_struct.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL 
+  if (TREE_CODE (decl) == FUNCTION_DECL
       || DECL_FUNCTION_TEMPLATE_P (decl))
     {
       /* We also need to add this function to the
         CLASSTYPE_METHOD_VEC.  */
-      add_method (current_class_type, decl);
-
-      TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
-      TYPE_METHODS (current_class_type) = decl;
+      if (add_method (current_class_type, decl, NULL_TREE))
+       {
+         TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
+         TYPE_METHODS (current_class_type) = decl;
 
-      maybe_add_class_template_decl_list (current_class_type, decl, 
-                                         /*friend_p=*/0);
+         maybe_add_class_template_decl_list (current_class_type, decl,
+                                             /*friend_p=*/0);
+       }
     }
   /* Enter the DECL into the scope of the class.  */
-  else if ((TREE_CODE (decl) == USING_DECL && TREE_TYPE (decl))
+  else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
           || pushdecl_class_level (decl))
     {
       /* All TYPE_DECLs go at the end of TYPE_FIELDS.  Ordinary fields
@@ -2216,7 +2302,7 @@ finish_member_declaration (tree decl)
         list.)  */
 
       if (TREE_CODE (decl) == TYPE_DECL)
-       TYPE_FIELDS (current_class_type) 
+       TYPE_FIELDS (current_class_type)
          = chainon (TYPE_FIELDS (current_class_type), decl);
       else
        {
@@ -2224,9 +2310,30 @@ finish_member_declaration (tree decl)
          TYPE_FIELDS (current_class_type) = decl;
        }
 
-      maybe_add_class_template_decl_list (current_class_type, decl, 
+      maybe_add_class_template_decl_list (current_class_type, decl,
                                          /*friend_p=*/0);
     }
+
+  if (pch_file)
+    note_decl_for_pch (decl);
+}
+
+/* DECL has been declared while we are building a PCH file.  Perform
+   actions that we might normally undertake lazily, but which can be
+   performed now so that they do not have to be performed in
+   translation units which include the PCH file.  */
+
+void
+note_decl_for_pch (tree decl)
+{
+  gcc_assert (pch_file);
+
+  /* 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)
+      && !processing_template_decl)
+    mangle_decl (decl);
 }
 
 /* Finish processing a complete template declaration.  The PARMS are
@@ -2253,7 +2360,7 @@ finish_template_type (tree name, tree args, int entering_scope)
 
   decl = lookup_template_class (name, args,
                                NULL_TREE, NULL_TREE, entering_scope,
-                               tf_error | tf_warning | tf_user);
+                               tf_warning_or_error | tf_user);
   if (decl != error_mark_node)
     decl = TYPE_STUB_DECL (decl);
 
@@ -2267,7 +2374,7 @@ finish_template_type (tree name, tree args, int entering_scope)
    access_{default,public,protected_private}_node.  For a virtual base
    we set TREE_TYPE.  */
 
-tree 
+tree
 finish_base_specifier (tree base, tree access, bool virtual_p)
 {
   tree result;
@@ -2282,10 +2389,10 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
   else
     {
       if (cp_type_quals (base) != 0)
-        {
-          error ("base class %qT has cv qualifiers", base);
-          base = TYPE_MAIN_VARIANT (base);
-        }
+       {
+         error ("base class %qT has cv qualifiers", base);
+         base = TYPE_MAIN_VARIANT (base);
+       }
       result = build_tree_list (access, base);
       if (virtual_p)
        TREE_TYPE (result) = integer_type_node;
@@ -2294,38 +2401,15 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
   return result;
 }
 
-/* Called when multiple declarators are processed.  If that is not
-   permitted in this context, an error is issued.  */
-
-void
-check_multiple_declarators (void)
-{
-  /* [temp]
-     
-     In a template-declaration, explicit specialization, or explicit
-     instantiation the init-declarator-list in the declaration shall
-     contain at most one declarator.  
-
-     We don't just use PROCESSING_TEMPLATE_DECL for the first
-     condition since that would disallow the perfectly valid code, 
-     like `template <class T> struct S { int i, j; };'.  */
-  if (at_function_scope_p ())
-    /* It's OK to write `template <class T> void f() { int i, j;}'.  */
-    return;
-     
-  if (PROCESSING_REAL_TEMPLATE_DECL_P () 
-      || processing_explicit_instantiation
-      || processing_specialization)
-    error ("multiple declarators in template declaration");
-}
-
 /* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is
    what we found when we tried to do the lookup.  */
 
 void
 qualified_name_lookup_error (tree scope, tree name, tree decl)
 {
-  if (TYPE_P (scope))
+  if (scope == error_mark_node)
+    ; /* We already complained.  */
+  else if (TYPE_P (scope))
     {
       if (!COMPLETE_TYPE_P (scope))
        error ("incomplete type %qT used in nested name specifier", scope);
@@ -2342,12 +2426,12 @@ qualified_name_lookup_error (tree scope, tree name, tree decl)
   else
     error ("%<::%D%> has not been declared", name);
 }
-             
+
 /* 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
    ID_EXPRESSION.  DECL is the entity to which that name has been
-   resolved.  
+   resolved.
 
    *CONSTANT_EXPRESSION_P is true if we are presently parsing a
    constant-expression.  In that case, *NON_CONSTANT_EXPRESSION_P will
@@ -2357,6 +2441,13 @@ qualified_name_lookup_error (tree scope, tree name, tree decl)
    constant-expression, but a non-constant expression is also
    permissible.
 
+   DONE is true if this expression is a complete postfix-expression;
+   it is false if this expression is followed by '->', '[', '(', etc.
+   ADDRESS_P is true iff this expression is the operand of '&'.
+   TEMPLATE_P is true iff the qualified-id was of the form
+   "A::template B".  TEMPLATE_ARG_P is true iff this qualified name
+   appears as a template argument.
+
    If an error occurs, and it is the kind of error that might cause
    the parser to abort a tentative parse, *ERROR_MSG is filled in.  It
    is the caller's responsibility to issue the message.  *ERROR_MSG
@@ -2366,19 +2457,22 @@ qualified_name_lookup_error (tree scope, tree name, tree decl)
    Return an expression for the entity, after issuing appropriate
    diagnostics.  This function is also responsible for transforming a
    reference to a non-static member into a COMPONENT_REF that makes
-   the use of "this" explicit.  
+   the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
 
 tree
-finish_id_expression (tree id_expression, 
+finish_id_expression (tree id_expression,
                      tree decl,
                      tree scope,
                      cp_id_kind *idk,
-                     tree *qualifying_class,
                      bool integral_constant_expression_p,
                      bool allow_non_integral_constant_expression_p,
                      bool *non_integral_constant_expression_p,
+                     bool template_p,
+                     bool done,
+                     bool address_p,
+                     bool template_arg_p,
                      const char **error_msg)
 {
   /* Initialize the output parameters.  */
@@ -2394,13 +2488,13 @@ finish_id_expression (tree id_expression,
           || TREE_CODE (decl) == TYPE_DECL)
     ;
   /* Look up the name.  */
-  else 
+  else
     {
       if (decl == error_mark_node)
        {
          /* Name lookup failed.  */
-         if (scope 
-             && (!TYPE_P (scope) 
+         if (scope
+             && (!TYPE_P (scope)
                  || (!dependent_type_p (scope)
                      && !(TREE_CODE (id_expression) == IDENTIFIER_NODE
                           && IDENTIFIER_TYPENAME_P (id_expression)
@@ -2433,6 +2527,21 @@ finish_id_expression (tree id_expression,
         was entirely defined.  */
       if (!scope && decl != error_mark_node)
        maybe_note_name_used_in_class (id_expression, decl);
+
+      /* Disallow uses of local variables from containing functions.  */
+      if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
+       {
+         tree context = decl_function_context (decl);
+         if (context != NULL_TREE && context != current_function_decl
+             && ! TREE_STATIC (decl))
+           {
+             error (TREE_CODE (decl) == VAR_DECL
+                    ? "use of %<auto%> variable from containing function"
+                    : "use of parameter from containing function");
+             error ("  %q+#D declared here", decl);
+             return error_mark_node;
+           }
+       }
     }
 
   /* If we didn't find anything, or what we found was a type,
@@ -2455,12 +2564,16 @@ finish_id_expression (tree id_expression,
   if ((TREE_CODE (decl) == CONST_DECL && DECL_TEMPLATE_PARM_P (decl))
       || TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
     {
+      tree r;
+
       *idk = CP_ID_KIND_NONE;
       if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
        decl = TEMPLATE_PARM_DECL (decl);
-      if (integral_constant_expression_p 
+      r = convert_from_reference (DECL_INITIAL (decl));
+
+      if (integral_constant_expression_p
          && !dependent_type_p (TREE_TYPE (decl))
-         && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))) 
+         && !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r))))
        {
          if (!allow_non_integral_constant_expression_p)
            error ("template parameter %qD of type %qT is not allowed in "
@@ -2468,15 +2581,18 @@ finish_id_expression (tree id_expression,
                   "integral or enumeration type", decl, TREE_TYPE (decl));
          *non_integral_constant_expression_p = true;
        }
-      return DECL_INITIAL (decl);
+      return r;
     }
-  /* Similarly, we resolve enumeration constants to their 
+  /* Similarly, we resolve enumeration constants to their
      underlying values.  */
   else if (TREE_CODE (decl) == CONST_DECL)
     {
       *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
@@ -2486,7 +2602,7 @@ finish_id_expression (tree id_expression,
       /* If the declaration was explicitly qualified indicate
         that.  The semantics of `A::f(3)' are different than
         `f(3)' if `f' is virtual.  */
-      *idk = (scope 
+      *idk = (scope
              ? CP_ID_KIND_QUALIFIED
              : (TREE_CODE (decl) == TEMPLATE_ID_EXPR
                 ? CP_ID_KIND_TEMPLATE_ID
@@ -2510,13 +2626,13 @@ finish_id_expression (tree id_expression,
       /* A template-id where the name of the template was not resolved
         is definitely dependent.  */
       else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
-              && (TREE_CODE (TREE_OPERAND (decl, 0)) 
+              && (TREE_CODE (TREE_OPERAND (decl, 0))
                   == IDENTIFIER_NODE))
        dependent_p = true;
       /* For anything except an overloaded function, just check its
         type.  */
       else if (!is_overloaded_fn (decl))
-       dependent_p 
+       dependent_p
          = dependent_type_p (TREE_TYPE (decl));
       /* For a set of overloaded functions, check each of the
         functions.  */
@@ -2565,45 +2681,67 @@ finish_id_expression (tree id_expression,
             dependent.  */
          if (scope)
            {
-             if (TYPE_P (scope))
-               *qualifying_class = scope;
              /* Since this name was dependent, the expression isn't
                 constant -- yet.  No error is issued because it might
                 be constant when things are instantiated.  */
              if (integral_constant_expression_p)
                *non_integral_constant_expression_p = true;
-             if (TYPE_P (scope) && dependent_type_p (scope))
-               return build_nt (SCOPE_REF, scope, id_expression);
-             else if (TYPE_P (scope) && DECL_P (decl))
-               return build2 (SCOPE_REF, TREE_TYPE (decl), scope,
-                              id_expression);
-             else
-               return decl;
+             if (TYPE_P (scope))
+               {
+                 if (address_p && done)
+                   decl = finish_qualified_id_expr (scope, decl,
+                                                    done, address_p,
+                                                    template_p,
+                                                    template_arg_p);
+                 else if (dependent_type_p (scope))
+                   decl = build_qualified_name (/*type=*/NULL_TREE,
+                                                scope,
+                                                id_expression,
+                                                template_p);
+                 else if (DECL_P (decl))
+                   decl = build_qualified_name (TREE_TYPE (decl),
+                                                scope,
+                                                id_expression,
+                                                template_p);
+               }
+             if (TREE_TYPE (decl))
+               decl = convert_from_reference (decl);
+             return decl;
            }
          /* A TEMPLATE_ID already contains all the information we
             need.  */
          if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
            return id_expression;
-         /* Since this name was dependent, the expression isn't
-            constant -- yet.  No error is issued because it might be
-            constant when things are instantiated.  */
-         if (integral_constant_expression_p)
-           *non_integral_constant_expression_p = true;
          *idk = CP_ID_KIND_UNQUALIFIED_DEPENDENT;
          /* If we found a variable, then name lookup during the
             instantiation will always resolve to the same VAR_DECL
             (or an instantiation thereof).  */
          if (TREE_CODE (decl) == VAR_DECL
              || TREE_CODE (decl) == PARM_DECL)
-           return decl;
+           return convert_from_reference (decl);
+         /* The same is true for FIELD_DECL, but we also need to
+            make sure that the syntax is correct.  */
+         else if (TREE_CODE (decl) == FIELD_DECL)
+           {
+             /* Since SCOPE is NULL here, this is an unqualified name.
+                Access checking has been performed during name lookup
+                already.  Turn off checking to avoid duplicate errors.  */
+             push_deferring_access_checks (dk_no_check);
+             decl = finish_non_static_data_member
+                      (decl, current_class_ref,
+                       /*qualifying_scope=*/NULL_TREE);
+             pop_deferring_access_checks ();
+             return decl;
+           }
          return id_expression;
        }
 
       /* Only certain kinds of names are allowed in constant
-       expression.  Enumerators and template parameters 
-       have already been handled above.  */
+        expression.  Enumerators and template parameters have already
+        been handled above.  */
       if (integral_constant_expression_p
-         && !DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+         && ! DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+         && ! builtin_valid_in_constant_expr_p (decl))
        {
          if (!allow_non_integral_constant_expression_p)
            {
@@ -2612,7 +2750,7 @@ finish_id_expression (tree id_expression,
            }
          *non_integral_constant_expression_p = true;
        }
-      
+
       if (TREE_CODE (decl) == NAMESPACE_DECL)
        {
          error ("use of namespace %qD as expression", decl);
@@ -2641,22 +2779,40 @@ finish_id_expression (tree id_expression,
 
       if (scope)
        {
-         decl = (adjust_result_of_qualified_name_lookup 
+         decl = (adjust_result_of_qualified_name_lookup
                  (decl, scope, current_class_type));
 
          if (TREE_CODE (decl) == FUNCTION_DECL)
            mark_used (decl);
 
          if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
-           *qualifying_class = scope;
-         else if (!processing_template_decl)
-           decl = convert_from_reference (decl);
-         else if (TYPE_P (scope))
-           decl = build2 (SCOPE_REF, TREE_TYPE (decl), scope, decl);
+           decl = finish_qualified_id_expr (scope,
+                                            decl,
+                                            done,
+                                            address_p,
+                                            template_p,
+                                            template_arg_p);
+         else
+           {
+             tree r = convert_from_reference (decl);
+
+             if (processing_template_decl && TYPE_P (scope))
+               r = build_qualified_name (TREE_TYPE (r),
+                                         scope, decl,
+                                         template_p);
+             decl = r;
+           }
        }
       else if (TREE_CODE (decl) == FIELD_DECL)
-       decl = finish_non_static_data_member (decl, current_class_ref,
-                                             /*qualifying_scope=*/NULL_TREE);
+       {
+         /* Since SCOPE is NULL here, this is an unqualified name.
+            Access checking has been performed during name lookup
+            already.  Turn off checking to avoid duplicate errors.  */
+         push_deferring_access_checks (dk_no_check);
+         decl = finish_non_static_data_member (decl, current_class_ref,
+                                               /*qualifying_scope=*/NULL_TREE);
+         pop_deferring_access_checks ();
+       }
       else if (is_overloaded_fn (decl))
        {
          tree first_fn = OVL_CURRENT (decl);
@@ -2667,52 +2823,31 @@ finish_id_expression (tree id_expression,
          if (!really_overloaded_fn (decl))
            mark_used (first_fn);
 
-         if (TREE_CODE (first_fn) == FUNCTION_DECL
+         if (!template_arg_p
+             && TREE_CODE (first_fn) == FUNCTION_DECL
              && DECL_FUNCTION_MEMBER_P (first_fn)
              && !shared_member_p (decl))
            {
              /* A set of member functions.  */
              decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
-             return finish_class_member_access_expr (decl, id_expression);
+             return finish_class_member_access_expr (decl, id_expression,
+                                                     /*template_p=*/false);
            }
        }
       else
        {
-         if (TREE_CODE (decl) == VAR_DECL
-             || TREE_CODE (decl) == PARM_DECL
-             || TREE_CODE (decl) == RESULT_DECL)
-           {
-             tree context = decl_function_context (decl);
-             
-             if (context != NULL_TREE && context != current_function_decl
-                 && ! TREE_STATIC (decl))
-               {
-                 error ("use of %s from containing function",
-                        (TREE_CODE (decl) == VAR_DECL
-                         ? "%<auto%> variable" : "parameter"));
-                 cp_error_at ("  %q#D declared here", decl);
-                 return error_mark_node;
-               }
-           }
-         
          if (DECL_P (decl) && DECL_NONLOCAL (decl)
              && DECL_CLASS_SCOPE_P (decl)
              && DECL_CONTEXT (decl) != current_class_type)
            {
              tree path;
-             
+
              path = currently_open_derived_class (DECL_CONTEXT (decl));
              perform_or_defer_access_check (TYPE_BINFO (path), decl);
            }
-         
-         if (! processing_template_decl)
-           decl = convert_from_reference (decl);
+
+         decl = convert_from_reference (decl);
        }
-      
-      /* Resolve references to variables of anonymous unions
-        into COMPONENT_REFs.  */
-      if (TREE_CODE (decl) == ALIAS_DECL)
-       decl = unshare_expr (DECL_INITIAL (decl));
     }
 
   if (TREE_DEPRECATED (decl))
@@ -2748,13 +2883,37 @@ finish_typeof (tree expr)
   return type;
 }
 
+/* Perform C++-specific checks for __builtin_offsetof before calling
+   fold_offsetof.  */
+
+tree
+finish_offsetof (tree expr)
+{
+  if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
+    {
+      error ("cannot apply %<offsetof%> to destructor %<~%T%>",
+             TREE_OPERAND (expr, 2));
+      return error_mark_node;
+    }
+  if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
+      || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
+      || TREE_CODE (TREE_TYPE (expr)) == UNKNOWN_TYPE)
+    {
+      if (TREE_CODE (expr) == COMPONENT_REF)
+       expr = TREE_OPERAND (expr, 1);
+      error ("cannot apply %<offsetof%> to member function %qD", expr);
+      return error_mark_node;
+    }
+  return fold_offsetof (expr, NULL_TREE);
+}
+
 /* Called from expand_body via walk_tree.  Replace all AGGR_INIT_EXPRs
    with equivalent CALL_EXPRs.  */
 
 static tree
-simplify_aggr_init_exprs_r (tree* tp, 
-                            int* walk_subtrees,
-                            void* data ATTRIBUTE_UNUSED)
+simplify_aggr_init_exprs_r (tree* tp,
+                           int* walk_subtrees,
+                           void* data ATTRIBUTE_UNUSED)
 {
   /* We don't need to walk into types; there's nothing in a type that
      needs simplification.  (And, furthermore, there are places we
@@ -2806,38 +2965,30 @@ simplify_aggr_init_expr (tree *tp)
       style = arg;
     }
 
-  if (style == ctor || style == arg)
+  if (style == ctor)
     {
-      /* Pass the address of the slot.  If this is a constructor, we
-        replace the first argument; otherwise, we tack on a new one.  */
+      /* Replace the first argument to the ctor with the address of the
+        slot.  */
       tree addr;
 
-      if (style == ctor)
-       args = TREE_CHAIN (args);
-
+      args = TREE_CHAIN (args);
       cxx_mark_addressable (slot);
       addr = build1 (ADDR_EXPR, build_pointer_type (type), slot);
-      if (style == arg)
-       {
-         /* The return type might have different cv-quals from the slot.  */
-         tree fntype = TREE_TYPE (TREE_TYPE (fn));
-         
-         gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
-                     || TREE_CODE (fntype) == METHOD_TYPE);
-         addr = convert (build_pointer_type (TREE_TYPE (fntype)), addr);
-       }
-
       args = tree_cons (NULL_TREE, addr, args);
     }
 
-  call_expr = build3 (CALL_EXPR, 
+  call_expr = build3 (CALL_EXPR,
                      TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
                      fn, args, NULL_TREE);
 
   if (style == arg)
-    /* Tell the backend that we've added our return slot to the argument
-       list.  */
-    CALL_EXPR_HAS_RETURN_SLOT_ADDR (call_expr) = 1;
+    {
+      /* Just mark it addressable here, and leave the rest to
+        expand_call{,_inline}.  */
+      cxx_mark_addressable (slot);
+      CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true;
+      call_expr = build2 (MODIFY_EXPR, TREE_TYPE (call_expr), slot, call_expr);
+    }
   else if (style == pcc)
     {
       /* If we're using the non-reentrant PCC calling convention, then we
@@ -2847,6 +2998,7 @@ simplify_aggr_init_expr (tree *tp)
       call_expr = build_aggr_init (slot, call_expr,
                                   DIRECT_BIND | LOOKUP_ONLYCONVERTING);
       pop_deferring_access_checks ();
+      call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot);
     }
 
   *tp = call_expr;
@@ -2865,7 +3017,7 @@ emit_associated_thunks (tree fn)
   if (DECL_VIRTUAL_P (fn))
     {
       tree thunk;
-      
+
       for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
        {
          if (!THUNK_ALIAS (thunk))
@@ -2874,7 +3026,7 @@ emit_associated_thunks (tree fn)
              if (DECL_RESULT_THUNK_P (thunk))
                {
                  tree probe;
-                 
+
                  for (probe = DECL_THUNKS (thunk);
                       probe; probe = TREE_CHAIN (probe))
                    use_thunk (probe, /*emit_p=*/1);
@@ -2924,9 +3076,9 @@ expand_body (tree fn)
   if (DECL_CLONED_FUNCTION_P (fn))
     {
       /* If this is a clone, go through the other clones now and mark
-         their parameters used.  We have to do that here, as we don't
-         know whether any particular clone will be expanded, and
-         therefore cannot pick one arbitrarily.  */ 
+        their parameters used.  We have to do that here, as we don't
+        know whether any particular clone will be expanded, and
+        therefore cannot pick one arbitrarily.  */
       tree probe;
 
       for (probe = TREE_CHAIN (DECL_CLONED_FUNCTION (fn));
@@ -2954,8 +3106,11 @@ expand_or_defer_fn (tree fn)
       /* Normally, collection only occurs in rest_of_compilation.  So,
         if we don't collect here, we never collect junk generated
         during the processing of templates until we hit a
-        non-template function.  */
-      ggc_collect ();
+        non-template function.  It's not safe to do this inside a
+        nested class, though, as the parser may have local state that
+        is not a GC root.  */
+      if (!function_depth)
+       ggc_collect ();
       return;
     }
 
@@ -2992,11 +3147,28 @@ expand_or_defer_fn (tree fn)
      these functions so that it can inline them as appropriate.  */
   if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn))
     {
-      if (!at_eof)
+      if (DECL_INTERFACE_KNOWN (fn))
+       /* We've already made a decision as to how this function will
+          be handled.  */;
+      else if (!at_eof)
        {
          DECL_EXTERNAL (fn) = 1;
          DECL_NOT_REALLY_EXTERN (fn) = 1;
          note_vague_linkage_fn (fn);
+         /* A non-template inline function with external linkage will
+            always be COMDAT.  As we must eventually determine the
+            linkage of all functions, and as that causes writes to
+            the data mapped in from the PCH file, it's advantageous
+            to mark the functions at this point.  */
+         if (!DECL_IMPLICIT_INSTANTIATION (fn))
+           {
+             /* This function must have external linkage, as
+                otherwise DECL_INTERFACE_KNOWN would have been
+                set.  */
+             gcc_assert (TREE_PUBLIC (fn));
+             comdat_linkage (fn);
+             DECL_INTERFACE_KNOWN (fn) = 1;
+           }
        }
       else
        import_export_decl (fn);
@@ -3110,9 +3282,636 @@ finalize_nrv (tree *tp, tree var, tree result)
   walk_tree (tp, finalize_nrv_r, &data, 0);
   htab_delete (data.visited);
 }
+\f
+/* For all elements of CLAUSES, validate them vs OpenMP constraints.
+   Remove any elements from the list that are invalid.  */
+
+tree
+finish_omp_clauses (tree clauses)
+{
+  bitmap_head generic_head, firstprivate_head, lastprivate_head;
+  tree c, t, *pc = &clauses;
+  const char *name;
+
+  bitmap_obstack_initialize (NULL);
+  bitmap_initialize (&generic_head, &bitmap_default_obstack);
+  bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
+  bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
+
+  for (pc = &clauses, c = clauses; c ; c = *pc)
+    {
+      bool remove = false;
+
+      switch (OMP_CLAUSE_CODE (c))
+       {
+       case OMP_CLAUSE_SHARED:
+         name = "shared";
+         goto check_dup_generic;
+       case OMP_CLAUSE_PRIVATE:
+         name = "private";
+         goto check_dup_generic;
+       case OMP_CLAUSE_REDUCTION:
+         name = "reduction";
+         goto check_dup_generic;
+       case OMP_CLAUSE_COPYPRIVATE:
+         name = "copyprivate";
+         goto check_dup_generic;
+       case OMP_CLAUSE_COPYIN:
+         name = "copyin";
+         goto check_dup_generic;
+       check_dup_generic:
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             if (processing_template_decl)
+               break;
+             error ("%qE is not a variable in clause %qs", t, name);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&generic_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_FIRSTPRIVATE:
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             if (processing_template_decl)
+               break;
+             error ("%qE is not a variable in clause %<firstprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&firstprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_LASTPRIVATE:
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             if (processing_template_decl)
+               break;
+             error ("%qE is not a variable in clause %<lastprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&lastprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_IF:
+         t = OMP_CLAUSE_IF_EXPR (c);
+         t = maybe_convert_cond (t);
+         if (t == error_mark_node)
+           remove = true;
+         OMP_CLAUSE_IF_EXPR (c) = t;
+         break;
+
+       case OMP_CLAUSE_NUM_THREADS:
+         t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
+         if (t == error_mark_node)
+           remove = true;
+         else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+                  && !type_dependent_expression_p (t))
+           {
+             error ("num_threads expression must be integral");
+             remove = true;
+           }
+         break;
+
+       case OMP_CLAUSE_SCHEDULE:
+         t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c);
+         if (t == NULL)
+           ;
+         else if (t == error_mark_node)
+           remove = true;
+         else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+                  && !type_dependent_expression_p (t))
+           {
+             error ("schedule chunk size expression must be integral");
+             remove = true;
+           }
+         break;
+
+       case OMP_CLAUSE_NOWAIT:
+       case OMP_CLAUSE_ORDERED:
+       case OMP_CLAUSE_DEFAULT:
+         break;
 
-/* Perform initialization related to this module.  */
+       default:
+         gcc_unreachable ();
+       }
+
+      if (remove)
+       *pc = OMP_CLAUSE_CHAIN (c);
+      else
+       pc = &OMP_CLAUSE_CHAIN (c);
+    }
+
+  for (pc = &clauses, c = clauses; c ; c = *pc)
+    {
+      enum tree_code c_kind = OMP_CLAUSE_CODE (c);
+      bool remove = false;
+      bool need_complete_non_reference = false;
+      bool need_default_ctor = false;
+      bool need_copy_ctor = false;
+      bool need_copy_assignment = false;
+      bool need_implicitly_determined = false;
+      tree type, inner_type;
+
+      switch (c_kind)
+       {
+       case OMP_CLAUSE_SHARED:
+         name = "shared";
+         need_implicitly_determined = true;
+         break;
+       case OMP_CLAUSE_PRIVATE:
+         name = "private";
+         need_complete_non_reference = true;
+         need_default_ctor = true;
+         need_implicitly_determined = true;
+         break;
+       case OMP_CLAUSE_FIRSTPRIVATE:
+         name = "firstprivate";
+         need_complete_non_reference = true;
+         need_copy_ctor = true;
+         need_implicitly_determined = true;
+         break;
+       case OMP_CLAUSE_LASTPRIVATE:
+         name = "lastprivate";
+         need_complete_non_reference = true;
+         need_copy_assignment = true;
+         need_implicitly_determined = true;
+         break;
+       case OMP_CLAUSE_REDUCTION:
+         name = "reduction";
+         need_implicitly_determined = true;
+         break;
+       case OMP_CLAUSE_COPYPRIVATE:
+         name = "copyprivate";
+         need_copy_assignment = true;
+         break;
+       case OMP_CLAUSE_COPYIN:
+         name = "copyin";
+         need_copy_assignment = true;
+         break;
+       default:
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
+       }
+
+      t = OMP_CLAUSE_DECL (c);
+      if (processing_template_decl
+         && TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+       {
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
+       }
+
+      switch (c_kind)
+       {
+       case OMP_CLAUSE_LASTPRIVATE:
+         if (!bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+           need_default_ctor = true;
+         break;
+
+       case OMP_CLAUSE_REDUCTION:
+         if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+             || POINTER_TYPE_P (TREE_TYPE (t)))
+           {
+             error ("%qE has invalid type for %<reduction%>", t);
+             remove = true;
+           }
+         else if (FLOAT_TYPE_P (TREE_TYPE (t)))
+           {
+             enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
+             switch (r_code)
+               {
+               case PLUS_EXPR:
+               case MULT_EXPR:
+               case MINUS_EXPR:
+                 break;
+               default:
+                 error ("%qE has invalid type for %<reduction(%s)%>",
+                        t, operator_name_info[r_code].name);
+                 remove = true;
+               }
+           }
+         break;
+
+       case OMP_CLAUSE_COPYIN:
+         if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
+           {
+             error ("%qE must be %<threadprivate%> for %<copyin%>", t);
+             remove = true;
+           }
+         break;
+
+       default:
+         break;
+       }
+
+      if (need_complete_non_reference)
+       {
+         t = require_complete_type (t);
+         if (t == error_mark_node)
+           remove = true;
+         else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+           {
+             error ("%qE has reference type for %qs", t, name);
+             remove = true;
+           }
+       }
+      if (need_implicitly_determined)
+       {
+         const char *share_name = NULL;
+
+         if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+           share_name = "threadprivate";
+         else switch (cxx_omp_predetermined_sharing (t))
+           {
+           case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
+             break;
+           case OMP_CLAUSE_DEFAULT_SHARED:
+             share_name = "shared";
+             break;
+           case OMP_CLAUSE_DEFAULT_PRIVATE:
+             share_name = "private";
+             break;
+           default:
+             gcc_unreachable ();
+           }
+         if (share_name)
+           {
+             error ("%qE is predetermined %qs for %qs",
+                    t, share_name, name);
+             remove = true;
+           }
+       }
+
+      /* We're interested in the base element, not arrays.  */
+      inner_type = type = TREE_TYPE (t);
+      while (TREE_CODE (inner_type) == ARRAY_TYPE)
+       inner_type = TREE_TYPE (inner_type);
+
+      /* Check for special function availability by building a call to one.
+        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))
+       {
+         int save_errorcount = errorcount;
+         tree info;
+
+         /* Always allocate 3 elements for simplicity.  These are the
+            function decls for the ctor, dtor, and assignment op.
+            This layout is known to the three lang hooks,
+            cxx_omp_clause_default_init, cxx_omp_clause_copy_init,
+            and cxx_omp_clause_assign_op.  */
+         info = make_tree_vec (3);
+         CP_OMP_CLAUSE_INFO (c) = info;
+
+         if (need_default_ctor
+             || (need_copy_ctor
+                 && !TYPE_HAS_TRIVIAL_INIT_REF (inner_type)))
+           {
+             if (need_default_ctor)
+               t = NULL;
+             else
+               {
+                 t = build_int_cst (build_pointer_type (inner_type), 0);
+                 t = build1 (INDIRECT_REF, inner_type, t);
+                 t = build_tree_list (NULL, t);
+               }
+             t = build_special_member_call (NULL_TREE,
+                                            complete_ctor_identifier,
+                                            t, inner_type, LOOKUP_NORMAL);
+             t = get_callee_fndecl (t);
+             TREE_VEC_ELT (info, 0) = t;
+           }
+
+         if ((need_default_ctor || need_copy_ctor)
+             && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_type))
+           {
+             t = build_int_cst (build_pointer_type (inner_type), 0);
+             t = build1 (INDIRECT_REF, inner_type, t);
+             t = build_special_member_call (t, complete_dtor_identifier,
+                                            NULL, inner_type, LOOKUP_NORMAL);
+             t = get_callee_fndecl (t);
+             TREE_VEC_ELT (info, 1) = t;
+           }
+
+         if (need_copy_assignment
+             && !TYPE_HAS_TRIVIAL_ASSIGN_REF (inner_type))
+           {
+             t = build_int_cst (build_pointer_type (inner_type), 0);
+             t = build1 (INDIRECT_REF, inner_type, t);
+             t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
+                                            build_tree_list (NULL, t),
+                                            inner_type, LOOKUP_NORMAL);
+
+             /* We'll have called convert_from_reference on the call, which
+                may well have added an indirect_ref.  It's unneeded here,
+                and in the way, so kill it.  */
+             if (TREE_CODE (t) == INDIRECT_REF)
+               t = TREE_OPERAND (t, 0);
+
+             t = get_callee_fndecl (t);
+             TREE_VEC_ELT (info, 2) = t;
+           }
 
+         if (errorcount != save_errorcount)
+           remove = true;
+       }
+
+      if (remove)
+       *pc = OMP_CLAUSE_CHAIN (c);
+      else
+       pc = &OMP_CLAUSE_CHAIN (c);
+    }
+
+  bitmap_obstack_release (NULL);
+  return clauses;
+}
+
+/* For all variables in the tree_list VARS, mark them as thread local.  */
+
+void
+finish_omp_threadprivate (tree vars)
+{
+  tree t;
+
+  /* Mark every variable in VARS to be assigned thread local storage.  */
+  for (t = vars; t; t = TREE_CHAIN (t))
+    {
+      tree v = TREE_PURPOSE (t);
+
+      /* If V had already been marked threadprivate, it doesn't matter
+        whether it had been used prior to this point.  */
+      if (TREE_USED (v)
+         && (DECL_LANG_SPECIFIC (v) == NULL
+             || !CP_DECL_THREADPRIVATE_P (v)))
+       error ("%qE declared %<threadprivate%> after first use", v);
+      else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
+       error ("automatic variable %qE cannot be %<threadprivate%>", v);
+      else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
+       error ("%<threadprivate%> %qE has incomplete type", v);
+      else if (TREE_STATIC (v) && TYPE_P (CP_DECL_CONTEXT (v)))
+       error ("%<threadprivate%> %qE is not file, namespace "
+              "or block scope variable", v);
+      else
+       {
+         /* Allocate a LANG_SPECIFIC structure for V, if needed.  */
+         if (DECL_LANG_SPECIFIC (v) == NULL)
+           {
+             retrofit_lang_decl (v);
+
+             /* Make sure that DECL_DISCRIMINATOR_P continues to be true
+                after the allocation of the lang_decl structure.  */
+             if (DECL_DISCRIMINATOR_P (v))
+               DECL_LANG_SPECIFIC (v)->decl_flags.u2sel = 1;
+           }
+
+         if (! DECL_THREAD_LOCAL_P (v))
+           {
+             DECL_TLS_MODEL (v) = decl_default_tls_model (v);
+             /* If rtl has been already set for this var, call
+                make_decl_rtl once again, so that encode_section_info
+                has a chance to look at the new decl flags.  */
+             if (DECL_RTL_SET_P (v))
+               make_decl_rtl (v);
+           }
+         CP_DECL_THREADPRIVATE_P (v) = 1;
+       }
+    }
+}
+
+/* Build an OpenMP structured block.  */
+
+tree
+begin_omp_structured_block (void)
+{
+  return do_pushlevel (sk_omp);
+}
+
+tree
+finish_omp_structured_block (tree block)
+{
+  return do_poplevel (block);
+}
+
+/* Similarly, except force the retention of the BLOCK.  */
+
+tree
+begin_omp_parallel (void)
+{
+  keep_next_level (true);
+  return begin_omp_structured_block ();
+}
+
+tree
+finish_omp_parallel (tree clauses, tree body)
+{
+  tree stmt;
+
+  body = finish_omp_structured_block (body);
+
+  stmt = make_node (OMP_PARALLEL);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_PARALLEL_CLAUSES (stmt) = clauses;
+  OMP_PARALLEL_BODY (stmt) = body;
+
+  return add_stmt (stmt);
+}
+
+/* Build and validate an OMP_FOR statement.  CLAUSES, BODY, COND, INCR
+   are directly for their associated operands in the statement.  DECL
+   and INIT are a combo; if DECL is NULL then INIT ought to be a
+   MODIFY_EXPR, and the DECL should be extracted.  PRE_BODY are
+   optional statements that need to go before the loop into its
+   sk_omp scope.  */
+
+tree
+finish_omp_for (location_t locus, tree decl, tree init, tree cond,
+               tree incr, tree body, tree pre_body)
+{
+  if (decl == NULL)
+    {
+      if (init != NULL)
+       switch (TREE_CODE (init))
+         {
+         case MODIFY_EXPR:
+           decl = TREE_OPERAND (init, 0);
+           init = TREE_OPERAND (init, 1);
+           break;
+         case MODOP_EXPR:
+           if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
+             {
+               decl = TREE_OPERAND (init, 0);
+               init = TREE_OPERAND (init, 2);
+             }
+           break;
+         default:
+           break;
+         }
+
+      if (decl == NULL)
+       {
+         error ("expected iteration declaration or initialization");
+         return NULL;
+       }
+    }
+
+  if (type_dependent_expression_p (decl)
+      || type_dependent_expression_p (init)
+      || (cond && type_dependent_expression_p (cond))
+      || (incr && type_dependent_expression_p (incr)))
+    {
+      tree stmt;
+
+      if (cond == NULL)
+       {
+         error ("%Hmissing controlling predicate", &locus);
+         return NULL;
+       }
+
+      if (incr == NULL)
+       {
+         error ("%Hmissing increment expression", &locus);
+         return NULL;
+       }
+
+      stmt = make_node (OMP_FOR);
+
+      /* This is really just a place-holder.  We'll be decomposing this
+        again and going through the build_modify_expr path below when
+        we instantiate the thing.  */
+      init = build2 (MODIFY_EXPR, void_type_node, decl, init);
+
+      TREE_TYPE (stmt) = void_type_node;
+      OMP_FOR_INIT (stmt) = init;
+      OMP_FOR_COND (stmt) = cond;
+      OMP_FOR_INCR (stmt) = incr;
+      OMP_FOR_BODY (stmt) = body;
+      OMP_FOR_PRE_BODY (stmt) = pre_body;
+
+      SET_EXPR_LOCATION (stmt, locus);
+      return add_stmt (stmt);
+    }
+
+  if (!DECL_P (decl))
+    {
+      error ("expected iteration declaration or initialization");
+      return NULL;
+    }
+
+  if (pre_body == NULL || IS_EMPTY_STMT (pre_body))
+    pre_body = NULL;
+  else if (! processing_template_decl)
+    {
+      add_stmt (pre_body);
+      pre_body = NULL;
+    }
+  init = build_modify_expr (decl, NOP_EXPR, init);
+  return c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
+}
+
+void
+finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
+{
+  tree orig_lhs;
+  tree orig_rhs;
+  bool dependent_p;
+  tree stmt;
+
+  orig_lhs = lhs;
+  orig_rhs = rhs;
+  dependent_p = false;
+  stmt = NULL_TREE;
+
+  /* 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)
+    {
+      dependent_p = (type_dependent_expression_p (lhs) 
+                    || type_dependent_expression_p (rhs));
+      if (!dependent_p)
+       {
+         lhs = build_non_dependent_expr (lhs);
+         rhs = build_non_dependent_expr (rhs);
+       }
+    }
+  if (!dependent_p)
+    {
+      stmt = c_finish_omp_atomic (code, lhs, rhs);
+      if (stmt == error_mark_node)
+       return;
+    }
+  if (processing_template_decl)
+    {
+      stmt = build2 (OMP_ATOMIC, void_type_node, orig_lhs, orig_rhs);
+      OMP_ATOMIC_DEPENDENT_P (stmt) = 1;
+      OMP_ATOMIC_CODE (stmt) = code;
+    }
+  add_stmt (stmt);
+}
+
+void
+finish_omp_barrier (void)
+{
+  tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
+  tree stmt = finish_call_expr (fn, NULL, false, false);
+  finish_expr_stmt (stmt);
+}
+
+void
+finish_omp_flush (void)
+{
+  tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE];
+  tree stmt = finish_call_expr (fn, NULL, false, false);
+  finish_expr_stmt (stmt);
+}
+
+/* True if OpenMP sharing attribute of DECL is predetermined.  */
+
+enum omp_clause_default_kind
+cxx_omp_predetermined_sharing (tree decl)
+{
+  enum omp_clause_default_kind kind;
+
+  kind = c_omp_predetermined_sharing (decl);
+  if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
+    return kind;
+
+  /* Static data members are predetermined as shared.  */
+  if (TREE_STATIC (decl))
+    {
+      tree ctx = CP_DECL_CONTEXT (decl);
+      if (TYPE_P (ctx) && IS_AGGR_TYPE (ctx))
+       return OMP_CLAUSE_DEFAULT_SHARED;
+    }
+
+  return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+}
+\f
 void
 init_cp_semantics (void)
 {