OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 6e6151d..a0ae6e4 100644 (file)
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-pragma.h"
 #include "tree-dump.h"
 #include "intl.h"
+#include "gimple.h"
 
 extern cpp_reader *parse_in;
 
@@ -353,7 +354,7 @@ grok_array_decl (tree array_expr, tree index_exp)
       if (array_expr == error_mark_node || index_exp == error_mark_node)
        error ("ambiguous conversion for array subscript");
 
-      expr = build_array_ref (array_expr, index_exp);
+      expr = build_array_ref (array_expr, index_exp, input_location);
     }
   if (processing_template_decl && expr != error_mark_node)
     return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp,
@@ -637,8 +638,9 @@ check_classfn (tree ctype, tree function, tree template_parms)
          return OVL_CURRENT (fndecls);
        }
       
-      error ("prototype for %q#D does not match any in class %qT",
-            function, ctype);
+      error_at (DECL_SOURCE_LOCATION (function),
+               "prototype for %q#D does not match any in class %qT",
+               function, ctype);
       is_conv_op = DECL_CONV_FN_P (fndecl);
 
       if (is_conv_op)
@@ -717,7 +719,7 @@ finish_static_data_member_decl (tree decl,
     VEC_safe_push (tree, gc, pending_statics, decl);
 
   if (LOCAL_CLASS_P (current_class_type))
-    permerror ("local class %q#T shall not have static data member %q#D",
+    permerror (input_location, "local class %q#T shall not have static data member %q#D",
               current_class_type, decl);
 
   /* Static consts need not be initialized in the class definition.  */
@@ -801,7 +803,17 @@ grokfield (const cp_declarator *declarator,
        value = push_template_decl (value);
 
       if (attrlist)
-       cplus_decl_attributes (&value, attrlist, 0);
+       {
+         int attrflags = 0;
+
+         /* If this is a typedef that names the class for linkage purposes
+            (7.1.3p8), apply any attributes directly to the type.  */
+         if (TAGGED_TYPE_P (TREE_TYPE (value))
+             && value == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+           attrflags = ATTR_FLAG_TYPE_IN_PLACE;
+
+         cplus_decl_attributes (&value, attrlist, attrflags);
+       }
 
       return value;
     }
@@ -836,7 +848,6 @@ grokfield (const cp_declarator *declarator,
                  DECL_DEFAULTED_FN (value) = 1;
                  DECL_INITIALIZED_IN_CLASS_P (value) = 1;
                  DECL_DECLARED_INLINE_P (value) = 1;
-                 DECL_INLINE (value) = 1;
                }
            }
          else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
@@ -1260,15 +1271,15 @@ build_anon_union_vars (tree type, tree object)
        continue;
       if (TREE_CODE (field) != FIELD_DECL)
        {
-         permerror ("%q+#D invalid; an anonymous union can only "
+         permerror (input_location, "%q+#D invalid; an anonymous union can only "
                     "have non-static data members", field);
          continue;
        }
 
       if (TREE_PRIVATE (field))
-       permerror ("private member %q+#D in anonymous union", field);
+       permerror (input_location, "private member %q+#D in anonymous union", field);
       else if (TREE_PROTECTED (field))
-       permerror ("protected member %q+#D in anonymous union", field);
+       permerror (input_location, "protected member %q+#D in anonymous union", field);
 
       if (processing_template_decl)
        ref = build_min_nt (COMPONENT_REF, object,
@@ -1403,7 +1414,7 @@ coerce_new_type (tree type)
     e = 2;
 
   if (e == 2)
-    permerror ("%<operator new%> takes type %<size_t%> (%qT) "
+    permerror (input_location, "%<operator new%> takes type %<size_t%> (%qT) "
               "as first parameter", size_type_node);
 
   switch (e)
@@ -2529,14 +2540,16 @@ get_guard_cond (tree guard)
       guard_value = integer_one_node;
       if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
        guard_value = convert (TREE_TYPE (guard), guard_value);
-      guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value,
+      guard = cp_build_binary_op (input_location,
+                                 BIT_AND_EXPR, guard, guard_value,
                                  tf_warning_or_error);
     }
 
   guard_value = integer_zero_node;
   if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
     guard_value = convert (TREE_TYPE (guard), guard_value);
-  return cp_build_binary_op (EQ_EXPR, guard, guard_value,
+  return cp_build_binary_op (input_location,
+                            EQ_EXPR, guard, guard_value,
                             tf_warning_or_error);
 }
 
@@ -2701,7 +2714,6 @@ start_static_storage_duration_function (unsigned count)
                               type);
   TREE_PUBLIC (ssdf_decl) = 0;
   DECL_ARTIFICIAL (ssdf_decl) = 1;
-  DECL_INLINE (ssdf_decl) = 1;
 
   /* Put this function in the list of functions to be called from the
      static constructors and destructors.  */
@@ -2812,6 +2824,38 @@ get_priority_info (int priority)
                                                    || DECL_ONE_ONLY (decl) \
                                                    || DECL_WEAK (decl)))
 
+/* Called from one_static_initialization_or_destruction(),
+   via walk_tree.
+   Walks the initializer list of a global variable and looks for
+   temporary variables (DECL_NAME() == NULL and DECL_ARTIFICIAL != 0)
+   and that have their DECL_CONTEXT() == NULL.
+   For each such temporary variable, set their DECL_CONTEXT() to
+   the current function. This is necessary because otherwise
+   some optimizers (enabled by -O2 -fprofile-arcs) might crash
+   when trying to refer to a temporary variable that does not have
+   it's DECL_CONTECT() properly set.  */
+static tree 
+fix_temporary_vars_context_r (tree *node,
+                             int  *unused ATTRIBUTE_UNUSED,
+                             void *unused1 ATTRIBUTE_UNUSED)
+{
+  gcc_assert (current_function_decl);
+
+  if (TREE_CODE (*node) == BIND_EXPR)
+    {
+      tree var;
+
+      for (var = BIND_EXPR_VARS (*node); var; var = TREE_CHAIN (var))
+       if (TREE_CODE (var) == VAR_DECL
+         && !DECL_NAME (var)
+         && DECL_ARTIFICIAL (var)
+         && !DECL_CONTEXT (var))
+         DECL_CONTEXT (var) = current_function_decl;
+    }
+
+  return NULL_TREE;
+}
+
 /* Set up to handle the initialization or destruction of DECL.  If
    INITP is nonzero, we are initializing the variable.  Otherwise, we
    are destroying it.  */
@@ -2834,6 +2878,19 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
      information.  */
   input_location = DECL_SOURCE_LOCATION (decl);
 
+  /* Make sure temporary variables in the initialiser all have
+     their DECL_CONTEXT() set to a value different from NULL_TREE.
+     This can happen when global variables initialisers are built.
+     In that case, the DECL_CONTEXT() of the global variables _AND_ of all 
+     the temporary variables that might have been generated in the
+     accompagning initialisers is NULL_TREE, meaning the variables have been
+     declared in the global namespace.
+     What we want to do here is to fix that and make sure the DECL_CONTEXT()
+     of the temporaries are set to the current function decl.  */
+  cp_walk_tree_without_duplicates (&init,
+                                  fix_temporary_vars_context_r,
+                                  NULL);
+
   /* Because of:
 
        [class.access.spec]
@@ -2882,20 +2939,22 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp)
         last to destroy the variable.  */
       else if (initp)
        guard_cond
-         = cp_build_binary_op (EQ_EXPR,
+         = cp_build_binary_op (input_location,
+                               EQ_EXPR,
                                cp_build_unary_op (PREINCREMENT_EXPR,
-                                               guard,
-                                               /*noconvert=*/1,
-                                                tf_warning_or_error),
+                                                  guard,
+                                                  /*noconvert=*/1,
+                                                  tf_warning_or_error),
                                integer_one_node,
                                tf_warning_or_error);
       else
        guard_cond
-         = cp_build_binary_op (EQ_EXPR,
+         = cp_build_binary_op (input_location,
+                               EQ_EXPR,
                                cp_build_unary_op (PREDECREMENT_EXPR,
-                                               guard,
-                                               /*noconvert=*/1,
-                                                tf_warning_or_error),
+                                                  guard,
+                                                  /*noconvert=*/1,
+                                                  tf_warning_or_error),
                                integer_zero_node,
                                tf_warning_or_error);
 
@@ -2948,7 +3007,8 @@ do_static_initialization_or_destruction (tree vars, bool initp)
   /* Build the outer if-stmt to check for initialization or destruction.  */
   init_if_stmt = begin_if_stmt ();
   cond = initp ? integer_one_node : integer_zero_node;
-  cond = cp_build_binary_op (EQ_EXPR,
+  cond = cp_build_binary_op (input_location,
+                            EQ_EXPR,
                             initialize_p_decl,
                             cond,
                             tf_warning_or_error);
@@ -2981,7 +3041,8 @@ do_static_initialization_or_destruction (tree vars, bool initp)
     /* Conditionalize this initialization on being in the right priority
        and being initializing/finalizing appropriately.  */
     priority_if_stmt = begin_if_stmt ();
-    cond = cp_build_binary_op (EQ_EXPR,
+    cond = cp_build_binary_op (input_location,
+                              EQ_EXPR,
                               priority_decl,
                               build_int_cst (NULL_TREE, priority),
                               tf_warning_or_error);
@@ -3422,7 +3483,7 @@ cp_write_global_declarations (void)
        {
          /* Does it need synthesizing?  */
          if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
-             && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
+             && (! DECL_REALLY_EXTERN (decl) || possibly_inlined_p (decl)))
            {
              /* Even though we're already at the top-level, we push
                 there again.  That way, when we pop back a few lines
@@ -3439,7 +3500,7 @@ cp_write_global_declarations (void)
              reconsider = true;
            }
 
-         if (!DECL_SAVED_TREE (decl))
+         if (!gimple_body (decl))
            continue;
 
          /* We lie to the back end, pretending that some functions
@@ -3683,6 +3744,22 @@ check_default_args (tree x)
     }
 }
 
+/* Return true if function DECL can be inlined.  This is used to force
+   instantiation of methods that might be interesting for inlining.  */
+bool
+possibly_inlined_p (tree decl)
+{
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+  if (DECL_UNINLINABLE (decl))
+    return false;
+  if (!optimize)
+    return DECL_DECLARED_INLINE_P (decl);
+  /* When optimizing, we might inline everything when flatten
+     attribute or heuristics inlining for size or autoinlining
+     is used.  */
+  return true;
+}
+
 /* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
    If DECL is a specialization or implicitly declared class member,
    generate the actual definition.  */
@@ -3707,9 +3784,24 @@ mark_used (tree decl)
   TREE_USED (decl) = 1;
   if (DECL_CLONED_FUNCTION_P (decl))
     TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DELETED_FN (decl))
+    {
+      error ("deleted function %q+D", decl);
+      error ("used here");
+    }
   /* If we don't need a value, then we don't need to synthesize DECL.  */
   if (skip_evaluation)
     return;
+
+  /* If within finish_function, defer the rest until that function
+     finishes, otherwise it might recurse.  */
+  if (defer_mark_used_calls)
+    {
+      VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
+      return;
+    }
+
   /* Normally, we can wait until instantiation-time to synthesize
      DECL.  However, if DECL is a static data member initialized with
      a constant, we need the value right now because a reference to
@@ -3770,18 +3862,13 @@ mark_used (tree decl)
       /* If we've already synthesized the method we don't need to
         do the instantiation test below.  */
     }
-  else if (TREE_CODE (decl) == FUNCTION_DECL
-          && DECL_DELETED_FN (decl))
-    {
-      error ("deleted function %q+D", decl);
-      error ("used here");
-    }
   else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
           && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
           && (!DECL_EXPLICIT_INSTANTIATION (decl)
               || (TREE_CODE (decl) == FUNCTION_DECL
-                  && DECL_INLINE (DECL_TEMPLATE_RESULT
-                                  (template_for_substitution (decl))))
+                  && possibly_inlined_p
+                      (DECL_TEMPLATE_RESULT (
+                        template_for_substitution (decl))))
               /* We need to instantiate static data members so that there
                  initializers are available in integral constant
                  expressions.  */