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:
parent
7aba8abebf
commit
1ef0df4745
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// PR c++/22252
|
||||
// { dg-do link }
|
||||
// { dg-additional-sources "interface1a.cc" }
|
||||
// { dg-options "-fno-inline" }
|
||||
|
||||
#pragma implementation
|
||||
#include "interface1.h"
|
|
@ -0,0 +1,10 @@
|
|||
#pragma interface
|
||||
struct B
|
||||
{
|
||||
B(){};
|
||||
~B(){}
|
||||
};
|
||||
struct A {
|
||||
B a;
|
||||
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
#include "interface1.h"
|
||||
A a;
|
||||
int main() {}
|
||||
|
Loading…
Reference in New Issue