aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/semantics.cc')
-rw-r--r--gcc/cp/semantics.cc105
1 files changed, 76 insertions, 29 deletions
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 28baf7b..be79b50 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2338,7 +2338,8 @@ finish_asm_stmt (location_t loc, int volatile_p, tree string,
oconstraints[i] = constraint;
if (parse_output_constraint (&constraint, i, ninputs, noutputs,
- &allows_mem, &allows_reg, &is_inout))
+ &allows_mem, &allows_reg, &is_inout,
+ nullptr))
{
/* If the operand is going to end up in memory,
mark it addressable. */
@@ -2397,7 +2398,8 @@ finish_asm_stmt (location_t loc, int volatile_p, tree string,
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
bool constraint_parsed
= parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
- oconstraints, &allows_mem, &allows_reg);
+ oconstraints, &allows_mem, &allows_reg,
+ nullptr);
/* If the operand is going to end up in memory, don't call
decay_conversion. */
if (constraint_parsed && !allows_reg && allows_mem)
@@ -3605,11 +3607,13 @@ finish_this_expr (void)
{
tree result = NULL_TREE;
- if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+ if (current_class_ref && !LAMBDA_TYPE_P (TREE_TYPE (current_class_ref)))
+ result = current_class_ptr;
+ else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
result = (lambda_expr_this_capture
(CLASSTYPE_LAMBDA_EXPR (current_class_type), /*add*/true));
- else if (current_class_ptr)
- result = current_class_ptr;
+ else
+ gcc_checking_assert (!current_class_ptr);
if (result)
/* The keyword 'this' is a prvalue expression. */
@@ -3739,6 +3743,11 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
if (!(complain & tf_warning))
return result;
+ /* These will never fold into a constant, so no need to check for
+ overflow for them. */
+ if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+ return result;
+
tree result_ovl = result;
tree expr_ovl = expr;
@@ -3983,9 +3992,15 @@ finish_compound_literal (tree type, tree compound_literal,
tree
finish_fname (tree id)
{
- tree decl;
-
- decl = fname_decl (input_location, C_RID_CODE (id), id);
+ tree decl = fname_decl (input_location, C_RID_CODE (id), id);
+ /* [expr.prim.lambda.closure]/16 "Unless the compound-statement is that
+ of a consteval-block-declaration, a variable __func__ is implicitly
+ defined...". We could be in a consteval block in a function, though,
+ and then we shouldn't warn. */
+ if (current_function_decl
+ && !current_nonlambda_function (/*only_skip_consteval_block_p=*/true))
+ pedwarn (input_location, 0, "%qD is not defined outside of function scope",
+ decl);
if (processing_template_decl && current_function_decl
&& decl != error_mark_node)
decl = DECL_NAME (decl);
@@ -6295,9 +6310,7 @@ handle_omp_array_sections (tree &c, enum c_omp_region_type ort)
tree *tp = &OMP_CLAUSE_DECL (c);
if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
- && TREE_CODE (*tp) == TREE_LIST
- && TREE_PURPOSE (*tp)
- && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+ && OMP_ITERATOR_DECL_P (*tp))
tp = &TREE_VALUE (*tp);
tree first = handle_omp_array_sections_1 (c, *tp, types,
maybe_zero_len, first_non_one,
@@ -8817,9 +8830,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* FALLTHRU */
case OMP_CLAUSE_AFFINITY:
t = OMP_CLAUSE_DECL (c);
- if (TREE_CODE (t) == TREE_LIST
- && TREE_PURPOSE (t)
- && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ if (OMP_ITERATOR_DECL_P (t))
{
if (TREE_PURPOSE (t) != last_iterators)
last_iterators_remove
@@ -12593,11 +12604,14 @@ cexpr_str::extract (location_t location, const char * & msg, int &len)
CONDITION and the message text MESSAGE. LOCATION is the location
of the static assertion in the source code. When MEMBER_P, this
static assertion is a member of a class. If SHOW_EXPR_P is true,
- print the condition (because it was instantiation-dependent). */
+ print the condition (because it was instantiation-dependent).
+ If CONSTEVAL_BLOCK_P is true, this static assertion represents
+ a consteval block. */
void
finish_static_assert (tree condition, tree message, location_t location,
- bool member_p, bool show_expr_p)
+ bool member_p, bool show_expr_p,
+ bool consteval_block_p/*=false*/)
{
tsubst_flags_t complain = tf_warning_or_error;
@@ -12625,6 +12639,7 @@ finish_static_assert (tree condition, tree message, location_t location,
STATIC_ASSERT_CONDITION (assertion) = orig_condition;
STATIC_ASSERT_MESSAGE (assertion) = cstr.message;
STATIC_ASSERT_SOURCE_LOCATION (assertion) = location;
+ CONSTEVAL_BLOCK_P (assertion) = consteval_block_p;
if (member_p)
maybe_add_class_template_decl_list (current_class_type,
@@ -12636,6 +12651,13 @@ finish_static_assert (tree condition, tree message, location_t location,
return;
}
+ /* Evaluate the consteval { }. This must be done only once. */
+ if (consteval_block_p)
+ {
+ cxx_constant_value (condition);
+ return;
+ }
+
/* Fold the expression and convert it to a boolean value. */
condition = contextual_conv_bool (condition, complain);
condition = fold_non_dependent_expr (condition, complain,
@@ -13359,6 +13381,18 @@ object_type_p (const_tree type)
&& !VOID_TYPE_P (type));
}
+/* [defns.referenceable] True iff TYPE is a referenceable type. */
+
+static bool
+referenceable_type_p (const_tree type)
+{
+ return (TYPE_REF_P (type)
+ || object_type_p (type)
+ || (FUNC_OR_METHOD_TYPE_P (type)
+ && type_memfn_quals (type) == TYPE_UNQUALIFIED
+ && type_memfn_rqual (type) == REF_QUAL_NONE));
+}
+
/* Actually evaluates the trait. */
static bool
@@ -13528,6 +13562,21 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_NOTHROW_INVOCABLE:
return expr_noexcept_p (build_invoke (type1, type2, tf_none), tf_none);
+ case CPTK_IS_NOTHROW_RELOCATABLE:
+ if (trivially_relocatable_type_p (type1))
+ return true;
+ else
+ {
+ type1 = strip_array_types (type1);
+ if (!referenceable_type_p (type1))
+ return false;
+ tree arg = make_tree_vec (1);
+ TREE_VEC_ELT (arg, 0)
+ = cp_build_reference_type (type1, /*rval=*/true);
+ return (is_nothrow_xible (INIT_EXPR, type1, arg)
+ && is_nothrow_xible (BIT_NOT_EXPR, type1, NULL_TREE));
+ }
+
case CPTK_IS_OBJECT:
return object_type_p (type1);
@@ -13546,6 +13595,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_REFERENCE:
return type_code1 == REFERENCE_TYPE;
+ case CPTK_IS_REPLACEABLE:
+ return replaceable_type_p (type1);
+
case CPTK_IS_SAME:
return same_type_p (type1, type2);
@@ -13570,6 +13622,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_TRIVIALLY_DESTRUCTIBLE:
return is_trivially_xible (BIT_NOT_EXPR, type1, NULL_TREE);
+ case CPTK_IS_TRIVIALLY_RELOCATABLE:
+ return trivially_relocatable_type_p (type1);
+
case CPTK_IS_UNBOUNDED_ARRAY:
return array_of_unknown_bound_p (type1);
@@ -13653,7 +13708,8 @@ check_trait_type (tree type, int kind = 1)
type = complete_type (strip_array_types (type));
if (!COMPLETE_TYPE_P (type)
- && cxx_incomplete_type_diagnostic (NULL_TREE, type, DK_PERMERROR)
+ && cxx_incomplete_type_diagnostic (NULL_TREE, type,
+ diagnostics::kind::permerror)
&& !flag_permissive)
return false;
return true;
@@ -13700,18 +13756,6 @@ same_type_ref_bind_p (cp_trait_kind kind, tree type1, tree type2)
(non_reference (to), non_reference (from))));
}
-/* [defns.referenceable] True iff TYPE is a referenceable type. */
-
-static bool
-referenceable_type_p (const_tree type)
-{
- return (TYPE_REF_P (type)
- || object_type_p (type)
- || (FUNC_OR_METHOD_TYPE_P (type)
- && (type_memfn_quals (type) == TYPE_UNQUALIFIED
- && type_memfn_rqual (type) == REF_QUAL_NONE)));
-}
-
/* Process a trait expression. */
tree
@@ -13760,8 +13804,11 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_LITERAL_TYPE:
case CPTK_IS_POD:
case CPTK_IS_STD_LAYOUT:
+ case CPTK_IS_REPLACEABLE:
+ case CPTK_IS_NOTHROW_RELOCATABLE:
case CPTK_IS_TRIVIAL:
case CPTK_IS_TRIVIALLY_COPYABLE:
+ case CPTK_IS_TRIVIALLY_RELOCATABLE:
case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
if (!check_trait_type (type1, /* kind = */ 2))
return error_mark_node;