OSDN Git Service

Make TREE_USED match the [basic.def.odr] concept for FUNCTION_DECL
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 16 Aug 2009 17:42:56 +0000 (17:42 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 16 Aug 2009 17:42:56 +0000 (17:42 +0000)
and VAR_DECL, so mark_used only has effect the first time.
* decl2.c (mark_used): Just return if TREE_USED is already set.
Don't set TREE_USED if cp_unevaluated_operand is set.
(tree_used_ok): New fn.
* init.c (build_offset_ref): Check it instead of TREE_USED.
* call.c (build_call_a): Likewise.
* cp-tree.h: Declare it.
(DECL_NO_LINKAGE_CHECKED): No longer needed.
(struct lang_decl_base): Remove no_linkage_checked bitfield.

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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/debug/dwarf2/inline1.C [new file with mode: 0644]

index 9a694d9..b98842e 100644 (file)
@@ -1,4 +1,15 @@
-2009-08-15  Jason Merrill  <jason@redhat.com>
+2009-08-16  Jason Merrill  <jason@redhat.com>
+
+       Make TREE_USED match the [basic.def.odr] concept for FUNCTION_DECL
+       and VAR_DECL, so mark_used only has effect the first time.
+       * decl2.c (mark_used): Just return if TREE_USED is already set.
+       Don't set TREE_USED if cp_unevaluated_operand is set.
+       (tree_used_ok): New fn.
+       * init.c (build_offset_ref): Check it instead of TREE_USED.
+       * call.c (build_call_a): Likewise.
+       * cp-tree.h: Declare it.
+       (DECL_NO_LINKAGE_CHECKED): No longer needed.
+       (struct lang_decl_base): Remove no_linkage_checked bitfield.
 
        * decl2.c (finish_static_data_member_decl): Don't set TREE_USED.
 
index f6a083b..30a1b45 100644 (file)
@@ -318,7 +318,7 @@ build_call_a (tree function, int n, tree *argarray)
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
     {
       decl = TREE_OPERAND (function, 0);
-      if (!TREE_USED (decl))
+      if (!tree_used_ok (decl))
        {
          /* We invoke build_call directly for several library
             functions.  These may have been declared normally if
index ae39110..bbd1a42 100644 (file)
@@ -1579,9 +1579,8 @@ struct GTY(()) lang_decl_base {
   unsigned anticipated_p : 1;             /* fn or type */
   unsigned friend_attr : 1;               /* fn or type */
   unsigned template_conv_p : 1;                   /* template only? */
-  unsigned no_linkage_checked : 1;         /* var or fn */
   unsigned u2sel : 1;
-  /* 1 spare bit */
+  /* 2 spare bits */
 };
 
 /* True for DECL codes which have template info and access.  */
@@ -1983,14 +1982,6 @@ struct GTY(()) lang_decl {
   (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
    ->u.base.initialized_in_class)
 
-/* Nonzero if we've checked whether DECL uses types without linkage in a
-   potentially invalid way.
-   ??? Instead, should fix mark_used to only set TREE_USED when we're
-   really using something, and just return if it's already set.  */
-#define DECL_NO_LINKAGE_CHECKED(DECL) \
-  (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
-   ->u.base.no_linkage_checked)
-
 /* Nonzero for DECL means that this decl is just a friend declaration,
    and should not be added to the list of members for this class.  */
 #define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr)
@@ -4486,6 +4477,7 @@ extern tree build_cleanup                 (tree);
 extern tree build_offset_ref_call_from_tree    (tree, VEC(tree,gc) **);
 extern void check_default_args                 (tree);
 extern void mark_used                          (tree);
+extern bool tree_used_ok                       (tree);
 extern void finish_static_data_member_decl     (tree, tree, bool, tree, int);
 extern tree cp_build_parm_decl                 (tree, tree);
 extern tree get_guard                          (tree);
@@ -4638,6 +4630,7 @@ extern void mark_decl_instantiated                (tree, int);
 extern int more_specialized_fn                 (tree, tree, int);
 extern void do_decl_instantiation              (tree, tree);
 extern void do_type_instantiation              (tree, tree, tsubst_flags_t);
+extern bool always_instantiate_p               (tree);
 extern tree instantiate_decl                   (tree, int, bool);
 extern int comp_template_parms                 (const_tree, const_tree);
 extern bool uses_parameter_packs                (tree);
index f78508b..e4ed963 100644 (file)
@@ -3845,20 +3845,24 @@ mark_used (tree decl)
       decl = OVL_CURRENT (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");
+      TREE_USED (decl) = 1;
       return;
     }
   /* If we don't need a value, then we don't need to synthesize DECL.  */
   if (cp_unevaluated_operand != 0)
     return;
 
+  /* We only want to do this processing once.  We don't need to keep trying
+     to instantiate inline templates, because unit-at-a-time will make sure
+     we get them compiled before functions that want to inline them.  */
+  if (TREE_USED (decl))
+    return;
+
   /* If within finish_function, defer the rest until that function
      finishes, otherwise it might recurse.  */
   if (defer_mark_used_calls)
@@ -3892,6 +3896,10 @@ mark_used (tree decl)
   if (processing_template_decl)
     return;
 
+  TREE_USED (decl) = 1;
+  if (DECL_CLONED_FUNCTION_P (decl))
+    TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
+
   /* DR 757: A type without linkage shall not be used as the type of a
      variable or function with linkage, unless
    o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
@@ -3900,10 +3908,8 @@ mark_used (tree decl)
   if (TREE_PUBLIC (decl)
       && (TREE_CODE (decl) == FUNCTION_DECL
          || TREE_CODE (decl) == VAR_DECL)
-      && DECL_LANG_SPECIFIC (decl)
-      && !DECL_NO_LINKAGE_CHECKED (decl))
+      && DECL_LANG_SPECIFIC (decl))
     {
-      DECL_NO_LINKAGE_CHECKED (decl) = true;
       if (!DECL_EXTERN_C_P (decl)
          && !DECL_ARTIFICIAL (decl)
          && !decl_defined_p (decl)
@@ -3949,15 +3955,7 @@ mark_used (tree decl)
   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
-                  && 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.  */
-              || (TREE_CODE (decl) == VAR_DECL
-                  && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
+              || always_instantiate_p (decl)))
     /* If this is a function or variable that is an instance of some
        template, we now know that we will need to actually do the
        instantiation. We check that DECL is not an explicit
@@ -3973,4 +3971,15 @@ mark_used (tree decl)
   processing_template_decl = saved_processing_template_decl;
 }
 
+/* Use this function to verify that mark_used has been called
+   previously.  That is, either TREE_USED is set, or we're in a
+   context that doesn't set it.  */
+
+bool
+tree_used_ok (tree decl)
+{
+  return (TREE_USED (decl) || cp_unevaluated_operand
+         || defer_mark_used_calls || processing_template_decl);
+}
+
 #include "gt-cp-decl2.h"
index ef18a6c..9dac7de 100644 (file)
@@ -1502,7 +1502,7 @@ build_offset_ref (tree type, tree member, bool address_p)
 
   gcc_assert (DECL_P (member) || BASELINK_P (member));
   /* Callers should call mark_used before this point.  */
-  gcc_assert (!DECL_P (member) || TREE_USED (member));
+  gcc_assert (!DECL_P (member) || tree_used_ok (member));
 
   if (!COMPLETE_TYPE_P (complete_type (type))
       && !TYPE_BEING_DEFINED (type))
index 36f1b00..eb43271 100644 (file)
@@ -15635,6 +15635,27 @@ template_for_substitution (tree decl)
   return tmpl;
 }
 
+/* Returns true if we need to instantiate this template instance even if we
+   know we aren't going to emit it..  */
+
+bool
+always_instantiate_p (tree decl)
+{
+  /* We always instantiate inline functions so that we can inline them.  An
+     explicit instantiation declaration prohibits implicit instantiation of
+     non-inline functions.  With high levels of optimization, we would
+     normally inline non-inline functions -- but we're not allowed to do
+     that for "extern template" functions.  Therefore, we check
+     DECL_DECLARED_INLINE_P, rather than possibly_inlined_p.  */
+  return ((TREE_CODE (decl) == FUNCTION_DECL
+          && DECL_DECLARED_INLINE_P (decl))
+         /* And we need to instantiate static data members so that
+            their initializers are available in integral constant
+            expressions.  */
+         || (TREE_CODE (decl) == VAR_DECL
+             && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)));
+}
+
 /* Produce the definition of D, a _DECL generated from a template.  If
    DEFER_OK is nonzero, then we don't have to actually do the
    instantiation now; we just have to do it sometime.  Normally it is
@@ -15688,6 +15709,15 @@ instantiate_decl (tree d, int defer_ok,
        the instantiation.  */
     return d;
 
+  /* Check to see whether we know that this template will be
+     instantiated in some other file, as with "extern template"
+     extension.  */
+  external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
+
+  /* In general, we do not instantiate such templates.  */
+  if (external_p && !always_instantiate_p (d))
+    return d;
+
   gen_tmpl = most_general_template (tmpl);
   gen_args = DECL_TI_ARGS (d);
 
@@ -15781,26 +15811,6 @@ instantiate_decl (tree d, int defer_ok,
       pop_access_scope (d);
     }
 
-  /* Check to see whether we know that this template will be
-     instantiated in some other file, as with "extern template"
-     extension.  */
-  external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
-  /* In general, we do not instantiate such templates...  */
-  if (external_p
-      /* ... but we instantiate inline functions so that we can inline
-        them.  An explicit instantiation declaration prohibits implicit
-        instantiation of non-inline functions.  With high levels of
-        optimization, we would normally inline non-inline functions
-        -- but we're not allowed to do that for "extern template" functions.
-        Therefore, we check DECL_DECLARED_INLINE_P, rather than
-        possibly_inlined_p.  And ...  */
-      && ! (TREE_CODE (d) == FUNCTION_DECL
-           && DECL_DECLARED_INLINE_P (d))
-      /* ... we instantiate static data members whose values are
-        needed in integral constant expressions.  */
-      && ! (TREE_CODE (d) == VAR_DECL
-           && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (d)))
-    goto out;
   /* Defer all other templates, unless we have been explicitly
      forbidden from doing so.  */
   if (/* If there is no definition, we cannot instantiate the
index acbc928..83eda2f 100644 (file)
@@ -1,3 +1,7 @@
+2009-08-16  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/debug/dwarf2/inline1.C: New.
+
 2009-08-16  Richard Sandiford  <rdsandiford@googlemail.com>
 
        PR target/38599
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/inline1.C b/gcc/testsuite/g++.dg/debug/dwarf2/inline1.C
new file mode 100644 (file)
index 0000000..ea405f8
--- /dev/null
@@ -0,0 +1,18 @@
+// This isn't really testing dwarf output, but rather that we can inline f
+// even though the call precedes the definition.
+
+// { dg-options "-gdwarf-2 -dA -O" }
+// { dg-final { scan-assembler "DW_TAG_inlined_subroutine" } }
+
+template <class T>
+inline T f(T);
+
+int main()
+{
+  f(1);
+}
+
+int i;
+
+template <class T>
+inline T f(T t) { ++i; return t; }