OSDN Git Service

2008-04-28 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 46789f7..7881a9f 100644 (file)
@@ -3,8 +3,8 @@
    building RTL.  These routines are used both during actual parsing
    and during the instantiation of template functions.
 
    building RTL.  These routines are used both during actual parsing
    and during the instantiation of template functions.
 
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+                2008 Free Software Foundation, Inc.
    Written by Mark Mitchell (mmitchell@usa.net) based on code found
    formerly in parse.y and pt.c.
 
    Written by Mark Mitchell (mmitchell@usa.net) based on code found
    formerly in parse.y and pt.c.
 
@@ -54,7 +54,6 @@ along with GCC; see the file COPYING3.  If not see
 
 static tree maybe_convert_cond (tree);
 static tree simplify_aggr_init_exprs_r (tree *, int *, void *);
 
 static tree maybe_convert_cond (tree);
 static tree simplify_aggr_init_exprs_r (tree *, int *, void *);
-static void emit_associated_thunks (tree);
 static tree finalize_nrv_r (tree *, int *, void *);
 
 
 static tree finalize_nrv_r (tree *, int *, void *);
 
 
@@ -382,9 +381,7 @@ add_stmt (tree t)
   return t;
 }
 
   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.  */
+/* Returns the stmt_tree to which statements are currently being added.  */
 
 stmt_tree
 current_stmt_tree (void)
 
 stmt_tree
 current_stmt_tree (void)
@@ -509,7 +506,8 @@ finish_cond (tree *cond_p, tree expr)
       if (TREE_CODE (cond) == DECL_EXPR)
        expr = cond;
 
       if (TREE_CODE (cond) == DECL_EXPR)
        expr = cond;
 
-      check_for_bare_parameter_packs (expr);
+      if (check_for_bare_parameter_packs (expr))
+        *cond_p = error_mark_node;
     }
   *cond_p = expr;
 }
     }
   *cond_p = expr;
 }
@@ -536,7 +534,7 @@ simplify_loop_decl_cond (tree *cond_p, tree body)
   *cond_p = boolean_true_node;
 
   if_stmt = begin_if_stmt ();
   *cond_p = boolean_true_node;
 
   if_stmt = begin_if_stmt ();
-  cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+  cond = cp_build_unary_op (TRUTH_NOT_EXPR, cond, 0, tf_warning_or_error);
   finish_if_stmt_cond (cond, if_stmt);
   finish_break_stmt ();
   finish_then_clause (if_stmt);
   finish_if_stmt_cond (cond, if_stmt);
   finish_break_stmt ();
   finish_then_clause (if_stmt);
@@ -614,12 +612,14 @@ finish_expr_stmt (tree expr)
        {
          if (warn_sequence_point)
            verify_sequence_points (expr);
        {
          if (warn_sequence_point)
            verify_sequence_points (expr);
-         expr = convert_to_void (expr, "statement");
+         expr = convert_to_void (expr, "statement", tf_warning_or_error);
        }
       else if (!type_dependent_expression_p (expr))
        }
       else if (!type_dependent_expression_p (expr))
-       convert_to_void (build_non_dependent_expr (expr), "statement");
+       convert_to_void (build_non_dependent_expr (expr), "statement", 
+                         tf_warning_or_error);
 
 
-      check_for_bare_parameter_packs (expr);
+      if (check_for_bare_parameter_packs (expr))
+        expr = error_mark_node;
 
       /* Simplification of inner statement expressions, compound exprs,
         etc can result in us already having an EXPR_STMT.  */
 
       /* Simplification of inner statement expressions, compound exprs,
         etc can result in us already having an EXPR_STMT.  */
@@ -871,12 +871,15 @@ finish_for_expr (tree expr, tree for_stmt)
     {
       if (warn_sequence_point)
        verify_sequence_points (expr);
     {
       if (warn_sequence_point)
        verify_sequence_points (expr);
-      expr = convert_to_void (expr, "3rd expression in for");
+      expr = convert_to_void (expr, "3rd expression in for",
+                              tf_warning_or_error);
     }
   else if (!type_dependent_expression_p (expr))
     }
   else if (!type_dependent_expression_p (expr))
-    convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
+    convert_to_void (build_non_dependent_expr (expr), "3rd expression in for",
+                     tf_warning_or_error);
   expr = maybe_cleanup_point_expr_void (expr);
   expr = maybe_cleanup_point_expr_void (expr);
-  check_for_bare_parameter_packs (expr);
+  if (check_for_bare_parameter_packs (expr))
+    expr = error_mark_node;
   FOR_EXPR (for_stmt) = expr;
 }
 
   FOR_EXPR (for_stmt) = expr;
 }
 
@@ -972,12 +975,13 @@ finish_switch_cond (tree cond, tree switch_stmt)
            cond = index;
        }
     }
            cond = index;
        }
     }
+  if (check_for_bare_parameter_packs (cond))
+    cond = error_mark_node;
   finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
   SWITCH_STMT_TYPE (switch_stmt) = orig_type;
   add_stmt (switch_stmt);
   push_switch (switch_stmt);
   SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
   finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
   SWITCH_STMT_TYPE (switch_stmt) = orig_type;
   add_stmt (switch_stmt);
   push_switch (switch_stmt);
   SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
-  check_for_bare_parameter_packs (cond);
 }
 
 /* Finish the body of a switch-statement, which may be given by
 }
 
 /* Finish the body of a switch-statement, which may be given by
@@ -1244,7 +1248,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
             otherwise we'll get an error.  Gross, but ...  */
          STRIP_NOPS (operand);
 
             otherwise we'll get an error.  Gross, but ...  */
          STRIP_NOPS (operand);
 
-         if (!lvalue_or_else (operand, lv_asm))
+         if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error))
            operand = error_mark_node;
 
          if (operand != error_mark_node
            operand = error_mark_node;
 
          if (operand != error_mark_node
@@ -1389,8 +1393,9 @@ finish_mem_initializers (tree mem_inits)
              any parameter packs in the TREE_VALUE have already been
              bound as part of the TREE_PURPOSE.  See
              make_pack_expansion for more information.  */
              any parameter packs in the TREE_VALUE have already been
              bound as part of the TREE_PURPOSE.  See
              make_pack_expansion for more information.  */
-          if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
-            check_for_bare_parameter_packs (TREE_VALUE (mem));
+          if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION
+              && check_for_bare_parameter_packs (TREE_VALUE (mem)))
+            TREE_VALUE (mem) = error_mark_node;
         }
 
       add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
         }
 
       add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
@@ -1501,7 +1506,8 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 
       return build_class_member_access_expr (object, decl,
                                             /*access_path=*/NULL_TREE,
 
       return build_class_member_access_expr (object, decl,
                                             /*access_path=*/NULL_TREE,
-                                            /*preserve_reference=*/false);
+                                            /*preserve_reference=*/false,
+                                            tf_warning_or_error);
     }
 }
 
     }
 }
 
@@ -1616,8 +1622,12 @@ finish_qualified_id_expr (tree qualifying_class,
        transformation, as there is no "this" pointer.  */
     ;
   else if (TREE_CODE (expr) == FIELD_DECL)
        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);
+    {
+      push_deferring_access_checks (dk_no_check);
+      expr = finish_non_static_data_member (expr, current_class_ref,
+                                           qualifying_class);
+      pop_deferring_access_checks ();
+    }
   else if (BASELINK_P (expr) && !processing_template_decl)
     {
       tree fns;
   else if (BASELINK_P (expr) && !processing_template_decl)
     {
       tree fns;
@@ -1635,7 +1645,8 @@ finish_qualified_id_expr (tree qualifying_class,
                (maybe_dummy_object (qualifying_class, NULL),
                 expr,
                 BASELINK_ACCESS_BINFO (expr),
                (maybe_dummy_object (qualifying_class, NULL),
                 expr,
                 BASELINK_ACCESS_BINFO (expr),
-                /*preserve_reference=*/false));
+                /*preserve_reference=*/false,
+                tf_warning_or_error));
       else if (done)
        /* The expression is a qualified name whose address is not
           being taken.  */
       else if (done)
        /* The expression is a qualified name whose address is not
           being taken.  */
@@ -1728,7 +1739,10 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
   tree result;
 
   if (error_operand_p (stmt_expr))
   tree result;
 
   if (error_operand_p (stmt_expr))
-    return error_mark_node;
+    {
+      pop_stmt_list (stmt_expr);
+      return error_mark_node;
+    }
 
   gcc_assert (TREE_CODE (stmt_expr) == STATEMENT_LIST);
 
 
   gcc_assert (TREE_CODE (stmt_expr) == STATEMENT_LIST);
 
@@ -1824,7 +1838,8 @@ perform_koenig_lookup (tree fn, tree args)
    Returns code for the call.  */
 
 tree
    Returns code for the call.  */
 
 tree
-finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
+finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
+                 tsubst_flags_t complain)
 {
   tree result;
   tree orig_fn;
 {
   tree result;
   tree orig_fn;
@@ -1847,6 +1862,20 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
        {
          result = build_nt_call_list (fn, args);
          KOENIG_LOOKUP_P (result) = koenig_p;
        {
          result = build_nt_call_list (fn, args);
          KOENIG_LOOKUP_P (result) = koenig_p;
+         if (cfun)
+           {
+             do
+               {
+                 tree fndecl = OVL_CURRENT (fn);
+                 if (TREE_CODE (fndecl) != FUNCTION_DECL
+                     || !TREE_THIS_VOLATILE (fndecl))
+                   break;
+                 fn = OVL_NEXT (fn);
+               }
+             while (fn);
+             if (!fn)
+               current_function_returns_abnormally = 1;
+           }
          return result;
        }
       if (!BASELINK_P (fn)
          return result;
        }
       if (!BASELINK_P (fn)
@@ -1909,7 +1938,8 @@ 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),
       result = build_new_method_call (object, fn, args, NULL_TREE,
                                      (disallow_virtual
                                       ? LOOKUP_NONVIRTUAL : 0),
-                                     /*fn_p=*/NULL);
+                                     /*fn_p=*/NULL,
+                                     complain);
     }
   else if (is_overloaded_fn (fn))
     {
     }
   else if (is_overloaded_fn (fn))
     {
@@ -1921,7 +1951,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 
       if (!result)
        /* A call to a namespace-scope function.  */
 
       if (!result)
        /* A call to a namespace-scope function.  */
-       result = build_new_function_call (fn, args, koenig_p);
+       result = build_new_function_call (fn, args, koenig_p, complain);
     }
   else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
     {
     }
   else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
     {
@@ -1938,11 +1968,11 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
     /* If the "function" is really an object of class type, it might
        have an overloaded `operator ()'.  */
     result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE,
     /* If the "function" is really an object of class type, it might
        have an overloaded `operator ()'.  */
     result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE,
-                          /*overloaded_p=*/NULL);
+                          /*overloaded_p=*/NULL, complain);
 
   if (!result)
     /* A call where the function is unknown.  */
 
   if (!result)
     /* A call where the function is unknown.  */
-    result = build_function_call (fn, args);
+    result = cp_build_function_call (fn, args, complain);
 
   if (processing_template_decl)
     {
 
   if (processing_template_decl)
     {
@@ -1959,7 +1989,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 tree
 finish_increment_expr (tree expr, enum tree_code code)
 {
 tree
 finish_increment_expr (tree expr, enum tree_code code)
 {
-  return build_x_unary_op (code, expr);
+  return build_x_unary_op (code, expr, tf_warning_or_error);
 }
 
 /* Finish a use of `this'.  Returns an expression for `this'.  */
 }
 
 /* Finish a use of `this'.  Returns an expression for `this'.  */
@@ -1999,7 +2029,7 @@ finish_this_expr (void)
 tree
 finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
 {
 tree
 finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
 {
-  if (destructor == error_mark_node)
+  if (object == error_mark_node || destructor == error_mark_node)
     return error_mark_node;
 
   gcc_assert (TYPE_P (destructor));
     return error_mark_node;
 
   gcc_assert (TYPE_P (destructor));
@@ -2048,7 +2078,7 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
 tree
 finish_unary_op_expr (enum tree_code code, tree expr)
 {
 tree
 finish_unary_op_expr (enum tree_code code, tree expr)
 {
-  tree result = build_x_unary_op (code, expr);
+  tree result = build_x_unary_op (code, expr, tf_warning_or_error);
   /* Inside a template, build_x_unary_op does not fold the
      expression. So check whether the result is folded before
      setting TREE_NEGATED_INT.  */
   /* Inside a template, build_x_unary_op does not fold the
      expression. So check whether the result is folded before
      setting TREE_NEGATED_INT.  */
@@ -2074,7 +2104,6 @@ finish_unary_op_expr (enum tree_code code, tree expr)
 tree
 finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
 {
 tree
 finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
 {
-  tree var;
   tree compound_literal;
 
   if (!TYPE_OBJ_P (type))
   tree compound_literal;
 
   if (!TYPE_OBJ_P (type))
@@ -2093,30 +2122,12 @@ finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
       return compound_literal;
     }
 
       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;
+  type = complete_type (type);
+  compound_literal = reshape_init (type, compound_literal);
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    cp_complete_array_type (&type, compound_literal, false);
+  compound_literal = digest_init (type, compound_literal);
+  return get_target_expr (compound_literal);
 }
 
 /* Return the declaration for the function-name variable indicated by
 }
 
 /* Return the declaration for the function-name variable indicated by
@@ -2178,6 +2189,10 @@ finish_template_template_parm (tree aggr, tree identifier)
 
   gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
 
 
   gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
 
+  check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl), 
+                          /*is_primary=*/true, /*is_partial=*/false,
+                          /*is_friend=*/0);
+
   return finish_template_type_parm (aggr, tmpl);
 }
 
   return finish_template_type_parm (aggr, tmpl);
 }
 
@@ -2228,9 +2243,9 @@ begin_class_definition (tree t, tree attributes)
       t = error_mark_node;
     }
 
       t = error_mark_node;
     }
 
-  if (t == error_mark_node || ! IS_AGGR_TYPE (t))
+  if (t == error_mark_node || ! MAYBE_CLASS_TYPE_P (t))
     {
     {
-      t = make_aggr_type (RECORD_TYPE);
+      t = make_class_type (RECORD_TYPE);
       pushtag (make_anon_name (), t, /*tag_scope=*/ts_current);
     }
 
       pushtag (make_anon_name (), t, /*tag_scope=*/ts_current);
     }
 
@@ -2239,7 +2254,7 @@ begin_class_definition (tree t, tree attributes)
 
   if (TYPE_BEING_DEFINED (t))
     {
 
   if (TYPE_BEING_DEFINED (t))
     {
-      t = make_aggr_type (TREE_CODE (t));
+      t = make_class_type (TREE_CODE (t));
       pushtag (TYPE_IDENTIFIER (t), t, /*tag_scope=*/ts_current);
     }
   maybe_process_partial_specialization (t);
       pushtag (TYPE_IDENTIFIER (t), t, /*tag_scope=*/ts_current);
     }
   maybe_process_partial_specialization (t);
@@ -2307,9 +2322,13 @@ finish_member_declaration (tree decl)
   DECL_CONTEXT (decl) = current_class_type;
 
   /* Check for bare parameter packs in the member variable declaration.  */
   DECL_CONTEXT (decl) = current_class_type;
 
   /* Check for bare parameter packs in the member variable declaration.  */
-  if (TREE_CODE (decl) == FIELD_DECL
-      && !check_for_bare_parameter_packs (TREE_TYPE (decl)))
-    TREE_TYPE (decl) = error_mark_node;
+  if (TREE_CODE (decl) == FIELD_DECL)
+    {
+      if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
+        TREE_TYPE (decl) = error_mark_node;
+      if (check_for_bare_parameter_packs (DECL_ATTRIBUTES (decl)))
+        DECL_ATTRIBUTES (decl) = NULL_TREE;
+    }
 
   /* [dcl.link]
 
 
   /* [dcl.link]
 
@@ -2439,8 +2458,11 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
       error ("invalid base-class specification");
       result = NULL_TREE;
     }
       error ("invalid base-class specification");
       result = NULL_TREE;
     }
-  else if (! is_aggr_type (base, 1))
-    result = NULL_TREE;
+  else if (! MAYBE_CLASS_TYPE_P (base))
+    {
+      error ("%qT is not a class type", base);
+      result = NULL_TREE;
+    }
   else
     {
       if (cp_type_quals (base) != 0)
   else
     {
       if (cp_type_quals (base) != 0)
@@ -2919,7 +2941,8 @@ finish_id_expression (tree id_expression,
              /* A set of member functions.  */
              decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
              return finish_class_member_access_expr (decl, id_expression,
              /* A set of member functions.  */
              decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
              return finish_class_member_access_expr (decl, id_expression,
-                                                     /*template_p=*/false);
+                                                     /*template_p=*/false,
+                                                     tf_warning_or_error);
            }
 
          decl = baselink_for_fns (decl);
            }
 
          decl = baselink_for_fns (decl);
@@ -2927,13 +2950,15 @@ finish_id_expression (tree id_expression,
       else
        {
          if (DECL_P (decl) && DECL_NONLOCAL (decl)
       else
        {
          if (DECL_P (decl) && DECL_NONLOCAL (decl)
-             && DECL_CLASS_SCOPE_P (decl)
-             && context_for_name_lookup (decl) != current_class_type)
+             && DECL_CLASS_SCOPE_P (decl))
            {
            {
-             tree path;
-
-             path = currently_open_derived_class (DECL_CONTEXT (decl));
-             perform_or_defer_access_check (TYPE_BINFO (path), decl, decl);
+             tree context = context_for_name_lookup (decl); 
+             if (context != current_class_type)
+               {
+                 tree path = currently_open_derived_class (context);
+                 perform_or_defer_access_check (TYPE_BINFO (path),
+                                                decl, decl);
+               }
            }
 
          decl = convert_from_reference (decl);
            }
 
          decl = convert_from_reference (decl);
@@ -2956,7 +2981,7 @@ finish_typeof (tree expr)
 
   if (type_dependent_expression_p (expr))
     {
 
   if (type_dependent_expression_p (expr))
     {
-      type = make_aggr_type (TYPEOF_TYPE);
+      type = cxx_make_type (TYPEOF_TYPE);
       TYPEOF_TYPE_EXPR (type) = expr;
       SET_TYPE_STRUCTURAL_EQUALITY (type);
 
       TYPEOF_TYPE_EXPR (type) = expr;
       SET_TYPE_STRUCTURAL_EQUALITY (type);
 
@@ -2996,6 +3021,8 @@ finish_offsetof (tree expr)
       error ("cannot apply %<offsetof%> to member function %qD", expr);
       return error_mark_node;
     }
       error ("cannot apply %<offsetof%> to member function %qD", expr);
       return error_mark_node;
     }
+  if (TREE_CODE (expr) == INDIRECT_REF && REFERENCE_REF_P (expr))
+    expr = TREE_OPERAND (expr, 0);
   return fold_offsetof (expr, NULL_TREE);
 }
 
   return fold_offsetof (expr, NULL_TREE);
 }
 
@@ -3084,7 +3111,8 @@ simplify_aggr_init_expr (tree *tp)
         SLOT.  */
       push_deferring_access_checks (dk_no_check);
       call_expr = build_aggr_init (slot, call_expr,
         SLOT.  */
       push_deferring_access_checks (dk_no_check);
       call_expr = build_aggr_init (slot, call_expr,
-                                  DIRECT_BIND | LOOKUP_ONLYCONVERTING);
+                                  DIRECT_BIND | LOOKUP_ONLYCONVERTING,
+                                   tf_warning_or_error);
       pop_deferring_access_checks ();
       call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot);
     }
       pop_deferring_access_checks ();
       call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot);
     }
@@ -3094,7 +3122,7 @@ simplify_aggr_init_expr (tree *tp)
 
 /* Emit all thunks to FN that should be emitted when FN is emitted.  */
 
 
 /* Emit all thunks to FN that should be emitted when FN is emitted.  */
 
-static void
+void
 emit_associated_thunks (tree fn)
 {
   /* When we use vcall offsets, we emit thunks with the virtual
 emit_associated_thunks (tree fn)
 {
   /* When we use vcall offsets, we emit thunks with the virtual
@@ -3129,42 +3157,6 @@ emit_associated_thunks (tree fn)
 /* Generate RTL for FN.  */
 
 void
 /* Generate RTL for FN.  */
 
 void
-expand_body (tree fn)
-{
-  /* Emit any thunks that should be emitted at the same time as FN.  */
-  emit_associated_thunks (fn);
-
-  /* This function is only called from cgraph, or recursively from
-     emit_associated_thunks.  In neither case should we be currently
-     generating trees for a function.  */
-  gcc_assert (function_depth == 0);
-
-  c_expand_body (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.  */
-      tree probe;
-
-      for (probe = TREE_CHAIN (DECL_CLONED_FUNCTION (fn));
-          probe && DECL_CLONED_FUNCTION_P (probe);
-          probe = TREE_CHAIN (probe))
-       {
-         tree parms;
-
-         for (parms = DECL_ARGUMENTS (probe);
-              parms; parms = TREE_CHAIN (parms))
-           TREE_USED (parms) = 1;
-       }
-    }
-}
-
-/* Generate RTL for FN.  */
-
-void
 expand_or_defer_fn (tree fn)
 {
   /* When the parser calls us after finishing the body of a template
 expand_or_defer_fn (tree fn)
 {
   /* When the parser calls us after finishing the body of a template
@@ -3404,13 +3396,16 @@ finish_omp_clauses (tree clauses)
            {
              if (processing_template_decl)
                break;
            {
              if (processing_template_decl)
                break;
-             error ("%qE is not a variable in clause %<firstprivate%>", t);
+             if (DECL_P (t))
+               error ("%qD is not a variable in clause %<firstprivate%>", t);
+             else
+               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)))
            {
              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);
+             error ("%qD appears more than once in data clauses", t);
              remove = true;
            }
          else
              remove = true;
            }
          else
@@ -3423,13 +3418,16 @@ finish_omp_clauses (tree clauses)
            {
              if (processing_template_decl)
                break;
            {
              if (processing_template_decl)
                break;
-             error ("%qE is not a variable in clause %<lastprivate%>", t);
+             if (DECL_P (t))
+               error ("%qD is not a variable in clause %<lastprivate%>", t);
+             else
+               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)))
            {
              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);
+             error ("%qD appears more than once in data clauses", t);
              remove = true;
            }
          else
              remove = true;
            }
          else
@@ -3448,8 +3446,8 @@ finish_omp_clauses (tree clauses)
          t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
          if (t == error_mark_node)
            remove = true;
          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))
+         else if (!type_dependent_expression_p (t)
+                  && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
              error ("num_threads expression must be integral");
              remove = true;
            {
              error ("num_threads expression must be integral");
              remove = true;
@@ -3462,8 +3460,8 @@ finish_omp_clauses (tree clauses)
            ;
          else if (t == error_mark_node)
            remove = true;
            ;
          else if (t == error_mark_node)
            remove = true;
-         else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
-                  && !type_dependent_expression_p (t))
+         else if (!type_dependent_expression_p (t)
+                  && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
            {
              error ("schedule chunk size expression must be integral");
              remove = true;
            {
              error ("schedule chunk size expression must be integral");
              remove = true;
@@ -3663,9 +3661,10 @@ finish_omp_clauses (tree clauses)
                }
              t = build_special_member_call (NULL_TREE,
                                             complete_ctor_identifier,
                }
              t = build_special_member_call (NULL_TREE,
                                             complete_ctor_identifier,
-                                            t, inner_type, LOOKUP_NORMAL);
+                                            t, inner_type, LOOKUP_NORMAL,
+                                             tf_warning_or_error);
 
 
-             if (targetm.cxx.cdtor_returns_this ())
+             if (targetm.cxx.cdtor_returns_this () || errorcount)
                /* Because constructors and destructors return this,
                   the call will have been cast to "void".  Remove the
                   cast here.  We would like to use STRIP_NOPS, but it
                /* Because constructors and destructors return this,
                   the call will have been cast to "void".  Remove the
                   cast here.  We would like to use STRIP_NOPS, but it
@@ -3685,9 +3684,10 @@ finish_omp_clauses (tree clauses)
              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,
              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);
+                                            NULL, inner_type, LOOKUP_NORMAL,
+                                             tf_warning_or_error);
 
 
-             if (targetm.cxx.cdtor_returns_this ())
+             if (targetm.cxx.cdtor_returns_this () || errorcount)
                /* Because constructors and destructors return this,
                   the call will have been cast to "void".  Remove the
                   cast here.  We would like to use STRIP_NOPS, but it
                /* Because constructors and destructors return this,
                   the call will have been cast to "void".  Remove the
                   cast here.  We would like to use STRIP_NOPS, but it
@@ -3708,7 +3708,8 @@ finish_omp_clauses (tree clauses)
              t = build1 (INDIRECT_REF, inner_type, t);
              t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
                                             build_tree_list (NULL, t),
              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);
+                                            inner_type, LOOKUP_NORMAL,
+                                             tf_warning_or_error);
 
              /* We'll have called convert_from_reference on the call, which
                 may well have added an indirect_ref.  It's unneeded here,
 
              /* We'll have called convert_from_reference on the call, which
                 may well have added an indirect_ref.  It's unneeded here,
@@ -3746,9 +3747,14 @@ finish_omp_threadprivate (tree vars)
     {
       tree v = TREE_PURPOSE (t);
 
     {
       tree v = TREE_PURPOSE (t);
 
+      if (error_operand_p (v))
+       ;
+      else if (TREE_CODE (v) != VAR_DECL)
+       error ("%<threadprivate%> %qD is not file, namespace "
+              "or block scope variable", v);
       /* If V had already been marked threadprivate, it doesn't matter
         whether it had been used prior to this point.  */
       /* If V had already been marked threadprivate, it doesn't matter
         whether it had been used prior to this point.  */
-      if (TREE_USED (v)
+      else if (TREE_USED (v)
          && (DECL_LANG_SPECIFIC (v) == NULL
              || !CP_DECL_THREADPRIVATE_P (v)))
        error ("%qE declared %<threadprivate%> after first use", v);
          && (DECL_LANG_SPECIFIC (v) == NULL
              || !CP_DECL_THREADPRIVATE_P (v)))
        error ("%qE declared %<threadprivate%> after first use", v);
@@ -3835,7 +3841,7 @@ tree
 finish_omp_for (location_t locus, tree decl, tree init, tree cond,
                tree incr, tree body, tree pre_body)
 {
 finish_omp_for (location_t locus, tree decl, tree init, tree cond,
                tree incr, tree body, tree pre_body)
 {
-  tree omp_for;
+  tree omp_for = NULL;
 
   if (decl == NULL)
     {
 
   if (decl == NULL)
     {
@@ -3907,6 +3913,16 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond,
       return NULL;
     }
 
       return NULL;
     }
 
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
+    {
+      location_t elocus = locus;
+
+      if (EXPR_HAS_LOCATION (init))
+       elocus = EXPR_LOCATION (init);
+      error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
+      return NULL;
+    }
+
   if (pre_body == NULL || IS_EMPTY_STMT (pre_body))
     pre_body = NULL;
   else if (! processing_template_decl)
   if (pre_body == NULL || IS_EMPTY_STMT (pre_body))
     pre_body = NULL;
   else if (! processing_template_decl)
@@ -3915,17 +3931,20 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond,
       pre_body = NULL;
     }
 
       pre_body = NULL;
     }
 
-  init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
-  init = build_modify_expr (decl, NOP_EXPR, init);
+  if (!processing_template_decl)
+    init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
+  init = cp_build_modify_expr (decl, NOP_EXPR, init, tf_warning_or_error);
   if (cond && TREE_SIDE_EFFECTS (cond) && COMPARISON_CLASS_P (cond))
     {
       int n = TREE_SIDE_EFFECTS (TREE_OPERAND (cond, 1)) != 0;
       tree t = TREE_OPERAND (cond, n);
 
   if (cond && TREE_SIDE_EFFECTS (cond) && COMPARISON_CLASS_P (cond))
     {
       int n = TREE_SIDE_EFFECTS (TREE_OPERAND (cond, 1)) != 0;
       tree t = TREE_OPERAND (cond, n);
 
-      TREE_OPERAND (cond, n)
-       = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+      if (!processing_template_decl)
+       TREE_OPERAND (cond, n)
+         = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
     }
     }
-  omp_for = c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
+  if (decl != error_mark_node && init != error_mark_node)
+    omp_for = c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
   if (omp_for != NULL
       && TREE_CODE (OMP_FOR_INCR (omp_for)) == MODIFY_EXPR
       && TREE_SIDE_EFFECTS (TREE_OPERAND (OMP_FOR_INCR (omp_for), 1))
   if (omp_for != NULL
       && TREE_CODE (OMP_FOR_INCR (omp_for)) == MODIFY_EXPR
       && TREE_SIDE_EFFECTS (TREE_OPERAND (OMP_FOR_INCR (omp_for), 1))
@@ -3934,9 +3953,10 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond,
       tree t = TREE_OPERAND (OMP_FOR_INCR (omp_for), 1);
       int n = TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)) != 0;
 
       tree t = TREE_OPERAND (OMP_FOR_INCR (omp_for), 1);
       int n = TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)) != 0;
 
-      TREE_OPERAND (t, n)
-       = fold_build_cleanup_point_expr (TREE_TYPE (TREE_OPERAND (t, n)),
-                                        TREE_OPERAND (t, n));
+      if (!processing_template_decl)
+       TREE_OPERAND (t, n)
+         = fold_build_cleanup_point_expr (TREE_TYPE (TREE_OPERAND (t, n)),
+                                          TREE_OPERAND (t, n));
     }
   return omp_for;
 }
     }
   return omp_for;
 }
@@ -3944,35 +3964,45 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond,
 void
 finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
 {
 void
 finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
 {
+  tree orig_lhs;
+  tree orig_rhs;
+  bool dependent_p;
   tree stmt;
 
   tree stmt;
 
-  if (processing_template_decl
-      && (type_dependent_expression_p (lhs) 
-         || type_dependent_expression_p (rhs)))
-    stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
-                  build2 (code, void_type_node, lhs, rhs));
-  else
+  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)
     {
     {
-      /* 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);
        }
        {
          lhs = build_non_dependent_expr (lhs);
          rhs = build_non_dependent_expr (rhs);
        }
-
+    }
+  if (!dependent_p)
+    {
       stmt = c_finish_omp_atomic (code, lhs, rhs);
       stmt = c_finish_omp_atomic (code, lhs, rhs);
+      if (stmt == error_mark_node)
+       return;
     }
     }
-    
-  if (stmt != error_mark_node)
-    add_stmt (stmt);
+  if (processing_template_decl)
+    stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
+                  build2 (code, void_type_node, orig_lhs, orig_rhs));
+  add_stmt (stmt);
 }
 
 void
 finish_omp_barrier (void)
 {
   tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
 }
 
 void
 finish_omp_barrier (void)
 {
   tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
-  tree stmt = finish_call_expr (fn, NULL, false, false);
+  tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
   finish_expr_stmt (stmt);
 }
 
   finish_expr_stmt (stmt);
 }
 
@@ -3980,7 +4010,7 @@ void
 finish_omp_flush (void)
 {
   tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE];
 finish_omp_flush (void)
 {
   tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE];
-  tree stmt = finish_call_expr (fn, NULL, false, false);
+  tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
   finish_expr_stmt (stmt);
 }
 
   finish_expr_stmt (stmt);
 }
 
@@ -3999,7 +4029,7 @@ cxx_omp_predetermined_sharing (tree decl)
   if (TREE_STATIC (decl))
     {
       tree ctx = CP_DECL_CONTEXT (decl);
   if (TREE_STATIC (decl))
     {
       tree ctx = CP_DECL_CONTEXT (decl);
-      if (TYPE_P (ctx) && IS_AGGR_TYPE (ctx))
+      if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
        return OMP_CLAUSE_DEFAULT_SHARED;
     }
 
        return OMP_CLAUSE_DEFAULT_SHARED;
     }
 
@@ -4019,6 +4049,9 @@ void
 finish_static_assert (tree condition, tree message, location_t location, 
                       bool member_p)
 {
 finish_static_assert (tree condition, tree message, location_t location, 
                       bool member_p)
 {
+  if (check_for_bare_parameter_packs (condition))
+    condition = error_mark_node;
+
   if (type_dependent_expression_p (condition) 
       || value_dependent_expression_p (condition))
     {
   if (type_dependent_expression_p (condition) 
       || value_dependent_expression_p (condition))
     {
@@ -4075,9 +4108,21 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
   tree orig_expr = expr;
   tree type;
 
   tree orig_expr = expr;
   tree type;
 
+  if (!expr || error_operand_p (expr))
+    return error_mark_node;
+
+  if (TYPE_P (expr)
+      || TREE_CODE (expr) == TYPE_DECL
+      || (TREE_CODE (expr) == BIT_NOT_EXPR
+         && TYPE_P (TREE_OPERAND (expr, 0))))
+    {
+      error ("argument to decltype must be an expression");
+      return error_mark_node;
+    }
+
   if (type_dependent_expression_p (expr))
     {
   if (type_dependent_expression_p (expr))
     {
-      type = make_aggr_type (DECLTYPE_TYPE);
+      type = cxx_make_type (DECLTYPE_TYPE);
       DECLTYPE_TYPE_EXPR (type) = expr;
       DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)
         = id_expression_or_member_access_p;
       DECLTYPE_TYPE_EXPR (type) = expr;
       DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)
         = id_expression_or_member_access_p;
@@ -4129,7 +4174,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
       switch (TREE_CODE (expr))
         {
         case FIELD_DECL:
       switch (TREE_CODE (expr))
         {
         case FIELD_DECL:
-          if (DECL_C_BIT_FIELD (expr))
+          if (DECL_BIT_FIELD_TYPE (expr))
             {
               type = DECL_BIT_FIELD_TYPE (expr);
               break;
             {
               type = DECL_BIT_FIELD_TYPE (expr);
               break;
@@ -4164,7 +4209,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
           break;
 
         default:
           break;
 
         default:
-          gcc_assert (TYPE_P (expr) || DECL_P (expr));
+         gcc_assert (TYPE_P (expr) || DECL_P (expr)
+                     || TREE_CODE (expr) == SCOPE_REF);
           error ("argument to decltype must be an expression");
           return error_mark_node;
         }
           error ("argument to decltype must be an expression");
           return error_mark_node;
         }
@@ -4173,6 +4219,15 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
     {
       tree fndecl;
 
     {
       tree fndecl;
 
+      /* Expressions of reference type are sometimes wrapped in
+         INDIRECT_REFs.  INDIRECT_REFs are just internal compiler
+         representation, not part of the language, so we have to look
+         through them.  */
+      if (TREE_CODE (expr) == INDIRECT_REF
+          && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
+         == REFERENCE_TYPE)
+        expr = TREE_OPERAND (expr, 0);
+
       if (TREE_CODE (expr) == CALL_EXPR
           && (fndecl = get_callee_fndecl (expr))
           && (fndecl != error_mark_node))
       if (TREE_CODE (expr) == CALL_EXPR
           && (fndecl = get_callee_fndecl (expr))
           && (fndecl != error_mark_node))
@@ -4202,7 +4257,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
                  decltype(e) is defined as T&, otherwise decltype(e) is
                  defined as T.  */
               type = TREE_TYPE (expr);
                  decltype(e) is defined as T&, otherwise decltype(e) is
                  defined as T.  */
               type = TREE_TYPE (expr);
-              if (expr == current_class_ptr)
+              if (type == error_mark_node)
+                return error_mark_node;
+              else if (expr == current_class_ptr)
                 /* If the expression is just "this", we want the
                    cv-unqualified pointer for the "this" type.  */
                 type = TYPE_MAIN_VARIANT (type);
                 /* If the expression is just "this", we want the
                    cv-unqualified pointer for the "this" type.  */
                 type = TYPE_MAIN_VARIANT (type);