2015-06-21 Martin Sebor <msebor@redhat.com>
PR c/66516
* c/c-typeck.c (default_function_array_conversion): Reject
converting a builtin function to a pointer.
(parser_build_unary_op): Reject taking the address of a builtin
function.
* cp/call.c (convert_like_real): Reject converting a builtin function
to a pointer.
(initialize_reference): Reject initializing a reference with a builtin
function.
* cp/typeck.c (cp_build_addr_expr_strict): Reject taking the address
of a builtin function.
(build_reinterpret_cast_1): Reject casting a builtin function to
a pointer.
(convert_for_initialization): Reject initializing a pointer with
the a builtin function.
@@ -58,6 +58,8 @@ along with GCC; see the file COPYING3. If not see
#include "cilk.h"
#include "gomp-constants.h"
+#include <stdlib.h>
+
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
enum impl_conv {
@@ -1940,6 +1942,12 @@ default_function_array_conversion (location_t loc, struct c_expr exp)
}
break;
case FUNCTION_TYPE:
+ if (DECL_IS_BUILTIN (exp.value))
+ {
+ error_at (loc, "converting builtin function to a pointer");
+ exp.value = error_mark_node;
+ }
+ else
exp.value = function_to_pointer_conversion (loc, exp.value);
break;
default:
@@ -3384,7 +3392,14 @@ parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
result.original_code = code;
result.original_type = NULL;
- if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
+ if (code == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (arg.value)) == FUNCTION_TYPE
+ && DECL_IS_BUILTIN (arg.value))
+ {
+ error_at (loc, "taking address of a builtin function");
+ result.value = error_mark_node;
+ }
+ else if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
overflow_warning (loc, result.value);
return result;
@@ -6570,6 +6570,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
expr = build_target_expr_with_type (expr, type, complain);
}
+ if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
+ && DECL_P (expr) && DECL_IS_BUILTIN (expr))
+ {
+ error_at (input_location, "taking address of a builtin function");
+ return error_mark_node;
+ }
+
/* Take the address of the thing to which we will bind the
reference. */
expr = cp_build_addr_expr (expr, complain);
@@ -9768,8 +9775,18 @@ initialize_reference (tree type, tree expr,
}
if (conv->kind == ck_ref_bind)
+ {
+ if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
+ && DECL_P (expr) && DECL_IS_BUILTIN (expr))
+ {
+ error_at (input_location, "invalid initialization of a reference "
+ "with a builtin function");
+ return error_mark_node;
+ }
+
/* Perform the conversion. */
expr = convert_like (conv, expr, complain);
+ }
else if (conv->kind == ck_ambig)
/* We gave an error in build_user_type_conversion_1. */
expr = error_mark_node;
@@ -5621,6 +5621,13 @@ cp_build_addr_expr (tree arg, tsubst_flags_t complain)
static tree
cp_build_addr_expr_strict (tree arg, tsubst_flags_t complain)
{
+ if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
+ && DECL_P (arg) && DECL_IS_BUILTIN (arg))
+ {
+ error_at (input_location, "taking address of a builtin function");
+ return error_mark_node;
+ }
+
return cp_build_addr_expr_1 (arg, 1, complain);
}
@@ -6860,6 +6867,14 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|| VOID_TYPE_P (TREE_TYPE (type))))
return convert_member_func_to_ptr (type, expr, complain);
+ if (TREE_CODE (intype) == FUNCTION_TYPE
+ && DECL_P (expr) && DECL_IS_BUILTIN (expr))
+ {
+ error_at (EXPR_LOC_OR_LOC (expr, input_location),
+ "taking address of a builtin function");
+ return error_mark_node;
+ }
+
/* If the cast is not to a reference type, the lvalue-to-rvalue,
array-to-pointer, and function-to-pointer conversions are
performed. */
@@ -8307,6 +8322,13 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
|| (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
return error_mark_node;
+ if (TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
+ && DECL_P (rhs) && DECL_IS_BUILTIN (rhs))
+ {
+ error_at (input_location, "taking address of a builtin function");
+ return error_mark_node;
+ }
+
if ((TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
&& TREE_CODE (type) != ARRAY_TYPE
&& (TREE_CODE (type) != REFERENCE_TYPE
2015-06-21 Martin Sebor <msebor@redhat.com>
PR c/66516
* gcc.dg/addr_builtin-pr66516.c: New test.
* g++.dg/addr_builtin-pr66516.C: New test.
new file mode 100644
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+
+/* Verify that taking the address of a builtin function generates
+ a compilation error. */
+
+#if 201103L <= __cplusplus
+
+bool func (void)
+{
+ /* Taking the address of builtin constants is valid. */
+ return &__func__ == &__func__; /* { dg-bogus "builtin" } */
+}
+
+#endif
+
+/* Calling the builtins is valid. */
+int foo (int i)
+{
+ const void* p = 0;
+
+ switch (i & 0xf) {
+ case 0: i = __builtin_expect (i, 0); /* { dg-bogus "builtin" } */
+ case 1: p = __builtin_return_address (0); /* { dg-bogus "builtin" } */
+ case 2: i = __builtin_strlen (""); /* { dg-bogus "builtin" } */
+ case 3: p = __builtin_FILE (); /* { dg-bogus "builtin" } */
+ case 4: p = __builtin_FUNCTION (); /* { dg-bogus "builtin" } */
+ case 5: i = __builtin_LINE (); /* { dg-bogus "builtin" } */
+ }
+ return p ? *(int*)p : i;
+}
+
+void* const addr[] = {
+ (void*)__builtin_expect, /* { dg-error "builtin" } */
+ (void*)__builtin_return_address, /* { dg-error "builtin" } */
+ (void*)__atomic_load, /* { dg-error "builtin" } */
+ (void*)__builtin_add_overflow, /* { dg-error "builtin" } */
+ (void*)__builtin_constant_p, /* { dg-error "builtin" } */
+ (void*)__builtin_nanf, /* { dg-error "builtin" } */
+ (void*)__builtin_strlen, /* { dg-error "builtin" } */
+ (void*)__builtin_unreachable, /* { dg-error "builtin" } */
+ (void*)__builtin_FILE, /* { dg-error "builtin" } */
+ (void*)__builtin_FUNCTION, /* { dg-error "builtin" } */
+ (void*)__builtin_LINE, /* { dg-error "builtin" } */
+
+ (void*)&__builtin_expect, /* { dg-error "builtin" } */
+ (void*)&__builtin_return_address, /* { dg-error "builtin" } */
+ (void*)&__atomic_load, /* { dg-error "builtin" } */
+ (void*)&__builtin_add_overflow, /* { dg-error "builtin" } */
+ (void*)&__builtin_constant_p, /* { dg-error "builtin" } */
+ (void*)&__builtin_nanf, /* { dg-error "builtin" } */
+ (void*)&__builtin_strlen, /* { dg-error "builtin" } */
+ (void*)&__builtin_unreachable, /* { dg-error "builtin" } */
+ (void*)&__builtin_FILE, /* { dg-error "builtin" } */
+ (void*)&__builtin_FUNCTION, /* { dg-error "builtin" } */
+ (void*)&__builtin_LINE, /* { dg-error "builtin" } */
+
+ reinterpret_cast<void*>(__builtin_expect), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_return_address), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__atomic_load), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_add_overflow), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_constant_p), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_nanf), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_strlen), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_unreachable), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_FILE), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_FUNCTION), /* { dg-error "builtin" } */
+ reinterpret_cast<void*>(__builtin_LINE), /* { dg-error "builtin" } */
+
+ 0
+};
new file mode 100644
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+
+/* Verify that taking the address of a builtin function generates
+ a compilation error. */
+
+#if 199901L <= __STDC_VERSION__
+
+int func (void)
+{
+ /* Taking the address of builtin constants is valid. */
+ return &__func__ == &__func__; /* { dg-bogus "builtin" } */
+}
+
+#endif
+
+
+/* Calling the builtins is valid. */
+int foo (int i)
+{
+ const void* p = 0;
+
+ switch (i & 0xf) {
+ case 0: i = __builtin_expect (i, 0); /* { dg-bogus "builtin" } */
+ case 1: p = __builtin_return_address (0); /* { dg-bogus "builtin" } */
+ case 2: i = __builtin_strlen (""); /* { dg-bogus "builtin" } */
+ case 3: p = __builtin_FILE (); /* { dg-bogus "builtin" } */
+ case 4: p = __builtin_FUNCTION (); /* { dg-bogus "builtin" } */
+ case 5: i = __builtin_LINE (); /* { dg-bogus "builtin" } */
+ }
+ return p ? *(int*)p : i;
+}
+
+void* const addr[] = {
+ (void*)__builtin_expect, /* { dg-error "builtin" } */
+ (void*)__builtin_return_address, /* { dg-error "builtin" } */
+ (void*)__atomic_load, /* { dg-error "builtin" } */
+ (void*)__builtin_add_overflow, /* { dg-error "builtin" } */
+ (void*)__builtin_constant_p, /* { dg-error "builtin" } */
+ (void*)__builtin_nanf, /* { dg-error "builtin" } */
+ (void*)__builtin_strlen, /* { dg-error "builtin" } */
+ (void*)__builtin_unreachable, /* { dg-error "builtin" } */
+ (void*)__builtin_FILE, /* { dg-error "builtin" } */
+ (void*)__builtin_FUNCTION, /* { dg-error "builtin" } */
+ (void*)__builtin_LINE, /* { dg-error "builtin" } */
+
+ (void*)&__builtin_expect, /* { dg-error "builtin" } */
+ (void*)&__builtin_return_address, /* { dg-error "builtin" } */
+ (void*)&__atomic_load, /* { dg-error "builtin" } */
+ (void*)&__builtin_add_overflow, /* { dg-error "builtin" } */
+ (void*)&__builtin_constant_p, /* { dg-error "builtin" } */
+ (void*)&__builtin_nanf, /* { dg-error "builtin" } */
+ (void*)&__builtin_strlen, /* { dg-error "builtin" } */
+ (void*)&__builtin_unreachable, /* { dg-error "builtin" } */
+ (void*)&__builtin_FILE, /* { dg-error "builtin" } */
+ (void*)&__builtin_FUNCTION, /* { dg-error "builtin" } */
+ (void*)&__builtin_LINE, /* { dg-error "builtin" } */
+
+ 0
+};