* 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
+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
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);
}
}
+ 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);
/* 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)
}
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
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
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))
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. */
tf_error, /*in_decl=*/NULL_TREE,
/*function_p=*/false);
processing_template_decl = saved_processing_template_decl;
+ r = fold (r);
}
- r = fold (r);
}
}
return r;
{
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
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);
+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.
--- /dev/null
+// PR c++/22252
+// { dg-do link }
+// { dg-additional-sources "interface1a.cc" }
+// { dg-options "-fno-inline" }
+
+#pragma implementation
+#include "interface1.h"
--- /dev/null
+#pragma interface
+struct B
+{
+ B(){};
+ ~B(){}
+};
+struct A {
+ B a;
+
+};
--- /dev/null
+#include "interface1.h"
+A a;
+int main() {}
+