Commit 1ef0df47 by Mark Mitchell Committed by Mark Mitchell

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
parent 7aba8abe
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> 2005-09-08 Richard Henderson <rth@redhat.com>
PR debug/23190 PR debug/23190
......
...@@ -10008,6 +10008,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -10008,6 +10008,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
tree current_function_parms; tree current_function_parms;
struct c_fileinfo *finfo struct c_fileinfo *finfo
= get_fileinfo (lbasename (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)))); = get_fileinfo (lbasename (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1))));
bool honor_interface;
/* Sanity check. */ /* Sanity check. */
gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE); gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
...@@ -10222,6 +10223,15 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -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)) if (DECL_INTERFACE_KNOWN (decl1))
{ {
tree ctx = decl_function_context (decl1); tree ctx = decl_function_context (decl1);
...@@ -10238,8 +10248,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -10238,8 +10248,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
/* If this function belongs to an interface, it is public. /* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external. If it belongs to someone else's interface, it is also external.
This only affects inlines and template instantiations. */ This only affects inlines and template instantiations. */
else if (finfo->interface_unknown == 0 else if (!finfo->interface_unknown && honor_interface)
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))
{ {
if (DECL_DECLARED_INLINE_P (decl1) if (DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)
...@@ -10256,7 +10265,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -10256,7 +10265,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
} }
else else
DECL_EXTERNAL (decl1) = 0; DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1; DECL_INTERFACE_KNOWN (decl1) = 1;
/* If this function is in an interface implemented in this file, /* If this function is in an interface implemented in this file,
make sure that the backend knows to emit this function make sure that the backend knows to emit this function
...@@ -10265,7 +10273,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -10265,7 +10273,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
mark_needed (decl1); mark_needed (decl1);
} }
else if (finfo->interface_unknown && finfo->interface_only 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 /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
interface, we will have both finfo->interface_unknown and interface, we will have both finfo->interface_unknown and
......
...@@ -2976,18 +2976,22 @@ cp_finish_file (void) ...@@ -2976,18 +2976,22 @@ cp_finish_file (void)
if (!DECL_SAVED_TREE (decl)) if (!DECL_SAVED_TREE (decl))
continue; continue;
import_export_decl (decl);
/* We lie to the back-end, pretending that some functions /* We lie to the back-end, pretending that some functions
are not defined when they really are. This keeps these are not defined when they really are. This keeps these
functions from being put out unnecessarily. But, we must functions from being put out unnecessarily. But, we must
stop lying when the functions are referenced, or if they stop lying when the functions are referenced, or if they
are not comdat since they need to be put out now. This are not comdat since they need to be put out now. If
is done in a separate for cycle, because if some deferred DECL_INTERFACE_KNOWN, then we have already set
function is contained in another deferred function later DECL_EXTERNAL appropriately, so there's no need to check
in deferred_fns varray, rest_of_compilation would skip again, and we do not want to clear DECL_EXTERNAL if a
this function and we really cannot expand the same previous call to import_export_decl set it.
function twice. */
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) if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl) && DECL_INITIAL (decl)
&& decl_needed_p (decl)) && decl_needed_p (decl))
...@@ -3047,13 +3051,12 @@ cp_finish_file (void) ...@@ -3047,13 +3051,12 @@ cp_finish_file (void)
TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
/* But not defined. */ /* But not defined. */
&& DECL_REALLY_EXTERN (decl) && DECL_REALLY_EXTERN (decl)
/* If we decided to emit this function in another /* If the definition actually was available here, then the
translation unit, the fact that the definition was fact that the function was not defined merely represents
missing here likely indicates only that the repository that for some reason (use of a template repository,
decided to place the function elsewhere. With -Winline, #pragma interface, etc.) we decided not to emit the
we will still warn if we could not inline the definition here. */
function. */ && !DECL_INITIAL (decl)
&& !flag_use_repository
/* An explicit instantiation can be used to specify /* An explicit instantiation can be used to specify
that the body is in another unit. It will have that the body is in another unit. It will have
already verified there was a definition. */ already verified there was a definition. */
......
...@@ -5939,8 +5939,8 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -5939,8 +5939,8 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
tf_error, /*in_decl=*/NULL_TREE, tf_error, /*in_decl=*/NULL_TREE,
/*function_p=*/false); /*function_p=*/false);
processing_template_decl = saved_processing_template_decl; processing_template_decl = saved_processing_template_decl;
r = fold (r);
} }
r = fold (r);
} }
} }
return r; return r;
......
...@@ -2259,20 +2259,6 @@ note_decl_for_pch (tree decl) ...@@ -2259,20 +2259,6 @@ note_decl_for_pch (tree decl)
{ {
gcc_assert (pch_file); 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 /* There's a good chance that we'll have to mangle names at some
point, even if only for emission in debugging information. */ point, even if only for emission in debugging information. */
if (TREE_CODE (decl) == VAR_DECL if (TREE_CODE (decl) == VAR_DECL
...@@ -3041,11 +3027,28 @@ expand_or_defer_fn (tree fn) ...@@ -3041,11 +3027,28 @@ expand_or_defer_fn (tree fn)
these functions so that it can inline them as appropriate. */ these functions so that it can inline them as appropriate. */
if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn)) 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_EXTERNAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1;
note_vague_linkage_fn (fn); 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 else
import_export_decl (fn); 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> 2005-09-09 Thomas Koenig <Thomas.Koenig@online.de>
* gfortran.dg/iomsg_1.f90: New test case. * gfortran.dg/iomsg_1.f90: New test case.
// PR c++/22252
// { dg-do link }
// { dg-additional-sources "interface1a.cc" }
// { dg-options "-fno-inline" }
#pragma implementation
#include "interface1.h"
#pragma interface
struct B
{
B(){};
~B(){}
};
struct A {
B a;
};
#include "interface1.h"
A a;
int main() {}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment