+2015-09-03 Martin Sebor <msebor@redhat.com>
+
+ PR c/66516
+ * doc/extend.texi (Other Builtins): Document when the address
+ of a built-in function can be taken.
+
2015-09-03 Richard Biener <rguenther@suse.de>
* dwarf2out.c (flush_limbo_die_list): Split out from ...
+2015-09-03 Martin Sebor <msebor@redhat.com>
+
+ PR c/66516
+ * c-common.h (c_decl_implicit, reject_gcc_builtin): Declare new
+ functions.
+ * c-common.c (reject_gcc_builtin): Define.
+
2015-09-02 Balaji V. Iyer <balaji.v.iyer@intel.com>
PR middle-end/60586
return (TYPE_SIZE (t) && integer_zerop (TYPE_SIZE (t)));
}
+/* For an EXPR of a FUNCTION_TYPE that references a GCC built-in function
+ with no library fallback or for an ADDR_EXPR whose operand is such type
+ issues an error pointing to the location LOC.
+ Returns true when the expression has been diagnosed and false
+ otherwise. */
+bool
+reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
+{
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ if (TREE_TYPE (expr)
+ && TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
+ && DECL_P (expr)
+ /* The intersection of DECL_BUILT_IN and DECL_IS_BUILTIN avoids
+ false positives for user-declared built-ins such as abs or
+ strlen, and for C++ operators new and delete.
+ The c_decl_implicit() test avoids false positives for implicitly
+ declared built-ins with library fallbacks (such as abs). */
+ && DECL_BUILT_IN (expr)
+ && DECL_IS_BUILTIN (expr)
+ && !c_decl_implicit (expr)
+ && !DECL_ASSEMBLER_NAME_SET_P (expr))
+ {
+ if (loc == UNKNOWN_LOCATION)
+ loc = EXPR_LOC_OR_LOC (expr, input_location);
+
+ /* Reject arguments that are built-in functions with
+ no library fallback. */
+ error_at (loc, "built-in function %qE must be directly called", expr);
+
+ return true;
+ }
+
+ return false;
+}
+
#include "gt-c-family-c-common.h"
extern void resort_sorted_fields (void *, void *, gt_pointer_operator,
void *);
extern bool has_c_linkage (const_tree decl);
+extern bool c_decl_implicit (const_tree);
\f
/* Switches common to the C front ends. */
extern tree cilk_for_number_of_iterations (tree);
extern bool check_no_cilk (tree, const char *, const char *,
location_t loc = UNKNOWN_LOCATION);
+extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION);
#endif /* ! GCC_C_COMMON_H */
+2015-09-03 Martin Sebor <msebor@redhat.com>
+
+ PR c/66516
+ * c/c-typeck.c (convert_arguments, parser_build_unary_op)
+ (build_conditional_expr, c_cast_expr, convert_for_assignment)
+ (build_binary_op, _objc_common_truthvalue_conversion): Call
+ reject_gcc_builtin.
+ (c_decl_implicit): Define.
+
2015-09-02 Marek Polacek <polacek@redhat.com>
PR c/67432
error (invalid_func_diag);
return -1;
}
+ else if (TREE_CODE (val) == ADDR_EXPR && reject_gcc_builtin (val))
+ {
+ return -1;
+ }
else
/* Convert `short' and `char' to full-size `int'. */
parmval = default_conversion (val);
{
struct c_expr result;
- result.value = build_unary_op (loc, code, arg.value, 0);
result.original_code = code;
result.original_type = NULL;
+ if (reject_gcc_builtin (arg.value))
+ {
+ result.value = error_mark_node;
+ }
+ else
+ {
+ result.value = build_unary_op (loc, code, arg.value, 0);
+
if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
overflow_warning (loc, result.value);
+ }
return result;
}
type2 = TREE_TYPE (op2);
code2 = TREE_CODE (type2);
+ if (code1 == POINTER_TYPE && reject_gcc_builtin (op1))
+ return error_mark_node;
+
+ if (code2 == POINTER_TYPE && reject_gcc_builtin (op2))
+ return error_mark_node;
+
/* C90 does not permit non-lvalue arrays in conditional expressions.
In C99 they will be pointers by now. */
if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
type = groktypename (type_name, &type_expr, &type_expr_const);
warn_strict_prototypes = saved_wsp;
+ if (TREE_CODE (expr) == ADDR_EXPR && !VOID_TYPE_P (type)
+ && reject_gcc_builtin (expr))
+ return error_mark_node;
+
ret = build_c_cast (loc, type, expr);
if (type_expr)
{
rhs = require_complete_type (rhs);
if (rhs == error_mark_node)
return error_mark_node;
+
+ if (coder == POINTER_TYPE && reject_gcc_builtin (rhs))
+ return error_mark_node;
+
/* A non-reference type can convert to a reference. This handles
va_start, va_copy and possibly port built-ins. */
if (codel == REFERENCE_TYPE && coder != REFERENCE_TYPE)
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
return error_mark_node;
+ if (code0 == POINTER_TYPE
+ && reject_gcc_builtin (op0, EXPR_LOCATION (orig_op0)))
+ return error_mark_node;
+
+ if (code1 == POINTER_TYPE
+ && reject_gcc_builtin (op1, EXPR_LOCATION (orig_op1)))
+ return error_mark_node;
+
if ((invalid_op_diag
= targetm.invalid_binary_op (code, type0, type1)))
{
error_at (location, "void value not ignored as it ought to be");
return error_mark_node;
+ case POINTER_TYPE:
+ if (reject_gcc_builtin (expr))
+ return error_mark_node;
+ break;
+
case FUNCTION_TYPE:
gcc_unreachable ();
append_to_statement_list (build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR,
body_list, dtor), &list);
}
+
+/* Returns true when the function declaration FNDECL is implicit,
+ introduced as a result of a call to an otherwise undeclared
+ function, and false otherwise. */
+
+bool
+c_decl_implicit (const_tree fndecl)
+{
+ return C_DECL_IMPLICIT (fndecl);
+}
+2015-09-03 Martin Sebor <msebor@redhat.com>
+
+ PR c/66516
+ * cp/cp-tree.h (mark_rvalue_use, decay_conversion): Add new
+ argument(s).
+ * cp/expr.c (mark_rvalue_use): Use new argument.
+ * cp/call.c (build_addr_func): Call decay_conversion with new
+ argument.
+ * cp/pt.c (convert_template_argument): Call reject_gcc_builtin.
+ * cp/typeck.c (decay_conversion): Use new argument.
+ (c_decl_implicit): Define.
+
2015-09-02 Balaji V. Iyer <balaji.v.iyer@intel.com>
PR middle-end/60586
function = build_address (function);
}
else
- function = decay_conversion (function, complain);
+ function = decay_conversion (function, complain, /*reject_builtin=*/false);
return function;
}
/* in expr.c */
extern tree cplus_expand_constant (tree);
-extern tree mark_rvalue_use (tree);
+extern tree mark_rvalue_use (tree,
+ location_t = UNKNOWN_LOCATION,
+ bool = true);
extern tree mark_lvalue_use (tree);
extern tree mark_type_use (tree);
extern void mark_exp_read (tree);
extern tree cxx_sizeof_nowarn (tree);
extern tree is_bitfield_expr_with_lowered_type (const_tree);
extern tree unlowered_expr_type (const_tree);
-extern tree decay_conversion (tree, tsubst_flags_t);
+extern tree decay_conversion (tree,
+ tsubst_flags_t,
+ bool = true);
extern tree build_class_member_access_expr (tree, tree, tree, bool,
tsubst_flags_t);
extern tree finish_class_member_access_expr (tree, tree, bool,
return cst;
}
-/* Called whenever an expression is used
- in a rvalue context. */
-
+/* Called whenever the expression EXPR is used in an rvalue context.
+ When REJECT_BUILTIN is true the expression is checked to make sure
+ it doesn't make it possible to obtain the address of a GCC built-in
+ function with no library fallback (or any of its bits, such as in
+ a conversion to bool). */
tree
-mark_rvalue_use (tree expr)
+mark_rvalue_use (tree expr,
+ location_t loc /* = UNKNOWN_LOCATION */,
+ bool reject_builtin /* = true */)
{
+ if (reject_builtin && reject_gcc_builtin (expr, loc))
+ return error_mark_node;
+
mark_exp_read (expr);
return expr;
}
-/* Called whenever an expression is used
- in a lvalue context. */
+/* Called whenever an expression is used in an lvalue context. */
tree
mark_lvalue_use (tree expr)
else if (val == error_mark_node && (complain & tf_error))
error ("could not convert template argument %qE to %qT", orig_arg, t);
+ if (INDIRECT_REF_P (val))
+ {
+ /* Reject template arguments that are references to built-in
+ functions with no library fallbacks. */
+ const_tree inner = TREE_OPERAND (val, 0);
+ if (TREE_CODE (TREE_TYPE (inner)) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (inner))) == FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (inner)) == REFERENCE_TYPE
+ && reject_gcc_builtin (TREE_OPERAND (inner, 0)))
+ return error_mark_node;
+ }
+
if (TREE_CODE (val) == SCOPE_REF)
{
/* Strip typedefs from the SCOPE_REF. */
that the return value is no longer an lvalue. */
tree
-decay_conversion (tree exp, tsubst_flags_t complain)
+decay_conversion (tree exp,
+ tsubst_flags_t complain,
+ bool reject_builtin /* = true */)
{
tree type;
enum tree_code code;
if (type == error_mark_node)
return error_mark_node;
- exp = mark_rvalue_use (exp);
+ exp = mark_rvalue_use (exp, loc, reject_builtin);
exp = resolve_nondeduced_context (exp);
if (type_unknown_p (exp))
return true;
}
}
+
+/* Always returns false since unlike C90, C++ has no concept of implicit
+ function declarations. */
+
+bool
+c_decl_implicit (const_tree)
+{
+ return false;
+}
The remaining functions are provided for optimization purposes.
+With the exception of built-ins that have library equivalents such as
+the standard C library functions discussed below, or that expand to
+library calls, GCC built-in functions are always expanded inline and
+thus do not have corresponding entry points and their address cannot
+be obtained. Attempting to use them in an expression other than
+a function call results in a compile-time error.
+
@opindex fno-builtin
GCC includes built-in versions of many of the functions in the standard
-C library. The versions prefixed with @code{__builtin_} are always
-treated as having the same meaning as the C library function even if you
-specify the @option{-fno-builtin} option. (@pxref{C Dialect Options})
-Many of these functions are only optimized in certain cases; if they are
-not optimized in a particular case, a call to the library function is
-emitted.
+C library. These functions come in two forms: one whose names start with
+the @code{__builtin_} prefix, and the other without. Both forms have the
+same type (including prototype), the same address (when their address is
+taken), and the same meaning as the C library functions even if you specify
+the @option{-fno-builtin} option @pxref{C Dialect Options}). Many of these
+functions are only optimized in certain cases; if they are not optimized in
+a particular case, a call to the library function is emitted.
@opindex ansi
@opindex std
+2015-09-03 Martin Sebor <msebor@redhat.com>
+
+ PR c/66516
+ * g++.dg/addr_builtin-1.C: New test.
+ * gcc.dg/addr_builtin-1.c: New test.
+
2015-09-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* gcc.target/powerpc/vec-shift.c: New test.