re PR c++/11131 (Unrelated declaration removes inline flag from function)
authorMark Mitchell <mark@codesourcery.com>
Tue, 10 Jun 2003 07:19:57 +0000 (07:19 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 10 Jun 2003 07:19:57 +0000 (07:19 +0000)
PR c++/11131
* tree-inline.c (inlinable_function_p): Call the language-specific
hook early.

PR c++/11131
* cp-tree.h (template_for_substitution): Declare.
* decl2.c (mark_used): Use it when figuring out whether or not a
function is inline.
* pt.c (template_for_substitution): Give it external linkage.
* tree.c (cp_cannot_inline_tree_fn): Instantiate as early as
possible.

PR c++/11131
* g++.dg/opt/template1.C: New test.

From-SVN: r67698

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/template1.C [new file with mode: 0644]
gcc/tree-inline.c

index 43d458d09631b05698c3d8802d6004072b5aeb7e..3c34fe2c21fd2d95649329f8396e93b9291c5b9d 100644 (file)
@@ -1,3 +1,9 @@
+2003-06-10  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11131
+       * tree-inline.c (inlinable_function_p): Call the language-specific
+       hook early.
+
 2003-06-09  David Taylor  <dtaylor@emc.com>
 
        * config/rs6000/rs6000.c (rs6000_va_start, rs6000_va_arg):  Skip over
index 417fb863ce45b76aaa019c1fd5d5333ec425e9db..0de9c7b840d8c8ba63d2c924300345e13ab57285 100644 (file)
@@ -1,3 +1,13 @@
+2003-06-10  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11131
+       * cp-tree.h (template_for_substitution): Declare.
+       * decl2.c (mark_used): Use it when figuring out whether or not a
+       function is inline.
+       * pt.c (template_for_substitution): Give it external linkage.
+       * tree.c (cp_cannot_inline_tree_fn): Instantiate as early as
+       possible.
+
 2003-06-09  Zack Weinberg  <zack@codesourcery.com>
 
        PR 8861
index 5b815fe82b7efd2d69b83ef6cf7726291d249940..4639e174ee0f8224e0461d7e09b5f781a6de8ccc 100644 (file)
@@ -3978,6 +3978,7 @@ extern bool type_dependent_expression_p         (tree);
 extern bool value_dependent_expression_p        (tree);
 extern tree resolve_typename_type               (tree, bool);
 extern tree resolve_typename_type_in_current_instantiation (tree);
+extern tree template_for_substitution           (tree);
 
 /* in repo.c */
 extern void repo_template_used (tree);
index e24d558c465cdfbc55828e069945061ac198094c..08a2d663b2a3b423c942037b38b548c01e0df056 100644 (file)
@@ -4590,7 +4590,9 @@ mark_used (tree decl)
   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))))
+         || (TREE_CODE (decl) == FUNCTION_DECL 
+             && DECL_INLINE (DECL_TEMPLATE_RESULT 
+                             (template_for_substitution (decl))))))
     {
       bool defer;
 
index 52bbc51990f809454b320fd0faf2f7e4c16a5a63..1f64f747ca623a9abe61311d82ac9be762a86bbc 100644 (file)
@@ -171,7 +171,6 @@ static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
 static void copy_default_args_to_explicit_spec PARAMS ((tree));
 static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
 static int eq_local_specializations (const void *, const void *);
-static tree template_for_substitution (tree);
 static bool dependent_type_p_r (tree);
 static bool dependent_template_id_p (tree, tree);
 static tree tsubst (tree, tree, tsubst_flags_t, tree);
@@ -10736,7 +10735,7 @@ regenerate_decl_from_template (decl, tmpl)
 /* Return the TEMPLATE_DECL into which DECL_TI_ARGS(DECL) should be
    substituted to get DECL.  */
 
-static tree
+tree
 template_for_substitution (tree decl)
 {
   tree tmpl = DECL_TI_TEMPLATE (decl);
index 5ce3500915a3fa60394d092ce2b1ed480c6a7a2e..b696c3bd655c6671016d71fc2dcb747015e34c24 100644 (file)
@@ -2204,10 +2204,6 @@ cp_cannot_inline_tree_fn (fnp)
 {
   tree fn = *fnp;
 
-  if (flag_really_no_inline
-      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
-    return 1;
-
   /* We can inline a template instantiation only if it's fully
      instantiated.  */
   if (DECL_TEMPLATE_INFO (fn)
@@ -2218,6 +2214,13 @@ cp_cannot_inline_tree_fn (fnp)
        return 1;
     }
 
+  if (!DECL_INLINE (fn))
+    return 1;
+
+  if (flag_really_no_inline
+      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
+    return 1;
+
   /* Don't auto-inline anything that might not be bound within
      this unit of translation.  */
   if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
index c660eca4838ce31a45a0d411d8ce73b2a84ac88a..88381678bf14f447d8321527bf4453e6928acd50 100644 (file)
@@ -1,3 +1,8 @@
+2003-06-10  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11131
+       * g++.dg/opt/template1.C: New test.
+
 2003-06-09  Mark Mitchell  <mark@codesourcery.com>
 
        * lib/gcc-dg.exp (dg-test): Clear additional_files and
diff --git a/gcc/testsuite/g++.dg/opt/template1.C b/gcc/testsuite/g++.dg/opt/template1.C
new file mode 100644 (file)
index 0000000..9003be1
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-options "-O2" }
+// { dg-final { scan-assembler-not "foo1" } }
+
+template <int>
+struct A {
+    void foo1 () throw ();
+    void foo2 ();
+
+    void UNRELATED ();
+};
+
+template <> void A<0>::UNRELATED ();
+
+template <int dim> inline void A<dim>::foo1 () throw () {}
+template <int dim> inline void A<dim>::foo2 ()          {}
+
+void bar (A<0> &a) {
+  a.foo1 ();
+}
index a0fbe8ee635dd8572811e030b89e97996a34dbe6..dd50ca1d63130af88aa81dbfa90422e1ee8cbbf7 100644 (file)
@@ -979,8 +979,10 @@ inlinable_function_p (fn, id, nolimit)
   if (DECL_UNINLINABLE (fn))
     return 0;
 
-  /* Assume it is not inlinable.  */
-  inlinable = 0;
+  /* See if there is any language-specific reason it cannot be
+     inlined.  (It is important that this hook be called early because
+     in C++ it may result in template instantiation.)  */
+  inlinable = !(*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn);
        
   /* We may be here either because fn is declared inline or because
      we use -finline-functions.  For the second case, we are more
@@ -993,7 +995,7 @@ inlinable_function_p (fn, id, nolimit)
 
   /* If we're not inlining things, then nothing is inlinable.  */
   if (! flag_inline_trees)
-    ;
+    inlinable = 0;
   /* If we're not inlining all functions and the function was not
      declared `inline', we don't inline it.  Don't think of
      disregarding DECL_INLINE when flag_inline_trees == 2; it's the
@@ -1001,11 +1003,11 @@ inlinable_function_p (fn, id, nolimit)
      dwarf2out loses if a function is inlined that doesn't have
      DECL_INLINE set.  */
   else if (! DECL_INLINE (fn) && !nolimit)
-    ;
+    inlinable = 0;
 #ifdef INLINER_FOR_JAVA
   /* Synchronized methods can't be inlined.  This is a bug.  */
   else if (METHOD_SYNCHRONIZED (fn))
-    ;
+    inlinable = 0;
 #endif /* INLINER_FOR_JAVA */
   /* We can't inline functions that are too big.  Only allow a single
      function to be of MAX_INLINE_INSNS_SINGLE size.  Make special
@@ -1013,7 +1015,7 @@ inlinable_function_p (fn, id, nolimit)
   else if (!nolimit
           && ! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn)
           && currfn_insns > max_inline_insns_single)
-    ;
+    inlinable = 0;
   /* We can't inline functions that call __builtin_longjmp at all.
      The non-local goto machenery really requires the destination
      be in a different function.  If we allow the function calling
@@ -1021,20 +1023,14 @@ inlinable_function_p (fn, id, nolimit)
      __builtin_setjmp, Things will Go Awry.  */
   /* ??? Need front end help to identify "regular" non-local goto.  */
   else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn)))
-    ;
+    inlinable = 0;
   /* Refuse to inline alloca call unless user explicitly forced so as this may
      change program's memory overhead drastically when the function using alloca
      is called in loop.  In GCC present in SPEC2000 inlining into schedule_block
      cause it to require 2GB of ram instead of 256MB.  */
   else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL
           && find_alloca_call (DECL_SAVED_TREE (fn)))
-    ;
-  /* All is well.  We can inline this function.  Traditionally, GCC
-     has refused to inline functions using alloca, or functions whose
-     values are returned in a PARALLEL, and a few other such obscure
-     conditions.  We are not equally constrained at the tree level.  */
-  else
-    inlinable = 1;
+    inlinable = 0;
 
   /* Squirrel away the result so that we don't have to check again.  */
   DECL_UNINLINABLE (fn) = ! inlinable;
@@ -1065,9 +1061,6 @@ inlinable_function_p (fn, id, nolimit)
        }
     }
 
-  if (inlinable && (*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn))
-    inlinable = 0;
-
   /* If we don't have the function body available, we can't inline
      it.  */
   if (! DECL_SAVED_TREE (fn))