OSDN Git Service

PR c++/20103
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 25 May 2006 20:18:26 +0000 (20:18 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 25 May 2006 20:18:26 +0000 (20:18 +0000)
* gimplify.c (gimplify_decl_expr): Do not call gimple_add_tmp_var
for anonymous variables explicitly declared by front ends.

PR c++/20103
* decl.c (cp_make_fname_decl): Don't set DECL_INITIAL to
error_mark_node to indicate an initialization is OK.
(start_decl): Likewise.  Adjust call to start_decl_1.
(start_decl_1): Add initialized parameter.  Simplify.
* except.c (initialize_handler_parm): Adjust call to
setart_decl_1.
(expand_start_catch_block): Let cp_finish_decl initialize catch
parameters.
* cp-tree.h (start_decl_1): Adjust prototype.
* pt.c (tsubst_expr): Don't set DECL_INITIAL to error_mark_node.
(instantiate_decl): Let cp_finish_decl handle initialization.
* semantics.c (finish_compound_literal): Create a temporary
variable for the literal.
* typeck.c (build_unary_op): Remove COMPOUND_LITERAL_P special
cases.
* decl2.c (finish_static_data_member_decl): Don't set
DECL_INITIAL.
(grokfield): Do not try to initialize functions.

PR c++/20103
* g++.dg/ext/complit6.C: New test.
* g++.dg/ext/complit3.C: Adjust error markers.
* g++.dg/init/const3.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114119 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/except.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/complit3.C
gcc/testsuite/g++.dg/ext/complit6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/const3.C [new file with mode: 0644]

index 8ab803d..4e271ed 100644 (file)
@@ -1,3 +1,9 @@
+2006-05-25  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/20103
+       * gimplify.c (gimplify_decl_expr): Do not call gimple_add_tmp_var
+       for anonymous variables explicitly declared by front ends. 
+
 2006-05-25  Eric Botcazou  <ebotcazou@adacore.com>
 
        * tree-ssa-structalias.h (PTR_IS_REF_ALL): New macro.
index f6bcf57..45d25bb 100644 (file)
@@ -1,3 +1,25 @@
+2006-05-24  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/20103
+       * decl.c (cp_make_fname_decl): Don't set DECL_INITIAL to
+       error_mark_node to indicate an initialization is OK.
+       (start_decl): Likewise.  Adjust call to start_decl_1.
+       (start_decl_1): Add initialized parameter.  Simplify.
+       * except.c (initialize_handler_parm): Adjust call to
+       setart_decl_1.
+       (expand_start_catch_block): Let cp_finish_decl initialize catch
+       parameters.
+       * cp-tree.h (start_decl_1): Adjust prototype.
+       * pt.c (tsubst_expr): Don't set DECL_INITIAL to error_mark_node.
+       (instantiate_decl): Let cp_finish_decl handle initialization.
+       * semantics.c (finish_compound_literal): Create a temporary
+       variable for the literal.
+       * typeck.c (build_unary_op): Remove COMPOUND_LITERAL_P special
+       cases.
+       * decl2.c (finish_static_data_member_decl): Don't set
+       DECL_INITIAL.
+       (grokfield): Do not try to initialize functions.
+
 2006-05-23  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/20173
index 044fe26..486a90d 100644 (file)
@@ -3835,7 +3835,7 @@ extern tree check_tag_decl                        (cp_decl_specifier_seq *);
 extern tree shadow_tag                         (cp_decl_specifier_seq *);
 extern tree groktypename                       (cp_decl_specifier_seq *, const cp_declarator *);
 extern tree start_decl                         (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
-extern void start_decl_1                       (tree);
+extern void start_decl_1                       (tree, bool);
 extern void cp_finish_decl                     (tree, tree, bool, tree, int);
 extern void finish_decl                                (tree, tree, tree);
 extern int cp_complete_array_type              (tree *, tree, bool);
index 95acc85..fef09ed 100644 (file)
@@ -3311,7 +3311,6 @@ cp_make_fname_decl (tree id, int type_dep)
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
-  DECL_INITIAL (decl) = init;
 
   TREE_USED (decl) = 1;
 
@@ -3848,11 +3847,6 @@ start_decl (const cp_declarator *declarator,
       DECL_EXTERNAL (decl) = 0;
       if (toplevel_bindings_p ())
        TREE_STATIC (decl) = 1;
-
-      /* Tell `pushdecl' this is an initialized decl
-        even though we don't yet have the initializer expression.
-        Also tell `cp_finish_decl' it may store the real initializer.  */
-      DECL_INITIAL (decl) = error_mark_node;
     }
 
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
@@ -3895,8 +3889,7 @@ start_decl (const cp_declarator *declarator,
                 declaration will have DECL_EXTERNAL set, but will have an
                 initialization.  Thus, duplicate_decls won't warn
                 about this situation, and so we check here.  */
-             if (DECL_INITIAL (decl) 
-                 && DECL_INITIALIZED_IN_CLASS_P (field))
+             if (initialized && DECL_INITIALIZED_IN_CLASS_P (field))
                error ("duplicate initialization of %qD", decl);
              if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
                decl = field;
@@ -3930,8 +3923,7 @@ start_decl (const cp_declarator *declarator,
 
             We check for processing_specialization so this only applies
             to the new specialization syntax.  */
-         if (!DECL_INITIAL (decl)
-             && processing_specialization)
+         if (!initialized && processing_specialization)
            DECL_EXTERNAL (decl) = 1;
        }
 
@@ -3960,21 +3952,25 @@ start_decl (const cp_declarator *declarator,
       && !have_global_bss_p ())
     DECL_COMMON (tem) = 1;
 
-  if (! processing_template_decl)
-    start_decl_1 (tem);
+  if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
+    start_decl_1 (tem, initialized);
 
   return tem;
 }
 
 void
-start_decl_1 (tree decl)
+start_decl_1 (tree decl, bool initialized)
 {
-  tree type = TREE_TYPE (decl);
-  int initialized = (DECL_INITIAL (decl) != NULL_TREE);
+  tree type;
 
-  if (type == error_mark_node)
+  gcc_assert (!processing_template_decl);
+
+  if (error_operand_p (decl))
     return;
 
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  type = TREE_TYPE (decl);
+
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
@@ -3998,16 +3994,10 @@ start_decl_1 (tree decl)
          initialized = 0;
        }
     }
-
-  if (!initialized
-      && TREE_CODE (decl) != TYPE_DECL
-      && TREE_CODE (decl) != TEMPLATE_DECL
-      && type != error_mark_node
-      && IS_AGGR_TYPE (type)
-      && ! DECL_EXTERNAL (decl))
+  else if (IS_AGGR_TYPE (type)
+          && ! DECL_EXTERNAL (decl))
     {
-      if ((! processing_template_decl || ! uses_template_parms (type))
-         && !COMPLETE_TYPE_P (complete_type (type)))
+      if (!COMPLETE_TYPE_P (complete_type (type)))
        {
          error ("aggregate %q#D has incomplete type and cannot be defined",
                 decl);
@@ -4027,9 +4017,6 @@ start_decl_1 (tree decl)
        }
     }
 
-  if (! initialized)
-    DECL_INITIAL (decl) = NULL_TREE;
-
   /* Create a new scope to hold this declaration if necessary.
      Whether or not a new scope is necessary cannot be determined
      until after the type has been completed; if the type is a
@@ -4665,16 +4652,6 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
   tree type = TREE_TYPE (decl);
   tree init_code = NULL;
 
-  /* If `start_decl' didn't like having an initialization, ignore it now.  */
-  if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
-    init = NULL_TREE;
-
-  /* If an initializer is present, DECL_INITIAL has been
-     error_mark_node, to indicate that an as-of-yet unevaluated
-     initialization will occur.  From now on, DECL_INITIAL reflects
-     the static initialization -- if any -- of DECL.  */
-  DECL_INITIAL (decl) = NULL_TREE;
-
   /* Things that are going to be initialized need to have complete
      type.  */
   TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
@@ -5040,7 +5017,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       if (at_function_scope_p ())
        add_decl_expr (decl);
 
-      if (init && DECL_INITIAL (decl))
+      if (init)
        {
          DECL_INITIAL (decl) = init;
          if (init_const_expr_p)
@@ -5227,10 +5204,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
            {
              /* Initialize the local variable.  */
              if (processing_template_decl)
-               {
-                 if (init || DECL_INITIAL (decl) == error_mark_node)
-                   DECL_INITIAL (decl) = init;
-               }
+               DECL_INITIAL (decl) = init;
              else if (!TREE_STATIC (decl))
                initialize_local_var (decl, init);
            }
index 27b88f0..c0bea8c 100644 (file)
@@ -720,9 +720,6 @@ finish_static_data_member_decl (tree decl,
   /* We cannot call pushdecl here, because that would fill in the
      TREE_CHAIN of our decl.  Instead, we modify cp_finish_decl to do
      the right thing, namely, to put this decl out straight away.  */
-  /* current_class_type can be NULL_TREE in case of error.  */
-  if (!asmspec_tree && current_class_type)
-    DECL_INITIAL (decl) = error_mark_node;
 
   if (! processing_template_decl)
     note_vague_linkage_var (decl);
@@ -920,7 +917,9 @@ grokfield (const cp_declarator *declarator,
       if (asmspec)
        set_user_assembler_name (value, asmspec);
 
-      cp_finish_decl (value, init, /*init_const_expr_p=*/false, 
+      cp_finish_decl (value, 
+                     /*init=*/NULL_TREE, 
+                     /*init_const_expr_p=*/false, 
                      asmspec_tree, flags);
 
       /* Pass friends back this way.  */
index efdbd91..4275910 100644 (file)
@@ -392,11 +392,9 @@ initialize_handler_parm (tree decl, tree exp)
       init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
     }
 
-  /* Let `cp_finish_decl' know that this initializer is ok.  */
-  DECL_INITIAL (decl) = error_mark_node;
   decl = pushdecl (decl);
 
-  start_decl_1 (decl);
+  start_decl_1 (decl, true);
   cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
                  LOOKUP_ONLYCONVERTING|DIRECT_BIND);
 }
@@ -464,7 +462,6 @@ expand_start_catch_block (tree decl)
       DECL_REGISTER (exp) = 1;
       cp_finish_decl (exp, init, /*init_const_expr=*/false, 
                      NULL_TREE, LOOKUP_ONLYCONVERTING);
-      finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
       initialize_handler_parm (decl, exp);
     }
 
index ca57676..4b8232e 100644 (file)
@@ -8266,8 +8266,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            decl = tsubst (decl, args, complain, in_decl);
            if (decl != error_mark_node)
              {
-               if (init)
-                 DECL_INITIAL (decl) = error_mark_node;
                /* By marking the declaration as instantiated, we avoid
                   trying to instantiate it.  Since instantiate_decl can't
                   handle local variables, and since we've already done
@@ -11850,7 +11848,6 @@ instantiate_decl (tree d, int defer_ok,
          init = tsubst_expr (DECL_INITIAL (code_pattern), 
                              args,
                              tf_warning_or_error, NULL_TREE);
-         DECL_INITIAL (d) = init;
          cp_finish_decl (d, init, /*init_const_expr_p=*/false,
                          /*asmspec_tree=*/NULL_TREE,
                          LOOKUP_ONLYCONVERTING);
@@ -11917,11 +11914,20 @@ instantiate_decl (tree d, int defer_ok,
 
   if (TREE_CODE (d) == VAR_DECL)
     {
+      tree init;
+
       /* Clear out DECL_RTL; whatever was there before may not be right
         since we've reset the type of the declaration.  */
       SET_DECL_RTL (d, NULL_RTX);
       DECL_IN_AGGR_P (d) = 0;
 
+      /* The initializer is placed in DECL_INITIAL by
+        regenerate_decl_from_template.  Pull it out so that
+        finish_decl can process it.  */
+      init = DECL_INITIAL (d);
+      DECL_INITIAL (d) = NULL_TREE;
+      DECL_INITIALIZED_P (d) = 0;
+
       /* Clear DECL_EXTERNAL so that cp_finish_decl will process the
         initializer.  That function will defer actual emission until
         we have a chance to determine linkage.  */
@@ -11929,7 +11935,7 @@ instantiate_decl (tree d, int defer_ok,
 
       /* Enter the scope of D so that access-checking works correctly.  */
       push_nested_class (DECL_CONTEXT (d));
-      finish_decl (d, DECL_INITIAL (d), NULL_TREE);
+      finish_decl (d, init, NULL_TREE);
       pop_nested_class ();
     }
   else if (TREE_CODE (d) == FUNCTION_DECL)
index 6af4564..976005c 100644 (file)
@@ -1089,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));
@@ -2019,33 +2018,43 @@ finish_unary_op_expr (enum tree_code code, tree expr)
 tree
 finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list)
 {
+  tree var;
   tree compound_literal;
 
   /* Build a CONSTRUCTOR for the INITIALIZER_LIST.  */
   compound_literal = build_constructor (NULL_TREE, initializer_list);
   if (processing_template_decl)
-    TREE_TYPE (compound_literal) = type;
-  else
     {
-      /* Check the initialization.  */
-      compound_literal = reshape_init (type, compound_literal);
-      compound_literal = digest_init (type, compound_literal);
-      /* 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))
-       cp_complete_array_type (&TREE_TYPE (compound_literal),
-                               compound_literal, 1);
-    }
-
-  /* Mark it as a compound-literal.  */
-  if (TREE_CODE (compound_literal) == CONSTRUCTOR)
-    TREE_HAS_CONSTRUCTOR (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 hase 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
index 5ee2ba1..975bfd3 100644 (file)
@@ -4324,9 +4324,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
       if (TREE_CODE (argtype) != FUNCTION_TYPE
          && TREE_CODE (argtype) != METHOD_TYPE
          && TREE_CODE (arg) != OFFSET_REF
-         /* Permit users to take the address of a compound-literal
-            with sufficient simple elements.  */
-         && !(COMPOUND_LITERAL_P (arg) && TREE_STATIC (arg))
          && !lvalue_or_else (arg, lv_addressof))
        return error_mark_node;
 
@@ -4343,24 +4340,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          return val;
        }
 
-      /* If the user has taken the address of the compound literal,
-        create a variable to contain the value of the literal and
-        then return the address of that variable.  */
-      if (COMPOUND_LITERAL_P (arg))
-       {
-         tree var;
-         gcc_assert (TREE_STATIC (arg));
-         var = create_temporary_var (TREE_TYPE (arg));
-         TREE_STATIC (var) = 1;
-         set_compound_literal_name (var); 
-         initialize_artificial_var (var, arg);
-         arg = pushdecl (var);
-         /* Since each compound literal is unique, pushdecl should
-            never find a pre-existing variable with the same
-            name.  */
-         gcc_assert (arg == var);
-       }
-      
       if (TREE_CODE (arg) != COMPONENT_REF)
        {
          val = build_address (arg);
index 103b36e..fe18bc1 100644 (file)
@@ -1216,10 +1216,12 @@ gimplify_decl_expr (tree *stmt_p)
            walk_tree (&init, force_labels_r, NULL, NULL);
        }
 
-      /* This decl isn't mentioned in the enclosing block, so add it to the
-        list of temps.  FIXME it seems a bit of a kludge to say that
-        anonymous artificial vars aren't pushed, but everything else is.  */
-      if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
+      /* Some front ends do not explicitly declare all anonymous
+        artificial variables.  We compensate here by declaring the
+        variables, though it would be better if the front ends would
+        explicitly declare them.  */
+      if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
+         && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
        gimple_add_tmp_var (decl);
     }
 
index 4e3a9b8..78fa87a 100644 (file)
@@ -1,3 +1,10 @@
+2006-05-25  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/20103
+       * g++.dg/ext/complit6.C: New test.
+       * g++.dg/ext/complit3.C: Adjust error markers.
+       * g++.dg/init/const3.C: New test.       
+
 2006-05-25  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/27743
index 1783a08..a54a8bc 100644 (file)
@@ -2,7 +2,7 @@
 
 int Compound_Literals_0()
 {
-  static int y[] = (int []) {1, 2, 3}; // { dg-error "compound literal" }
-  static int z[] = (int [3]) {1}; // { dg-error "compound literal" }
+  static int y[] = (int []) {1, 2, 3}; // { dg-error "init" }
+  static int z[] = (int [3]) {1}; // { dg-error "init" }
   return y[0]+z[0]; 
 }
diff --git a/gcc/testsuite/g++.dg/ext/complit6.C b/gcc/testsuite/g++.dg/ext/complit6.C
new file mode 100644 (file)
index 0000000..d3187a6
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/20103
+// { dg-options "" }
+
+struct A
+{
+  A(const A&);
+};
+
+struct B
+{
+  A a;
+};
+
+void foo(B);
+
+void bar(A &x)
+{
+  foo((B){x});
+}
diff --git a/gcc/testsuite/g++.dg/init/const3.C b/gcc/testsuite/g++.dg/init/const3.C
new file mode 100644 (file)
index 0000000..96cb6f9
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-do run }
+
+struct S {
+  static const int i = 3;
+};
+
+const int S::i;
+
+int main () {
+  if (!S::i)
+    return 1;
+}