OSDN Git Service

PR c++/33407
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index 054a83e..8cf9ceb 100644 (file)
@@ -3,8 +3,8 @@
    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.
 
@@ -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 void emit_associated_thunks (tree);
 static tree finalize_nrv_r (tree *, int *, void *);
 
 
@@ -509,7 +508,8 @@ finish_cond (tree *cond_p, tree expr)
       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;
 }
@@ -619,7 +619,8 @@ finish_expr_stmt (tree expr)
       else if (!type_dependent_expression_p (expr))
        convert_to_void (build_non_dependent_expr (expr), "statement");
 
-      check_for_bare_parameter_packs (expr);
+      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.  */
@@ -876,7 +877,8 @@ finish_for_expr (tree expr, tree for_stmt)
   else if (!type_dependent_expression_p (expr))
     convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
   expr = maybe_cleanup_point_expr_void (expr);
-  check_for_bare_parameter_packs (expr);
+  if (check_for_bare_parameter_packs (&expr))
+    expr = error_mark_node;
   FOR_EXPR (for_stmt) = expr;
 }
 
@@ -972,12 +974,13 @@ finish_switch_cond (tree cond, tree switch_stmt)
            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 ();
-  check_for_bare_parameter_packs (cond);
 }
 
 /* Finish the body of a switch-statement, which may be given by
@@ -1389,8 +1392,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.  */
-          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));
@@ -1847,6 +1851,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;
+         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)
@@ -1999,7 +2017,7 @@ finish_this_expr (void)
 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));
@@ -2178,6 +2196,10 @@ finish_template_template_parm (tree aggr, tree identifier)
 
   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);
 }
 
@@ -2307,9 +2329,13 @@ finish_member_declaration (tree decl)
   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]
 
@@ -2927,13 +2953,15 @@ finish_id_expression (tree id_expression,
       else
        {
          if (DECL_P (decl) && DECL_NONLOCAL (decl)
-             && DECL_CLASS_SCOPE_P (decl)
-             && DECL_CONTEXT (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);
@@ -3094,7 +3122,7 @@ simplify_aggr_init_expr (tree *tp)
 
 /* 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
@@ -3129,42 +3157,6 @@ emit_associated_thunks (tree fn)
 /* 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
@@ -3448,8 +3440,8 @@ finish_omp_clauses (tree clauses)
          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;
@@ -3462,8 +3454,8 @@ finish_omp_clauses (tree clauses)
            ;
          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;
@@ -3915,15 +3907,17 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond,
       pre_body = NULL;
     }
 
-  init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
+  if (!processing_template_decl)
+    init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
   init = build_modify_expr (decl, NOP_EXPR, init);
   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 (omp_for != NULL
@@ -3934,9 +3928,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_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;
 }
@@ -3944,28 +3939,38 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond,
 void
 finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
 {
+  tree orig_lhs;
+  tree orig_rhs;
+  bool dependent_p;
   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);
        }
-
+    }
+  if (!dependent_p)
+    {
       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
@@ -4075,6 +4080,18 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
   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))
     {
       type = make_aggr_type (DECLTYPE_TYPE);
@@ -4164,7 +4181,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
           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;
         }
@@ -4173,6 +4191,15 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
     {
       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))
@@ -4202,7 +4229,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);
-              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);