This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Disallow redefinition of decls etc. in __builtin_* namespace (PR c/32455)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard Henderson <rth at redhat dot com>
- Date: Fri, 14 Nov 2008 17:35:20 +0100
- Subject: [PATCH] Disallow redefinition of decls etc. in __builtin_* namespace (PR c/32455)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
This is Richard's patch from February extended to complain about
{struct,class,union,enum} __builtin_something.
When Richard posted this patch, I've objected that glibc used
to redefine a few __builtin_* functions to add __asm redirection to them,
but since then glibc has been changed not to do that (apparently,
the __builtin_fwrite{,_unlocked} redefinition was just a workaround for 3.x
ERA gcc bugs and isn't needed for 4.1-4.4), so current 2.9 release
doesn't need it.
I've bootstrapped/regtested this on x86_64-linux, ok for trunk?
2008-11-14 Richard Henderson <rth@redhat.com>
Jakub Jelinek <jakub@redhat.com>
PR c/32455
* c-common.c (builtin_name_p): New.
(disable_builtin_function, def_builtin_1): Use it.
* c-common.h (builtin_name_p): Declare.
* c-decl.c (pushtag, grokdeclarator): Deny declarations w/
builtin_name_p.
(grokfield): Create an error field when grokdeclarator fails.
* decl.c (grokdeclarator): Deny declarations w/ builtin_name_p.
* name-lookup.c (pushtag): Likewise.
* g++.old-deja/g++.law/operators24.C: Remove.
* gcc.dg/torture/builtin-convert-3.c: Don't declare __builtin's.
* gcc.dg/torture/builtin-nonneg-1.c: Likewise.
* gcc.dg/pr32455-1.c: New test.
* gcc.dg/pr32455-2.c: New test.
* g++.dg/parse/builtin3.C: New test.
* g++.dg/parse/builtin4.C: New test.
--- gcc/c-decl.c.jj 2008-11-10 10:28:19.000000000 +0100
+++ gcc/c-decl.c 2008-11-14 13:15:04.000000000 +0100
@@ -946,7 +946,14 @@ pushtag (tree name, tree type)
{
/* Record the identifier as the type's name if it has none. */
if (name && !TYPE_NAME (type))
- TYPE_NAME (type) = name;
+ {
+ if (builtin_name_p (IDENTIFIER_POINTER (name)))
+ {
+ error ("%qs is a reserved name", IDENTIFIER_POINTER (name));
+ return;
+ }
+ TYPE_NAME (type) = name;
+ }
bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
@@ -4028,9 +4035,14 @@ grokdeclarator (const struct c_declarato
name = "type name";
}
+ if (name && builtin_name_p (name))
+ {
+ error ("%qs is a reserved name", name);
+ return 0;
+ }
+
/* A function definition's declarator must have the form of
a function declarator. */
-
if (funcdef_flag && !funcdef_syntax)
return 0;
@@ -5443,8 +5455,13 @@ grokfield (location_t loc,
width ? &width : NULL, decl_attrs,
DEPRECATED_NORMAL);
- finish_decl (value, NULL_TREE, NULL_TREE);
- DECL_INITIAL (value) = width;
+ if (value == 0)
+ value = build_decl (FIELD_DECL, NULL_TREE, error_mark_node);
+ else
+ {
+ finish_decl (value, NULL_TREE, NULL_TREE);
+ DECL_INITIAL (value) = width;
+ }
return value;
}
--- gcc/cp/name-lookup.c.jj 2008-10-23 13:21:09.000000000 +0200
+++ gcc/cp/name-lookup.c 2008-11-14 14:11:05.000000000 +0100
@@ -5015,6 +5015,12 @@ pushtag (tree name, tree type, tag_scope
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ if (builtin_name_p (IDENTIFIER_POINTER (name)))
+ {
+ error ("%qs is a reserved name", IDENTIFIER_POINTER (name));
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ }
+
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
--- gcc/cp/decl.c.jj 2008-11-13 15:02:46.000000000 +0100
+++ gcc/cp/decl.c 2008-11-14 12:59:10.000000000 +0100
@@ -7716,6 +7716,12 @@ grokdeclarator (const cp_declarator *dec
break;
}
+ if (name && builtin_name_p (name))
+ {
+ error ("%qs is a reserved name", name);
+ return error_mark_node;
+ }
+
/* [dcl.fct.edf]
The declarator in a function-definition shall have the form
--- gcc/c-common.c.jj 2008-11-14 11:56:59.000000000 +0100
+++ gcc/c-common.c 2008-11-14 12:59:10.000000000 +0100
@@ -4439,13 +4439,19 @@ static disabled_builtin *disabled_builti
static bool builtin_function_disabled_p (const char *);
+bool
+builtin_name_p (const char *name)
+{
+ return strncmp (name, "__builtin_", strlen ("__builtin_")) == 0;
+}
+
/* Disable a built-in function specified by -fno-builtin-NAME. If NAME
begins with "__builtin_", give an error. */
void
disable_builtin_function (const char *name)
{
- if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
+ if (builtin_name_p (name))
error ("cannot disable built-in function %qs", name);
else
{
@@ -4492,9 +4498,7 @@ def_builtin_1 (enum built_in_function fn
if (fntype == error_mark_node)
return;
- gcc_assert ((!both_p && !fallback_p)
- || !strncmp (name, "__builtin_",
- strlen ("__builtin_")));
+ gcc_assert ((!both_p && !fallback_p) || builtin_name_p (name));
libname = name + strlen ("__builtin_");
decl = add_builtin_function (name, fntype, fncode, fnclass,
--- gcc/c-common.h.jj 2008-11-10 10:28:19.000000000 +0100
+++ gcc/c-common.h 2008-11-14 12:59:10.000000000 +0100
@@ -684,6 +684,7 @@ extern const struct attribute_spec c_com
extern tree (*make_fname_decl) (tree, int);
+extern bool builtin_name_p (const char *);
extern tree identifier_global_value (tree);
extern void record_builtin_type (enum rid, const char *, tree);
extern tree build_void_list_node (void);
--- gcc/testsuite/gcc.dg/pr32455-2.c.jj 2008-11-14 12:59:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr32455-2.c 2008-11-14 13:52:03.000000000 +0100
@@ -0,0 +1,30 @@
+/* PR c/32455 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int __builtin_type; /* { dg-error "reserved" } */
+
+struct __builtin_struct
+{ /* { dg-error "reserved" } */
+ int x;
+ int __builtin_field; /* { dg-error "reserved" } */
+} s;
+
+union __builtin_struct2; /* { dg-error "reserved" } */
+
+enum __builtin_enum
+{ /* { dg-error "reserved" } */
+ E = 0
+};
+
+int __builtin_var = 1; /* { dg-error "reserved" } */
+
+extern void __builtin_func_decl (void); /* { dg-error "reserved" } */
+
+/* ??? We get multiple errors here, cause we forget it's supposed
+ to be a function type we're declaring... */
+void __builtin_func_defn (void)
+{ /* { dg-error "reserved|expected" } */
+}
+
+/* { dg-warning "unnamed" "" { target *-*-* } 13 } */
--- gcc/testsuite/gcc.dg/torture/builtin-convert-3.c.jj 2008-11-10 10:28:19.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/builtin-convert-3.c 2008-11-14 12:59:10.000000000 +0100
@@ -20,7 +20,6 @@
argument is a narrower type (perhaps implicitly) cast to a wider
one. */
#define INNER_CAST1(MATHFN, RET) \
- PROTOTYPE1_RET (MATHFN, RET); \
extern void link_failure_inner_##MATHFN##l_##MATHFN(void); \
extern void link_failure_inner_##MATHFN##l_##MATHFN##f(void); \
extern void link_failure_inner_##MATHFN##_##MATHFN##f(void); \
@@ -37,6 +36,10 @@
&& MATHFN(f1) != MATHFN##f(f1)) \
link_failure_inner_##MATHFN##_##MATHFN##f()
+#define INNER_CAST2(MATHFN, RET) \
+ PROTOTYPE1_RET (MATHFN, RET) \
+ INNER_CAST1 (MATHFN, RET)
+
void __attribute__ ((__noinline__)) test (double d1, float f1)
{
#ifdef __OPTIMIZE__
@@ -46,10 +49,10 @@ void __attribute__ ((__noinline__)) test
INNER_CAST1 (__builtin_llceil, long long);
INNER_CAST1 (__builtin_lfloor, long);
INNER_CAST1 (__builtin_llfloor, long long);
- INNER_CAST1 (lround, long);
- INNER_CAST1 (llround, long long);
- INNER_CAST1 (lrint, long);
- INNER_CAST1 (llrint, long long);
+ INNER_CAST2 (lround, long);
+ INNER_CAST2 (llround, long long);
+ INNER_CAST2 (lrint, long);
+ INNER_CAST2 (llrint, long long);
#endif /* HAVE_C99_RUNTIME */
#endif /* __OPTIMIZE__ */
}
--- gcc/testsuite/gcc.dg/torture/builtin-nonneg-1.c.jj 2008-11-10 10:28:19.000000000 +0100
+++ gcc/testsuite/gcc.dg/torture/builtin-nonneg-1.c 2008-11-14 12:59:10.000000000 +0100
@@ -55,6 +55,11 @@ void test(double d1, double d2, float f1
if (signbit(FN(d1)) || signbitf(FN##f(f1)) || signbitl(FN##l(ld1))) \
link_failure_##FN()
+#define _ITEST1(FN) \
+ extern void link_failure_##FN (void); \
+ if (signbit(FN(d1)) || signbitf(FN##l(f1)) || signbitl(FN##ll(ld1))) \
+ link_failure_##FN()
+
#define ITEST1(FN) \
extern void link_failure_##FN (void); IPROTOTYPE(FN) \
if (signbit(FN(d1)) || signbitf(FN##l(f1)) || signbitl(FN##ll(ld1))) \
@@ -74,8 +79,8 @@ void test(double d1, double d2, float f1
TEST1 (pow10);
TEST1 (sqrt);
ITEST1 (ffs);
- ITEST1 (__builtin_parity);
- ITEST1 (__builtin_popcount);
+ _ITEST1 (__builtin_parity);
+ _ITEST1 (__builtin_popcount);
/* These are nonnegative if the first argument is. */
#define ARG1TEST1(FN) \
@@ -85,6 +90,12 @@ void test(double d1, double d2, float f1
link_failure_##FN()
/* Same, but allow specifying the return type. */
+#define _ARG1TEST1_RTYPE(FN,RTYPE) \
+ extern void link_failure_##FN (void); \
+ if (signbit(FN(fabs(d1))) || signbitf(FN##f(fabsf(f1))) \
+ || signbitl(FN##l(fabsl(ld1)))) \
+ link_failure_##FN()
+
#define ARG1TEST1_RTYPE(FN,RTYPE) \
extern void link_failure_##FN (void); PROTOTYPE_RTYPE(FN,RTYPE) \
if (signbit(FN(fabs(d1))) || signbitf(FN##f(fabsf(f1))) \
@@ -144,12 +155,12 @@ void test(double d1, double d2, float f1
ARG1TEST1 (floor);
ARG1TEST2 (fmod);
ARG1TEST2_A2INT (ldexp, int);
- ARG1TEST1_RTYPE (__builtin_llceil, long long);
- ARG1TEST1_RTYPE (__builtin_llfloor, long long);
+ _ARG1TEST1_RTYPE (__builtin_llceil, long long);
+ _ARG1TEST1_RTYPE (__builtin_llfloor, long long);
ARG1TEST1_RTYPE (llrint, long long);
ARG1TEST1_RTYPE (llround, long long);
- ARG1TEST1_RTYPE (__builtin_lceil, long);
- ARG1TEST1_RTYPE (__builtin_lfloor, long);
+ _ARG1TEST1_RTYPE (__builtin_lceil, long);
+ _ARG1TEST1_RTYPE (__builtin_lfloor, long);
ARG1TEST1_RTYPE (lrint, long);
ARG1TEST1_RTYPE (lround, long);
/* The modf* functions aren't ever "const" or "pure" even with
--- gcc/testsuite/gcc.dg/pr32455-1.c.jj 2008-11-14 12:59:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr32455-1.c 2008-11-14 13:53:56.000000000 +0100
@@ -0,0 +1,15 @@
+/* PR c/32455 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef double* va_list;
+
+void __builtin_va_start(va_list, ...); /* { dg-error "reserved" } */
+
+void foo(const char* s, ...)
+{
+ va_list v;
+ __builtin_va_start(v, s); /* { dg-message "note: expected" } */
+}
+
+/* { dg-warning "from incompatible pointer" "" { target *-*-* } 12 } */
--- gcc/testsuite/g++.dg/parse/builtin3.C.jj 2008-11-14 14:15:18.000000000 +0100
+++ gcc/testsuite/g++.dg/parse/builtin3.C 2008-11-14 14:14:35.000000000 +0100
@@ -0,0 +1,13 @@
+// PR c/32455
+// { dg-do compile }
+// { dg-options "" }
+
+typedef double* va_list;
+
+void __builtin_va_start(va_list, ...); // { dg-error "reserved" }
+
+void foo(const char* s, ...)
+{
+ va_list v;
+ __builtin_va_start(v, s); // { dg-error "cannot convert" }
+}
--- gcc/testsuite/g++.dg/parse/builtin4.C.jj 2008-11-14 14:15:21.000000000 +0100
+++ gcc/testsuite/g++.dg/parse/builtin4.C 2008-11-14 14:13:38.000000000 +0100
@@ -0,0 +1,30 @@
+// PR c/32455
+// { dg-do compile }
+// { dg-options "" }
+
+typedef int __builtin_type; // { dg-error "reserved" }
+
+struct __builtin_struct // { dg-error "reserved" }
+{
+ int x;
+};
+
+struct Z
+{
+ int __builtin_field; // { dg-error "reserved" }
+};
+
+union __builtin_struct2; // { dg-error "reserved" }
+
+enum __builtin_enum // { dg-error "reserved" }
+{
+ E = 0
+};
+
+int __builtin_var = 1; // { dg-error "reserved" }
+
+extern void __builtin_func_decl (void); // { dg-error "reserved" }
+
+void __builtin_func_defn (void) // { dg-error "reserved" }
+{
+}
--- gcc/testsuite/g++.old-deja/g++.law/operators24.C.jj 2008-11-10 10:28:19.000000000 +0100
+++ gcc/testsuite/g++.old-deja/g++.law/operators24.C 2008-11-14 12:59:10.000000000 +0100
@@ -1,14 +0,0 @@
-// { dg-do assemble }
-// GROUPS passed operators
-// opr-new file
-// From: rwave!myersn%rwave.roguewave@cs.orst.edu (Nathan Myers)
-// Date: Wed, 16 Dec 92 11:55 PST
-// Subject: 2.3.2: friend decl breaks member op new
-// Message-ID: <m0n24qP-0000GmC@rwave.roguewave.com>
-
-#include <stddef.h>
-struct Link {
- void* operator new(size_t, int);
- friend void* __builtin_new(size_t); // This declaration triggers the bug
-};
-void f() { new(2) Link; }
Jakub