diff options
Diffstat (limited to 'gcc/cp/semantics.cc')
-rw-r--r-- | gcc/cp/semantics.cc | 191 |
1 files changed, 147 insertions, 44 deletions
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 52ecac4..1937ace 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see #include "predict.h" #include "memmodel.h" #include "gimplify.h" +#include "contracts.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -677,7 +678,7 @@ do_poplevel (tree stmt_list) /* Begin a new scope. */ -static tree +tree do_pushlevel (scope_kind sk) { tree ret = push_stmt_list (); @@ -1854,6 +1855,21 @@ finish_range_for_decl (tree range_for_stmt, tree decl, tree expr) RANGE_FOR_BODY (range_for_stmt) = do_pushlevel (sk_block); } +/* Begin the scope of an expansion-statement. */ + +tree +begin_template_for_scope (tree *init) +{ + tree scope = do_pushlevel (sk_template_for); + + if (processing_template_decl) + *init = push_stmt_list (); + else + *init = NULL_TREE; + + return scope; +} + /* Finish a break-statement. */ tree @@ -3992,9 +4008,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); @@ -4490,6 +4512,17 @@ baselink_for_fns (tree fns) return build_baselink (conv_path, access_path, fns, /*optype=*/NULL_TREE); } +/* Returns true iff we are currently parsing a lambda-declarator. */ + +static bool +parsing_lambda_declarator () +{ + cp_binding_level *b = current_binding_level; + while (b->kind == sk_template_parms || b->kind == sk_function_parms) + b = b->level_chain; + return b->kind == sk_lambda; +} + /* Returns true iff DECL is a variable from a function outside the current one. */ @@ -4504,7 +4537,15 @@ outer_var_p (tree decl) /* Don't get confused by temporaries. */ && DECL_NAME (decl) && (DECL_CONTEXT (decl) != current_function_decl - || parsing_nsdmi ())); + || parsing_nsdmi () + /* Also consider captures as outer vars if we are in + decltype in a lambda declarator as in: + auto l = [j=0]() -> decltype((j)) { ... } + for the sake of finish_decltype_type. + + (Similar issue also affects non-lambdas, but vexing parse + makes it more difficult to handle than lambdas.) */ + || parsing_lambda_declarator ())); } /* As above, but also checks that DECL is automatic. */ @@ -4550,7 +4591,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use) if (!mark_used (decl, complain)) return error_mark_node; - if (parsing_nsdmi ()) + if (parsing_nsdmi () || parsing_lambda_declarator ()) containing_function = NULL_TREE; if (containing_function && LAMBDA_FUNCTION_P (containing_function)) @@ -7745,7 +7786,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) /* We've reached the end of a list of expanded nodes. Reset the group start pointer. */ if (c == grp_sentinel) - grp_start_p = NULL; + { + if (grp_start_p + && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p)) + for (tree gc = *grp_start_p; gc != grp_sentinel; + gc = OMP_CLAUSE_CHAIN (gc)) + OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p); + grp_start_p = NULL; + } switch (OMP_CLAUSE_CODE (c)) { @@ -8997,6 +9045,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) /* FALLTHRU */ case OMP_CLAUSE_TO: case OMP_CLAUSE_FROM: + if (OMP_CLAUSE_ITERATORS (c) + && cp_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c))) + { + t = error_mark_node; + break; + } + /* FALLTHRU */ case OMP_CLAUSE__CACHE_: { using namespace omp_addr_tokenizer; @@ -9900,6 +9955,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); } + if (grp_start_p + && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p)) + for (tree gc = *grp_start_p; gc; gc = OMP_CLAUSE_CHAIN (gc)) + OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p); + if (reduction_seen < 0 && (ordered_seen || schedule_seen)) reduction_seen = -2; @@ -12598,11 +12658,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; @@ -12630,6 +12693,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, @@ -12641,6 +12705,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, @@ -12890,9 +12961,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, } else { - if (outer_automatic_var_p (STRIP_REFERENCE_REF (expr)) - && current_function_decl - && LAMBDA_FUNCTION_P (current_function_decl)) + tree decl = STRIP_REFERENCE_REF (expr); + tree lam = current_lambda_expr (); + if (lam && outer_automatic_var_p (decl)) { /* [expr.prim.id.unqual]/3: If naming the entity from outside of an unevaluated operand within S would refer to an entity captured by @@ -12909,8 +12980,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, local variable inside decltype, not just decltype((x)) (PR83167). And we don't handle nested lambdas properly, where we need to consider the outer lambdas as well (PR112926). */ - tree decl = STRIP_REFERENCE_REF (expr); - tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl)); tree cap = lookup_name (DECL_NAME (decl), LOOK_where::BLOCK, LOOK_want::HIDDEN_LAMBDA); @@ -12926,17 +12995,28 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, if (type && !TYPE_REF_P (type)) { - tree obtype = TREE_TYPE (DECL_ARGUMENTS (current_function_decl)); - if (WILDCARD_TYPE_P (non_reference (obtype))) - /* We don't know what the eventual obtype quals will be. */ - goto dependent; - auto direct_type = [](tree t){ - if (INDIRECT_TYPE_P (t)) - return TREE_TYPE (t); - return t; - }; - int const quals = cp_type_quals (type) - | cp_type_quals (direct_type (obtype)); + int quals; + if (current_function_decl + && LAMBDA_FUNCTION_P (current_function_decl) + && DECL_XOBJ_MEMBER_FUNCTION_P (current_function_decl)) + { + tree obtype = TREE_TYPE (DECL_ARGUMENTS (current_function_decl)); + if (WILDCARD_TYPE_P (non_reference (obtype))) + /* We don't know what the eventual obtype quals will be. */ + goto dependent; + auto direct_type = [](tree t){ + if (INDIRECT_TYPE_P (t)) + return TREE_TYPE (t); + return t; + }; + quals = (cp_type_quals (type) + | cp_type_quals (direct_type (obtype))); + } + else + /* We are in the parameter clause, trailing return type, or + the requires clause and have no relevant c_f_decl yet. */ + quals = (LAMBDA_EXPR_CONST_QUAL_P (lam) + ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED); type = cp_build_qualified_type (type, quals); type = build_reference_type (type); } @@ -13631,10 +13711,11 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_DEDUCIBLE: return type_targs_deducible_from (type1, type2); - /* __array_rank and __builtin_type_order are handled in - finish_trait_expr. */ + /* __array_rank, __builtin_type_order and __builtin_structured_binding_size + are handled in finish_trait_expr. */ case CPTK_RANK: case CPTK_TYPE_ORDER: + case CPTK_STRUCTURED_BINDING_SIZE: gcc_unreachable (); #define DEFTRAIT_TYPE(CODE, NAME, ARITY) \ @@ -13739,6 +13820,27 @@ same_type_ref_bind_p (cp_trait_kind kind, tree type1, tree type2) (non_reference (to), non_reference (from)))); } +/* Helper for finish_trait_expr and tsubst_expr. Handle + CPTK_STRUCTURED_BINDING_SIZE in possibly SFINAE-friendly + way. */ + +tree +finish_structured_binding_size (location_t loc, tree type, + tsubst_flags_t complain) +{ + if (TYPE_REF_P (type)) + { + if (complain & tf_error) + error_at (loc, "%qs argument %qT is a reference", + "__builtin_structured_binding_size", type); + return error_mark_node; + } + HOST_WIDE_INT ret = cp_decomp_size (loc, type, complain); + if (ret == -1) + return error_mark_node; + return maybe_wrap_with_location (build_int_cst (size_type_node, ret), loc); +} + /* Process a trait expression. */ tree @@ -13751,7 +13853,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) if (processing_template_decl) { tree trait_expr = make_node (TRAIT_EXPR); - if (kind == CPTK_RANK) + if (kind == CPTK_RANK || kind == CPTK_STRUCTURED_BINDING_SIZE) TREE_TYPE (trait_expr) = size_type_node; else if (kind == CPTK_TYPE_ORDER) { @@ -13868,9 +13970,22 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_UNBOUNDED_ARRAY: case CPTK_IS_UNION: case CPTK_IS_VOLATILE: + break; + case CPTK_RANK: + { + size_t rank = 0; + for (; TREE_CODE (type1) == ARRAY_TYPE; type1 = TREE_TYPE (type1)) + ++rank; + return maybe_wrap_with_location (build_int_cst (size_type_node, rank), + loc); + } + case CPTK_TYPE_ORDER: - break; + return maybe_wrap_with_location (type_order_value (type1, type2), loc); + + case CPTK_STRUCTURED_BINDING_SIZE: + return finish_structured_binding_size (loc, type1, tf_warning_or_error); case CPTK_IS_LAYOUT_COMPATIBLE: if (!array_of_unknown_bound_p (type1) @@ -13901,20 +14016,8 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) gcc_unreachable (); } - tree val; - if (kind == CPTK_RANK) - { - size_t rank = 0; - for (; TREE_CODE (type1) == ARRAY_TYPE; type1 = TREE_TYPE (type1)) - ++rank; - val = build_int_cst (size_type_node, rank); - } - else if (kind == CPTK_TYPE_ORDER) - val = type_order_value (type1, type2); - else - val = (trait_expr_value (kind, type1, type2) - ? boolean_true_node : boolean_false_node); - + tree val = (trait_expr_value (kind, type1, type2) + ? boolean_true_node : boolean_false_node); return maybe_wrap_with_location (val, loc); } @@ -14111,7 +14214,7 @@ apply_deduced_return_type (tree fco, tree return_type) result); DECL_RESULT (fco) = result; - if (!processing_template_decl) + if (!uses_template_parms (fco)) if (function *fun = DECL_STRUCT_FUNCTION (fco)) { bool aggr = aggregate_value_p (result, fco); |