#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "attribs.h"
+#include "calls.h"
#include "flags.h"
#include "cp-tree.h"
#include "tree-iterator.h"
#include "c-family/c-common.h"
#include "c-family/c-objc.h"
#include "c-family/c-pragma.h"
+#include "c-family/c-target.h"
+#include "c-family/c-ubsan.h"
#include "diagnostic.h"
#include "intl.h"
#include "debug.h"
#include "splay-tree.h"
#include "plugin.h"
#include "cgraph.h"
+#include "wide-int.h"
/* Possible cases of bad specifiers type used by bad_specifiers. */
enum bad_spec_place {
static int check_static_variable_definition (tree, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (tree, tree, bool);
-static tree build_library_fn_1 (tree, enum tree_code, tree);
static int member_function_or_else (tree, tree, enum overload_flags);
static void bad_specifiers (tree, enum bad_spec_place, int, int, int, int,
int);
static void initialize_predefined_identifiers (void);
static tree check_special_function_return_type
(special_function_kind, tree, tree);
-static tree push_cp_library_fn (enum tree_code, tree);
-static tree build_cp_library_fn (tree, enum tree_code, tree);
+static tree push_cp_library_fn (enum tree_code, tree, int);
+static tree build_cp_library_fn (tree, enum tree_code, tree, int);
static void store_parm_decls (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
if (! DECL_TEMPLATE_SPECIALIZATION (old_decl)
&& DECL_TEMPLATE_SPECIALIZATION (new_decl))
return true;
+
+ error ("redeclaration %qD differs in %<constexpr%>", new_decl);
+ error ("from previous declaration %q+D", old_decl);
+ return false;
}
- error ("redeclaration %qD differs in %<constexpr%>", new_decl);
- error ("from previous declaration %q+D", old_decl);
- return false;
+ return true;
}
#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \
}
return NULL_TREE;
}
+ else if (DECL_OMP_DECLARE_REDUCTION_P (olddecl))
+ {
+ gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (newdecl));
+ error_at (DECL_SOURCE_LOCATION (newdecl),
+ "redeclaration of %<pragma omp declare reduction%>");
+ error_at (DECL_SOURCE_LOCATION (olddecl),
+ "previous %<pragma omp declare reduction%> declaration");
+ return error_mark_node;
+ }
else if (!types_match)
{
/* Avoid warnings redeclaring built-ins which have not been
newtype = build_exception_variant (newtype, new_eh_spec);
deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
- push_cp_library_fn (NEW_EXPR, newtype);
- push_cp_library_fn (VEC_NEW_EXPR, newtype);
- global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
- push_cp_library_fn (VEC_DELETE_EXPR, deltype);
+ DECL_IS_OPERATOR_NEW (push_cp_library_fn (NEW_EXPR, newtype, 0)) = 1;
+ DECL_IS_OPERATOR_NEW (push_cp_library_fn (VEC_NEW_EXPR, newtype, 0)) = 1;
+ global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+ push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
nullptr_type_node = make_node (NULLPTR_TYPE);
TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
}
abort_fndecl
- = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
+ = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
+ ECF_NORETURN | ECF_NOTHROW);
/* Perform other language dependent initializations. */
init_class_processing ();
function. Not called directly. */
static tree
-build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
+build_library_fn (tree name, enum tree_code operator_code, tree type,
+ int ecf_flags)
{
tree fn = build_lang_decl (FUNCTION_DECL, name, type);
DECL_EXTERNAL (fn) = 1;
external shared object. */
DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (fn) = 1;
- return fn;
-}
-
-/* Returns the _DECL for a library function with C linkage.
- We assume that such functions never throw; if this is incorrect,
- callers should unset TREE_NOTHROW. */
-
-static tree
-build_library_fn (tree name, tree type)
-{
- tree fn = build_library_fn_1 (name, ERROR_MARK, type);
- TREE_NOTHROW (fn) = 1;
+ set_call_expr_flags (fn, ecf_flags);
return fn;
}
/* Returns the _DECL for a library function with C++ linkage. */
static tree
-build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
+build_cp_library_fn (tree name, enum tree_code operator_code, tree type,
+ int ecf_flags)
{
- tree fn = build_library_fn_1 (name, operator_code, type);
- TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
+ tree fn = build_library_fn (name, operator_code, type, ecf_flags);
DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
SET_DECL_LANGUAGE (fn, lang_cplusplus);
return fn;
IDENTIFIER_NODE. */
tree
-build_library_fn_ptr (const char* name, tree type)
+build_library_fn_ptr (const char* name, tree type, int ecf_flags)
{
- return build_library_fn (get_identifier (name), type);
+ return build_library_fn (get_identifier (name), ERROR_MARK, type, ecf_flags);
}
/* Like build_cp_library_fn, but takes a C string instead of an
IDENTIFIER_NODE. */
tree
-build_cp_library_fn_ptr (const char* name, tree type)
+build_cp_library_fn_ptr (const char* name, tree type, int ecf_flags)
{
- return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
+ return build_cp_library_fn (get_identifier (name), ERROR_MARK, type,
+ ecf_flags);
}
/* Like build_library_fn, but also pushes the function so that we will
may throw exceptions listed in RAISES. */
tree
-push_library_fn (tree name, tree type, tree raises)
+push_library_fn (tree name, tree type, tree raises, int ecf_flags)
{
tree fn;
if (raises)
type = build_exception_variant (type, raises);
- fn = build_library_fn (name, type);
+ fn = build_library_fn (name, ERROR_MARK, type, ecf_flags);
pushdecl_top_level (fn);
return fn;
}
will be found by normal lookup. */
static tree
-push_cp_library_fn (enum tree_code operator_code, tree type)
+push_cp_library_fn (enum tree_code operator_code, tree type,
+ int ecf_flags)
{
tree fn = build_cp_library_fn (ansi_opname (operator_code),
operator_code,
- type);
+ type, ecf_flags);
pushdecl (fn);
if (flag_tm)
apply_tm_attr (fn, get_identifier ("transaction_safe"));
a FUNCTION_TYPE. */
tree
-push_void_library_fn (tree name, tree parmtypes)
+push_void_library_fn (tree name, tree parmtypes, int ecf_flags)
{
tree type = build_function_type (void_type_node, parmtypes);
- return push_library_fn (name, type, NULL_TREE);
+ return push_library_fn (name, type, NULL_TREE, ecf_flags);
}
/* Like push_library_fn, but also note that this function throws
tree
push_throw_library_fn (tree name, tree type)
{
- tree fn = push_library_fn (name, type, NULL_TREE);
- TREE_THIS_VOLATILE (fn) = 1;
- TREE_NOTHROW (fn) = 0;
+ tree fn = push_library_fn (name, type, NULL_TREE, ECF_NORETURN);
return fn;
}
\f
if (TREE_CODE (ce->index) == INTEGER_CST)
{
/* A C99 designator is OK if it matches the current index. */
- if (TREE_INT_CST_LOW (ce->index) == index)
+ if (wi::eq_p (ce->index, index))
return true;
else
sorry ("non-trivial designated initializers not supported");
if (integer_all_onesp (max_index))
return new_init;
- if (host_integerp (max_index, 1))
- max_index_cst = tree_low_cst (max_index, 1);
+ if (tree_fits_uhwi_p (max_index))
+ max_index_cst = tree_to_uhwi (max_index);
/* sizetype is sign extended, not zero extended. */
else
- max_index_cst = tree_low_cst (fold_convert (size_type_node, max_index),
- 1);
+ max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index));
}
/* Loop until there are no more initializers. */
&& !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CP_AGGREGATE_TYPE_P (type)
&& (CLASS_TYPE_P (type)
+ || !TYPE_NEEDS_CONSTRUCTING (type)
|| type_has_extended_temps (type))))
{
init_code = build_aggr_init_full_exprs (decl, init, flags);
&& TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
error ("non-static data member %qD has Java class type", decl);
- if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
- {
- /* If the VLA bound is larger than half the address space, or less
- than zero, throw std::bad_array_length. */
- tree max = convert (ssizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
- /* C++1y says we should throw for length <= 0, but we have
- historically supported zero-length arrays. Let's treat that as an
- extension to be disabled by -std=c++NN. */
- int lower = flag_iso ? 0 : -1;
- tree comp = build2 (LT_EXPR, boolean_type_node, max, ssize_int (lower));
- comp = build3 (COND_EXPR, void_type_node, comp,
- throw_bad_array_length (), void_zero_node);
- finish_expr_stmt (comp);
- }
-
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_EXPR for a
reference temp is added before the DECL_EXPR for the reference itself. */
/* Now, build the function declaration. */
push_lang_context (lang_name_c);
- atexit_fndecl = build_library_fn_ptr (name, fn_type);
+ atexit_fndecl = build_library_fn_ptr (name, fn_type, ECF_LEAF | ECF_NOTHROW);
mark_used (atexit_fndecl);
pop_lang_context ();
atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error);
NULL_TREE);
/* Now, build the function declaration. */
- tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type);
+ tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type,
+ ECF_LEAF | ECF_NOTHROW);
return decay_conversion (atexit_fndecl, tf_warning_or_error);
}
/* Some variables require no dynamic initialization. */
if (!init
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
- return;
+ {
+ /* Make sure the destructor is callable. */
+ cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+ return;
+ }
if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
&& !DECL_FUNCTION_SCOPE_P (decl))
(acquire_name, build_function_type_list (integer_type_node,
TREE_TYPE (guard_addr),
NULL_TREE),
- NULL_TREE);
+ NULL_TREE, ECF_NOTHROW | ECF_LEAF);
if (!release_fn || !abort_fn)
vfntype = build_function_type_list (void_type_node,
TREE_TYPE (guard_addr),
NULL_TREE);
if (!release_fn)
- release_fn = push_library_fn (release_name, vfntype, NULL_TREE);
+ release_fn = push_library_fn (release_name, vfntype, NULL_TREE,
+ ECF_NOTHROW | ECF_LEAF);
if (!abort_fn)
- abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE);
+ abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE,
+ ECF_NOTHROW | ECF_LEAF);
inner_if_stmt = begin_if_stmt ();
finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
decl);
}
+/* Helper function. Replace the temporary this parameter injected
+ during cp_finish_omp_declare_simd with the real this parameter. */
+
+static tree
+declare_simd_adjust_this (tree *tp, int *walk_subtrees, void *data)
+{
+ tree this_parm = (tree) data;
+ if (TREE_CODE (*tp) == PARM_DECL
+ && DECL_NAME (*tp) == this_identifier
+ && *tp != this_parm)
+ *tp = this_parm;
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
/* CTYPE is class type, or null if non-class.
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
or METHOD_TYPE.
|| (IDENTIFIER_LENGTH (declarator) > 10
&& IDENTIFIER_POINTER (declarator)[0] == '_'
&& IDENTIFIER_POINTER (declarator)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
+ && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0)
+ || (targetcm.cxx_implicit_extern_c
+ && targetcm.cxx_implicit_extern_c(IDENTIFIER_POINTER (declarator))))
&& current_lang_name == lang_name_cplusplus
&& ctype == NULL_TREE
&& DECL_FILE_SCOPE_P (decl))
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
TREE_NOTHROW (decl) = 1;
+ if (flag_openmp)
+ {
+ /* Adjust "omp declare simd" attributes. */
+ tree ods = lookup_attribute ("omp declare simd", *attrlist);
+ if (ods)
+ {
+ tree attr;
+ for (attr = ods; attr;
+ attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr)))
+ {
+ if (TREE_CODE (type) == METHOD_TYPE)
+ walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+ DECL_ARGUMENTS (decl), NULL);
+ if (TREE_VALUE (attr) != NULL_TREE)
+ {
+ tree cl = TREE_VALUE (TREE_VALUE (attr));
+ cl = c_omp_declare_simd_clauses_to_numbers
+ (DECL_ARGUMENTS (decl), cl);
+ if (cl)
+ TREE_VALUE (TREE_VALUE (attr)) = cl;
+ else
+ TREE_VALUE (attr) = NULL_TREE;
+ }
+ }
+ }
+ }
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
{
/* A variable sized array. */
itype = variable_size (itype);
+
if (TREE_CODE (itype) != SAVE_EXPR)
{
/* Look for SIZEOF_EXPRs in itype and fold them, otherwise
if (found)
itype = variable_size (fold (newitype));
}
+
+ stabilize_vla_size (itype);
+
+ if (cxx_dialect >= cxx1y)
+ {
+ /* If the VLA bound is larger than half the address space,
+ or less than zero, throw std::bad_array_length. */
+ tree comp = build2 (LT_EXPR, boolean_type_node, itype,
+ ssize_int (-1));
+ comp = build3 (COND_EXPR, void_type_node, comp,
+ throw_bad_array_length (), void_zero_node);
+ finish_expr_stmt (comp);
+ }
+ else if (flag_sanitize & SANITIZE_VLA)
+ {
+ /* From C++1y onwards, we throw an exception on a negative
+ length size of an array; see above. */
+
+ /* We have to add 1 -- in the ubsan routine we generate
+ LE_EXPR rather than LT_EXPR. */
+ tree t = fold_build2 (PLUS_EXPR, TREE_TYPE (itype), itype,
+ build_one_cst (TREE_TYPE (itype)));
+ t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t),
+ ubsan_instrument_vla (input_location, t), t);
+ finish_expr_stmt (t);
+ }
}
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
&& !uniquely_derived_from_p (ctype,
current_class_type))
{
- error ("type %qT is not derived from type %qT",
- ctype, current_class_type);
+ error ("invalid use of qualified-name %<%T::%D%>",
+ qualifying_scope, decl);
return error_mark_node;
}
}
&& (decl_context == NORMAL || decl_context == FIELD)
&& at_function_scope_p ()
&& variably_modified_type_p (type, NULL_TREE))
- {
- /* First break out any side-effects. */
- stabilize_vla_size (TYPE_SIZE (type));
- /* And then force evaluation of the SAVE_EXPR. */
- finish_expr_stmt (TYPE_SIZE (type));
- }
+ /* Force evaluation of the SAVE_EXPR. */
+ finish_expr_stmt (TYPE_SIZE (type));
if (declarator->kind == cdk_reference)
{
}
}
- /* We need to stabilize side-effects in VLA sizes for regular array
- declarations too, not just pointers to arrays. */
- if (type != error_mark_node && !TYPE_NAME (type)
- && (decl_context == NORMAL || decl_context == FIELD)
- && at_function_scope_p ()
- && variably_modified_type_p (type, NULL_TREE))
- stabilize_vla_size (TYPE_SIZE (type));
-
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
{
error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
- crash in tree_low_cst(). */
+ crash in tree_to_[su]hwi(). */
type = error_mark_node;
}
if (type_uses_auto (type))
{
- error ("parameter declared %<auto%>");
+ if (cxx_dialect >= cxx1y)
+ error ("%<auto%> parameter not permitted in this context");
+ else
+ error ("parameter declared %<auto%>");
type = error_mark_node;
}
enumeration. We must do this before the type of MINNODE and
MAXNODE are transformed, since tree_int_cst_min_precision relies
on the TREE_TYPE of the value it is passed. */
- bool unsignedp = tree_int_cst_sgn (minnode) >= 0;
- int lowprec = tree_int_cst_min_precision (minnode, unsignedp);
- int highprec = tree_int_cst_min_precision (maxnode, unsignedp);
+ signop sgn = tree_int_cst_sgn (minnode) >= 0 ? UNSIGNED : SIGNED;
+ int lowprec = tree_int_cst_min_precision (minnode, sgn);
+ int highprec = tree_int_cst_min_precision (maxnode, sgn);
int precision = MAX (lowprec, highprec);
unsigned int itk;
bool use_short_enum;
underlying_type = integer_types[itk];
if (underlying_type != NULL_TREE
&& TYPE_PRECISION (underlying_type) >= precision
- && TYPE_UNSIGNED (underlying_type) == unsignedp)
+ && TYPE_SIGN (underlying_type) == sgn)
break;
}
if (itk == itk_none)
= build_distinct_type_copy (underlying_type);
TYPE_PRECISION (ENUM_UNDERLYING_TYPE (enumtype)) = precision;
set_min_and_max_values_for_integral_type
- (ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
+ (ENUM_UNDERLYING_TYPE (enumtype), precision, sgn);
/* If -fstrict-enums, still constrain TYPE_MIN/MAX_VALUE. */
if (flag_strict_enums)
- set_min_and_max_values_for_integral_type (enumtype, precision,
- unsignedp);
+ set_min_and_max_values_for_integral_type (enumtype, precision, sgn);
}
else
underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
value = error_mark_node;
else
{
- double_int di = TREE_INT_CST (prev_value)
- .add_with_sign (double_int_one,
- false, &overflowed);
+ tree type = TREE_TYPE (prev_value);
+ signop sgn = TYPE_SIGN (type);
+ widest_int wi = wi::add (wi::to_widest (prev_value), 1, sgn,
+ &overflowed);
if (!overflowed)
{
- tree type = TREE_TYPE (prev_value);
- bool pos = TYPE_UNSIGNED (type) || !di.is_negative ();
- if (!double_int_fits_to_tree_p (type, di))
+ bool pos = !wi::neg_p (wi, sgn);
+ if (!wi::fits_to_tree_p (wi, type))
{
unsigned int itk;
for (itk = itk_int; itk != itk_none; itk++)
type = integer_types[itk];
if (type != NULL_TREE
&& (pos || !TYPE_UNSIGNED (type))
- && double_int_fits_to_tree_p (type, di))
+ && wi::fits_to_tree_p (wi, type))
break;
}
if (type && cxx_dialect < cxx11
if (type == NULL_TREE)
overflowed = true;
else
- value = double_int_to_tree (type, di);
+ value = wide_int_to_tree (type, wi);
}
if (overflowed)
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (type_build_dtor_call (type))
{
- int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
- bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
- && CLASSTYPE_VBASECLASSES (type));
+ int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR;
tree addr;
tree call;
else
addr = build_address (decl);
- /* Optimize for space over speed here. */
- if (!has_vbases || flag_expensive_optimizations)
- flags |= LOOKUP_NONVIRTUAL;
-
call = build_delete (TREE_TYPE (addr), addr,
sfk_complete_destructor, flags, 0, complain);
if (call == error_mark_node)
cleanup = error_mark_node;
+ else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+ /* Discard the call. */;
else if (cleanup)
cleanup = cp_build_compound_expr (cleanup, call, complain);
else