On Thu, Mar 08, 2018 at 04:06:24PM -0500, Jason Merrill wrote:
> On Thu, Mar 8, 2018 at 1:01 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> > The C FE just warns and doesn't override builtins, but C++ FE
> > on say int __builtin_trap (); will override the builtin, so later
> > builtin_decl_explicit will return the bogus user function which e.g.
> > doesn't have any merged attributes, can have different arguments or
> > return type etc.
> >
> > This patch prevents that; generally the builtins we want to override
> > are the DECL_ANTICIPATED which we handle properly earlier.
> >
> > The testcase in the PR ICEs not because of the argument mismatch (there is
> > none in this case) or return value mismatch (because nothing cares about the
> > return value), but because the new decl lacks noreturn attribute and GCC
> > relies on builtin_decl_explicit (BUILT_IN_TRAP) to be really noreturn.
> >
> > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> > Or shall we error on these, or ignore the name checks and just
> > if (DECL_BUILT_IN (olddecl)) return NULL_TREE;, something else?
> 
> Seems like returning NULL_TREE means that we overload the built-in,
> which also seems undesirable; what if we return olddecl unmodified?
> It would also be good to improve the diagnostic to say that we're
> ignoring the declaration.  Perhaps as a permerror.

So like this (if it passes bootstrap/regtest, though I think we don't have
any tests other than these new ones that cover it anyway, so I don't expect
issues)?

2018-03-09  Jakub Jelinek  <ja...@redhat.com>

        PR c++/84724
        * decl.c (duplicate_decls): Don't override __* prefixed builtins
        except for __[^b]*_chk, instead issue permerror and for -fpermissive
        also a note and return olddecl.

        * g++.dg/ext/pr84724.C: New test.

--- gcc/cp/decl.c.jj    2018-03-08 21:53:44.989559552 +0100
+++ gcc/cp/decl.c       2018-03-09 11:53:58.557156637 +0100
@@ -1566,6 +1566,33 @@ next_arg:;
                   || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
                                 TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
            {
+             /* Don't really override olddecl for __* prefixed builtins
+                except for __[^b]*_chk, the compiler might be using those
+                explicitly.  */
+             if (DECL_BUILT_IN (olddecl))
+               {
+                 tree id = DECL_NAME (olddecl);
+                 const char *name = IDENTIFIER_POINTER (id);
+                 size_t len;
+
+                 if (name[0] == '_'
+                     && name[1] == '_'
+                     && (strncmp (name + 2, "builtin_",
+                                  strlen ("builtin_")) == 0
+                         || (len = strlen (name)) <= strlen ("___chk")
+                         || memcmp (name + len - strlen ("_chk"),
+                                    "_chk", strlen ("_chk") + 1) != 0))
+                   {
+                     if (permerror (DECL_SOURCE_LOCATION (newdecl),
+                                    "new declaration %q#D ambiguates built-in"
+                                    " declaration %q#D", newdecl, olddecl)
+                         && flag_permissive)
+                       inform (DECL_SOURCE_LOCATION (newdecl),
+                               "ignoring the %q#D declaration", newdecl);
+                     return olddecl;
+                   }
+               }
+
              /* A near match; override the builtin.  */
 
              if (TREE_PUBLIC (newdecl))
--- gcc/testsuite/g++.dg/ext/pr84724-1.C.jj     2018-03-09 11:44:49.037993207 
+0100
+++ gcc/testsuite/g++.dg/ext/pr84724-1.C        2018-03-09 11:57:11.599204801 
+0100
@@ -0,0 +1,14 @@
+// PR c++/84724
+// { dg-do compile }
+// { dg-options "-O3 -fpermissive" }
+
+int __builtin_trap ();         // { dg-warning "ambiguates built-in 
declaration" }
+                               // { dg-message "ignoring the 'int 
__builtin_trap\\(\\)' declaration" "" { target *-*-* } .-1 }
+
+int
+foo ()
+{
+  int b;
+  int c (&b);                  // { dg-warning "invalid conversion from" }
+  return b %= b ? c : 0;
+}
--- gcc/testsuite/g++.dg/ext/pr84724-2.C.jj     2018-03-09 11:57:26.017208398 
+0100
+++ gcc/testsuite/g++.dg/ext/pr84724-2.C        2018-03-09 11:57:40.775212078 
+0100
@@ -0,0 +1,14 @@
+// PR c++/84724
+// { dg-do compile }
+// { dg-options "-O3 -fpermissive -w" }
+
+int __builtin_trap ();         // { dg-bogus "ambiguates built-in declaration" 
}
+                               // { dg-bogus "ignoring the 'int 
__builtin_trap\\(\\)' declaration" "" { target *-*-* } .-1 }
+
+int
+foo ()
+{
+  int b;
+  int c (&b);                  // { dg-bogus "invalid conversion from" }
+  return b %= b ? c : 0;
+}
--- gcc/testsuite/g++.dg/ext/pr84724-3.C.jj     2018-03-09 11:57:50.000214382 
+0100
+++ gcc/testsuite/g++.dg/ext/pr84724-3.C        2018-03-09 11:58:10.797219571 
+0100
@@ -0,0 +1,5 @@
+// PR c++/84724
+// { dg-do compile }
+// { dg-options "" }
+
+int __builtin_trap ();         // { dg-error "ambiguates built-in declaration" 
}


        Jakub

Reply via email to