PR c++/22252
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Sep 2005 18:56:16 +0000 (18:56 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Sep 2005 18:56:16 +0000 (18:56 +0000)
* decl.c (start_preparsed_function): Do not pay attention to
#pragma interface for implicitly-defined methods.
* decl2.c (cp_finish_file): Do not complain about uses of inline
functions that have bodies, even if we decided not to emit the
body in this translation unit.
* semantics.c (note_decl_for_pch): Do not mess with linkage.
(expand_or_defer_fn): Make inline, non-template functions COMDAT
at this point.

PR c++/22252
* g++.dg/ext/interface1.C: New test.
* g++.dg/ext/interface1.h: Likewise.
* g++.dg/ext/interface1a.cc: Likewise.

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

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/interface1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/interface1.h [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/interface1a.cc [new file with mode: 0644]

index 2967e18..ae12c20 100644 (file)
@@ -1,3 +1,15 @@
+2005-09-09  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/22252
+       * decl.c (start_preparsed_function): Do not pay attention to
+       #pragma interface for implicitly-defined methods.
+       * decl2.c (cp_finish_file): Do not complain about uses of inline
+       functions that have bodies, even if we decided not to emit the
+       body in this translation unit.
+       * semantics.c (note_decl_for_pch): Do not mess with linkage.
+       (expand_or_defer_fn): Make inline, non-template functions COMDAT
+       at this point.
+
 2005-09-08  Richard Henderson  <rth@redhat.com>
 
        PR debug/23190
index 50c1fd6..f332761 100644 (file)
@@ -10008,6 +10008,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   tree current_function_parms;
   struct c_fileinfo *finfo
     = get_fileinfo (lbasename (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1))));
+  bool honor_interface;
 
   /* Sanity check.  */
   gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
@@ -10222,6 +10223,15 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        }
     }
 
+  honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
+                    /* Implicitly-defined methods (like the
+                       destructor for a class in which no destructor
+                       is explicitly declared) must not be defined
+                       until their definition is needed.  So, we
+                       ignore interface specifications for
+                       compiler-generated functions.  */
+                    && !DECL_ARTIFICIAL (decl1));
+                    
   if (DECL_INTERFACE_KNOWN (decl1))
     {
       tree ctx = decl_function_context (decl1);
@@ -10238,8 +10248,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   /* If this function belongs to an interface, it is public.
      If it belongs to someone else's interface, it is also external.
      This only affects inlines and template instantiations.  */
-  else if (finfo->interface_unknown == 0
-          && ! DECL_TEMPLATE_INSTANTIATION (decl1))
+  else if (!finfo->interface_unknown && honor_interface)
     {
       if (DECL_DECLARED_INLINE_P (decl1)
          || DECL_TEMPLATE_INSTANTIATION (decl1)
@@ -10256,7 +10265,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        }
       else
        DECL_EXTERNAL (decl1) = 0;
-      DECL_NOT_REALLY_EXTERN (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
       /* If this function is in an interface implemented in this file,
         make sure that the backend knows to emit this function
@@ -10265,7 +10273,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        mark_needed (decl1);
     }
   else if (finfo->interface_unknown && finfo->interface_only
-          && ! DECL_TEMPLATE_INSTANTIATION (decl1))
+          && honor_interface)
     {
       /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
         interface, we will have both finfo->interface_unknown and
index afb747f..8a7d7d6 100644 (file)
@@ -2976,18 +2976,22 @@ cp_finish_file (void)
          if (!DECL_SAVED_TREE (decl))
            continue;
 
-         import_export_decl (decl);
-
          /* We lie to the back-end, pretending that some functions
             are not defined when they really are.  This keeps these
             functions from being put out unnecessarily.  But, we must
             stop lying when the functions are referenced, or if they
-            are not comdat since they need to be put out now.  This
-            is done in a separate for cycle, because if some deferred
-            function is contained in another deferred function later
-            in deferred_fns varray, rest_of_compilation would skip
-            this function and we really cannot expand the same
-            function twice.  */
+            are not comdat since they need to be put out now.  If
+            DECL_INTERFACE_KNOWN, then we have already set
+            DECL_EXTERNAL appropriately, so there's no need to check
+            again, and we do not want to clear DECL_EXTERNAL if a
+            previous call to import_export_decl set it.
+            
+            This is done in a separate for cycle, because if some
+            deferred function is contained in another deferred
+            function later in deferred_fns varray,
+            rest_of_compilation would skip this function and we
+            really cannot expand the same function twice.  */
+         import_export_decl (decl);
          if (DECL_NOT_REALLY_EXTERN (decl)
              && DECL_INITIAL (decl)
              && decl_needed_p (decl))
@@ -3047,13 +3051,12 @@ cp_finish_file (void)
          TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
          /* But not defined.  */
          && DECL_REALLY_EXTERN (decl)
-         /* If we decided to emit this function in another
-            translation unit, the fact that the definition was
-            missing here likely indicates only that the repository
-            decided to place the function elsewhere.  With -Winline,
-            we will still warn if we could not inline the
-            function.  */
-         && !flag_use_repository
+         /* If the definition actually was available here, then the
+            fact that the function was not defined merely represents
+            that for some reason (use of a template repository,
+            #pragma interface, etc.) we decided not to emit the
+            definition here.  */
+         && !DECL_INITIAL (decl)
          /* An explicit instantiation can be used to specify
             that the body is in another unit. It will have
             already verified there was a definition.  */
index d6ab9df..f78da93 100644 (file)
@@ -5939,8 +5939,8 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                                         tf_error, /*in_decl=*/NULL_TREE,
                                         /*function_p=*/false);
              processing_template_decl = saved_processing_template_decl;
+             r = fold (r);
            }
-         r = fold (r);
        }
     }
   return r;
index c7fd1bb..3691457 100644 (file)
@@ -2259,20 +2259,6 @@ note_decl_for_pch (tree decl)
 {
   gcc_assert (pch_file);
 
-  /* A non-template inline function with external linkage will always
-     be COMDAT.  As we must eventually determine the linkage of all
-     functions, and as that causes writes to the data mapped in from
-     the PCH file, it's advantageous to mark the functions at this
-     point.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && TREE_PUBLIC (decl)
-      && DECL_DECLARED_INLINE_P (decl)
-      && !DECL_IMPLICIT_INSTANTIATION (decl))
-    {
-      comdat_linkage (decl);
-      DECL_INTERFACE_KNOWN (decl) = 1;
-    }
-
   /* There's a good chance that we'll have to mangle names at some
      point, even if only for emission in debugging information.  */
   if (TREE_CODE (decl) == VAR_DECL
@@ -3041,11 +3027,28 @@ expand_or_defer_fn (tree fn)
      these functions so that it can inline them as appropriate.  */
   if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn))
     {
-      if (!at_eof)
+      if (DECL_INTERFACE_KNOWN (fn))
+       /* We've already made a decision as to how this function will
+          be handled.  */;
+      else if (!at_eof)
        {
          DECL_EXTERNAL (fn) = 1;
          DECL_NOT_REALLY_EXTERN (fn) = 1;
          note_vague_linkage_fn (fn);
+         /* A non-template inline function with external linkage will
+            always be COMDAT.  As we must eventually determine the
+            linkage of all functions, and as that causes writes to
+            the data mapped in from the PCH file, it's advantageous
+            to mark the functions at this point.  */
+         if (!DECL_IMPLICIT_INSTANTIATION (fn))
+           {
+             /* This function must have external linkage, as
+                otherwise DECL_INTERFACE_KNOWN would have been
+                set.  */
+             gcc_assert (TREE_PUBLIC (fn));
+             comdat_linkage (fn);
+             DECL_INTERFACE_KNOWN (fn) = 1;
+           }
        }
       else
        import_export_decl (fn);
index da40a59..3942c33 100644 (file)
@@ -1,3 +1,10 @@
+2005-09-09  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/22252
+       * g++.dg/ext/interface1.C: New test.
+       * g++.dg/ext/interface1.h: Likewise.
+       * g++.dg/ext/interface1a.cc: Likewise.
+
 2005-09-09  Thomas Koenig  <Thomas.Koenig@online.de>
 
        * gfortran.dg/iomsg_1.f90:  New test case.
diff --git a/gcc/testsuite/g++.dg/ext/interface1.C b/gcc/testsuite/g++.dg/ext/interface1.C
new file mode 100644 (file)
index 0000000..0f803ab
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/22252
+// { dg-do link }
+// { dg-additional-sources "interface1a.cc" }
+// { dg-options "-fno-inline" }
+
+#pragma implementation 
+#include "interface1.h"
diff --git a/gcc/testsuite/g++.dg/ext/interface1.h b/gcc/testsuite/g++.dg/ext/interface1.h
new file mode 100644 (file)
index 0000000..ce91527
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma interface
+struct B
+{
+  B(){};
+  ~B(){}
+};
+struct A {
+  B a;
+
+};
diff --git a/gcc/testsuite/g++.dg/ext/interface1a.cc b/gcc/testsuite/g++.dg/ext/interface1a.cc
new file mode 100644 (file)
index 0000000..1859d5c
--- /dev/null
@@ -0,0 +1,4 @@
+#include "interface1.h"
+A a;
+int main() {}
+