cgraph: A COMDAT decl always has non-zero address.
authorJason Merrill <jason@redhat.com>
Wed, 5 Feb 2020 06:02:22 +0000 (01:02 -0500)
committerJason Merrill <jason@redhat.com>
Thu, 6 Feb 2020 02:22:40 +0000 (21:22 -0500)
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.

gcc/ChangeLog
gcc/symtab.c
gcc/testsuite/g++.dg/cpp0x/constexpr-static13.C [new file with mode: 0644]

index b8fa14e..c31b861 100644 (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
index eae891a..a879c09 100644 (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))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static13.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static13.C
new file mode 100644 (file)
index 0000000..644f9f7
--- /dev/null
@@ -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