re PR c++/22252 (pragma interface/implementation still break synthesized methods)

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.

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

From-SVN: r104103
This commit is contained in:
Mark Mitchell 2005-09-09 18:56:16 +00:00 committed by Mark Mitchell
parent 7aba8abebf
commit 1ef0df4745
9 changed files with 89 additions and 35 deletions

View 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

View 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

View 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. */

View 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;

View 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);

View 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.

View File

@ -0,0 +1,7 @@
// PR c++/22252
// { dg-do link }
// { dg-additional-sources "interface1a.cc" }
// { dg-options "-fno-inline" }
#pragma implementation
#include "interface1.h"

View File

@ -0,0 +1,10 @@
#pragma interface
struct B
{
B(){};
~B(){}
};
struct A {
B a;
};

View File

@ -0,0 +1,4 @@
#include "interface1.h"
A a;
int main() {}