cgraph: A COMDAT decl always has non-zero address.

We should be able to assume that a template instantiation or other COMDAT
has non-zero address even if MAKE_DECL_ONE_ONLY for the target sets
DECL_WEAK and we haven't yet decided to emit a definition in this
translation unit.

	PR c++/92003
	* symtab.c (symtab_node::nonzero_address): A DECL_COMDAT decl has
	non-zero address even if weak and not yet defined.
This commit is contained in:
Jason Merrill 2020-02-05 01:02:22 -05:00
parent b8e165be65
commit 3774c0b934
3 changed files with 28 additions and 5 deletions

View File

@ -1,3 +1,9 @@
2020-02-05 Jason Merrill <jason@redhat.com>
PR c++/92003
* symtab.c (symtab_node::nonzero_address): A DECL_COMDAT decl has
non-zero address even if weak and not yet defined.
2020-02-05 Martin Sebor <msebor@redhat.com>
PR tree-optimization/92765

View File

@ -2058,22 +2058,22 @@ symtab_node::nonzero_address ()
bind to NULL. This is on by default on embedded targets only.
Otherwise all non-WEAK symbols must be defined and thus non-NULL or
linking fails. Important case of WEAK we want to do well are comdats.
Those are handled by later check for definition.
linking fails. Important case of WEAK we want to do well are comdats,
which also must be defined somewhere.
When parsing, beware the cases when WEAK attribute is added later. */
if (!DECL_WEAK (decl)
if ((!DECL_WEAK (decl) || DECL_COMDAT (decl))
&& flag_delete_null_pointer_checks)
{
refuse_visibility_changes = true;
return true;
}
/* If target is defined and either comdat or not extern, we know it will be
/* If target is defined and not extern, we know it will be
output and thus it will bind to non-NULL.
Play safe for flag_delete_null_pointer_checks where weak definition may
be re-defined by NULL. */
if (definition && (!DECL_EXTERNAL (decl) || DECL_COMDAT (decl))
if (definition && !DECL_EXTERNAL (decl)
&& (flag_delete_null_pointer_checks || !DECL_WEAK (decl)))
{
if (!DECL_WEAK (decl))

View File

@ -0,0 +1,17 @@
// PR c++/92003
// { dg-do compile { target c++11 } }
// { dg-prune-output "narrowing conversion" }
constexpr char const* get_c_str() { return "abc"; }
constexpr bool use_get_c_str_in_constexpr_context{get_c_str()}; // works
template <char... Cs>
struct string {
static constexpr char const* c_str() { return c; }
private:
static constexpr char c[]{Cs..., '\0'};
};
constexpr char const* cstr{string<'a', 'b', 'c'>::c_str()};
constexpr bool use_cstr_in_constexpr_context{cstr}; // doesn't work