diff options
author | Marek Polacek <polacek@redhat.com> | 2024-05-31 08:54:00 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2024-07-10 15:38:48 -0400 |
commit | f0fb6b6acd805cfd3197eaf78d5404fa45759727 (patch) | |
tree | d4c1002b3f5535a2d4640b6e5d96a6c6638f8827 /gcc/cp | |
parent | 0c27eade4754c13a54e265e4305182c95be1e441 (diff) | |
download | gcc-f0fb6b6acd805cfd3197eaf78d5404fa45759727.zip gcc-f0fb6b6acd805cfd3197eaf78d5404fa45759727.tar.gz gcc-f0fb6b6acd805cfd3197eaf78d5404fa45759727.tar.bz2 |
c++: remove Concepts TS code
In GCC 14 we deprecated Concepts TS and discussed removing the code
in GCC 15. This patch removes Concepts TS code from the front end,
including support for template-introductions, as in:
template<typename T>
concept C = true;
C{T} void foo (T); // write template<C T> void foo (T);
The biggest part of this patch is adjusting the testsuite. We don't
want to lose coverage so I've converted most of -fconcepts-ts tests
to C++20. That means they no longer have to be c++17_only. Mostly
this meant turning "concept bool" into "concept" and turning function
concepts into C++20 concepts. I've added missing "auto"s where
required, but "auto"s in template-argument-lists are not supported
anymore so I've removed some of the tests; some of them are still
present to verify we don't crash on such autos. I've also added ()
around "requires" expressions.
I plan to add a porting_to.html entry with a few hints.
I've rebased and tested the patch after the recent r15-1103.
gcc/c-family/ChangeLog:
* c-cppbuiltin.cc (c_cpp_builtins): Remove flag_concepts_ts code.
* c-opts.cc (c_common_post_options): Likewise.
* c.opt: Remove -fconcepts-ts.
* c.opt.urls: Regenerate.
gcc/cp/ChangeLog:
* constraint.cc (deduce_concept_introduction, get_deduced_wildcard,
get_introduction_prototype, introduce_type_template_parameter,
introduce_template_template_parameter,
introduce_nontype_template_parameter,
build_introduced_template_parameter, introduce_template_parameter,
introduce_template_parameter_pack, introduce_template_parameter,
introduce_template_parameters, process_introduction_parms,
check_introduction_list, finish_template_introduction): Remove.
(finish_shorthand_constraint): Remove a Concepts TS comment.
* cp-tree.h (check_auto_in_tmpl_args, finish_template_introduction):
Remove.
* decl.cc (function_requirements_equivalent_p): Remove pre-C++20 code.
(grokfndecl): Don't check flag_concepts_ts.
(grokvardecl): Don't check that concept have type bool.
* parser.cc (cp_parser_decl_specifier_seq): Don't check
flag_concepts_ts.
(cp_parser_introduction_list): Remove.
(cp_parser_template_id): Remove dead code.
(cp_parser_simple_type_specifier): Don't check flag_concepts_ts.
(cp_parser_placeholder_type_specifier): Require require auto or
decltype(auto) even pre-C++20. Don't check flag_concepts_ts.
(cp_parser_type_id_1): Don't check flag_concepts_ts.
(cp_parser_template_type_arg): Likewise.
(cp_parser_requires_clause_opt): Remove flag_concepts_ts code.
(cp_parser_compound_requirement): Don't check flag_concepts_ts.
(cp_parser_template_introduction): Remove.
(cp_parser_template_declaration_after_export): Don't call
cp_parser_template_introduction.
* pt.cc (template_heads_equivalent_p): Remove pre-C++20 code.
(find_parameter_pack_data): Remove type_pack_expansion_p.
(find_parameter_packs_r): Remove flag_concepts_ts code. Remove
type_pack_expansion_p code.
(uses_parameter_packs): Remove type_pack_expansion_p code.
(make_pack_expansion): Likewise.
(check_for_bare_parameter_packs): Likewise.
(fixed_parameter_pack_p): Likewise.
(tsubst_qualified_id): Remove dead code.
(extract_autos_r): Remove.
(extract_autos): Remove.
(do_auto_deduction): Remove flag_concepts_ts code.
(type_uses_auto): Likewise.
(check_auto_in_tmpl_args): Remove.
gcc/ChangeLog:
* doc/invoke.texi: Mention that -fconcepts-ts was removed.
libstdc++-v3/ChangeLog:
* testsuite/std/ranges/access/101782.cc: Don't compile with
-fconcepts-ts.
gcc/testsuite/ChangeLog:
* g++.dg/concepts/auto3.C: Compile with -fconcepts. Run in C++17 and
up. Add dg-error.
* g++.dg/concepts/auto5.C: Likewise.
* g++.dg/concepts/auto7.C: Compile with -fconcepts. Add dg-error.
* g++.dg/concepts/auto8a.C: Compile with -fconcepts.
* g++.dg/concepts/class-deduction1.C: Compile with -fconcepts. Run in
C++17 and up. Convert to C++20.
* g++.dg/concepts/class5.C: Likewise.
* g++.dg/concepts/class6.C: Likewise.
* g++.dg/concepts/debug1.C: Likewise.
* g++.dg/concepts/decl-diagnose.C: Compile with -fconcepts. Run in
C++17 and up. Add dg-error.
* g++.dg/concepts/deduction-constraint1.C: Compile with -fconcepts.
Run in C++17 and up. Convert to C++20.
* g++.dg/concepts/diagnostic1.C: Likewise.
* g++.dg/concepts/dr1430.C: Likewise.
* g++.dg/concepts/equiv.C: Likewise.
* g++.dg/concepts/equiv2.C: Likewise.
* g++.dg/concepts/expression.C: Likewise.
* g++.dg/concepts/expression2.C: Likewise.
* g++.dg/concepts/expression3.C: Likewise.
* g++.dg/concepts/fn-concept2.C: Compile with -fconcepts. Run in
C++17 and up. Remove code. Add dg-prune-output.
* g++.dg/concepts/fn-concept3.C: Compile with -fconcepts. Run in
C++17 and up. Convert to C++20.
* g++.dg/concepts/fn1.C: Likewise.
* g++.dg/concepts/fn10.C: Likewise.
* g++.dg/concepts/fn2.C: Likewise.
* g++.dg/concepts/fn3.C: Likewise.
* g++.dg/concepts/fn4.C: Likewise.
* g++.dg/concepts/fn5.C: Likewise.
* g++.dg/concepts/fn6.C: Likewise.
* g++.dg/concepts/fn7.C: Compile with -fconcepts. Add dg-error.
* g++.dg/concepts/fn8.C: Compile with -fconcepts. Run in C++17 and up.
Convert to C++20.
* g++.dg/concepts/fn9.C: Likewise.
* g++.dg/concepts/generic-fn-err.C: Likewise.
* g++.dg/concepts/generic-fn.C: Likewise.
* g++.dg/concepts/inherit-ctor1.C: Likewise.
* g++.dg/concepts/inherit-ctor3.C: Likewise.
* g++.dg/concepts/intro1.C: Likewise.
* g++.dg/concepts/locations1.C: Compile with -fconcepts. Run in C++17
and up. Add dg-prune-output.
* g++.dg/concepts/partial-concept-id1.C: Compile with -fconcepts.
Run in C++17 and up. Convert to C++20.
* g++.dg/concepts/partial-concept-id2.C: Likewise.
* g++.dg/concepts/partial-spec5.C: Likewise.
* g++.dg/concepts/placeholder2.C: Likewise.
* g++.dg/concepts/placeholder3.C: Likewise.
* g++.dg/concepts/placeholder4.C: Likewise.
* g++.dg/concepts/placeholder5.C: Likewise.
* g++.dg/concepts/placeholder6.C: Likewise.
* g++.dg/concepts/pr65634.C: Likewise.
* g++.dg/concepts/pr65636.C: Likewise.
* g++.dg/concepts/pr65681.C: Likewise.
* g++.dg/concepts/pr65848.C: Likewise.
* g++.dg/concepts/pr67249.C: Likewise.
* g++.dg/concepts/pr67595.C: Likewise.
* g++.dg/concepts/pr68434.C: Likewise.
* g++.dg/concepts/pr71127.C: Likewise.
* g++.dg/concepts/pr71128.C: Compile with -fconcepts. Run in C++17
and up. Add dg-error.
* g++.dg/concepts/pr71131.C: Compile with -fconcepts. Run in C++17
and up. Convert to C++20.
* g++.dg/concepts/pr71385.C: Likewise.
* g++.dg/concepts/pr85065.C: Likewise.
* g++.dg/concepts/pr92804-2.C: Compile with -fconcepts. Convert to
C++20.
* g++.dg/concepts/template-parm11.C: Compile with -fconcepts. Run in
C++17 and up. Convert to C++20.
* g++.dg/concepts/template-parm12.C: Likewise.
* g++.dg/concepts/template-parm2.C: Likewise.
* g++.dg/concepts/template-parm3.C: Likewise.
* g++.dg/concepts/template-parm4.C: Likewise.
* g++.dg/concepts/template-template-parm1.C: Likewise.
* g++.dg/concepts/var-concept1.C: Likewise.
* g++.dg/concepts/var-concept2.C: Likewise.
* g++.dg/concepts/var-concept3.C: Likewise.
* g++.dg/concepts/var-concept4.C: Likewise.
* g++.dg/concepts/var-concept5.C: Likewise.
* g++.dg/concepts/var-concept6.C: Likewise.
* g++.dg/concepts/var-concept7.C: Likewise.
* g++.dg/concepts/var-templ1.C: Run in C++17 and up.
* g++.dg/concepts/var-templ2.C: Compile with -fconcepts. Run in C++17
and up. Convert to C++20.
* g++.dg/concepts/var-templ3.C: Likewise.
* g++.dg/concepts/variadic1.C: Likewise.
* g++.dg/concepts/variadic2.C: Likewise.
* g++.dg/concepts/variadic3.C: Likewise.
* g++.dg/concepts/variadic4.C: Likewise.
* g++.dg/cpp2a/concepts-pr65575.C: Likewise.
* g++.dg/cpp2a/concepts-pr66091.C: Likewise.
* g++.dg/cpp2a/concepts-pr67148.C: Compile with -fconcepts. Convert
to C++20.
* g++.dg/cpp2a/concepts-pr67225-1.C: Likewise.
* g++.dg/cpp2a/concepts-pr67225-2.C: Likewise.
* g++.dg/cpp2a/concepts-pr67225-3.C: Likewise.
* g++.dg/cpp2a/concepts-pr67225-4.C: Likewise.
* g++.dg/cpp2a/concepts-pr67225-5.C: Likewise.
* g++.dg/cpp2a/concepts-pr67319.C: Likewise.
* g++.dg/cpp2a/concepts-pr67427.C: Likewise.
* g++.dg/cpp2a/concepts-pr67654.C: Likewise.
* g++.dg/cpp2a/concepts-pr67658.C: Likewise.
* g++.dg/cpp2a/concepts-pr67684.C: Likewise.
* g++.dg/cpp2a/concepts-pr67697.C: Likewise.
* g++.dg/cpp2a/concepts-pr67719.C: Likewise.
* g++.dg/cpp2a/concepts-pr67774.C: Likewise.
* g++.dg/cpp2a/concepts-pr67825.C: Likewise.
* g++.dg/cpp2a/concepts-pr67860.C: Likewise.
* g++.dg/cpp2a/concepts-pr67862.C: Likewise.
* g++.dg/cpp2a/concepts-pr67969.C: Likewise.
* g++.dg/cpp2a/concepts-pr68093-2.C: Likewise.
* g++.dg/cpp2a/concepts-pr68372.C: Likewise.
* g++.dg/cpp2a/concepts-pr68812.C: Likewise.
* g++.dg/cpp2a/concepts-pr69235.C: Likewise.
* g++.dg/cpp2a/concepts-pr78752-2.C: Likewise.
* g++.dg/cpp2a/concepts-pr78752.C: Likewise.
* g++.dg/cpp2a/concepts-pr79759.C: Likewise.
* g++.dg/cpp2a/concepts-pr80746.C: Likewise.
* g++.dg/cpp2a/concepts-pr80773.C: Likewise.
* g++.dg/cpp2a/concepts-pr82507.C: Likewise.
* g++.dg/cpp2a/concepts-pr82740.C: Likewise.
* g++.dg/cpp2a/concepts-pr84980.C: Compile with -fconcepts. Run in
C++17 and up. Convert to C++20.
* g++.dg/cpp2a/concepts-pr85265.C: Likewise.
* g++.dg/cpp2a/concepts-pr85808.C: Compile with -fconcepts. Convert
to C++20.
* g++.dg/cpp2a/concepts-pr86269.C: Likewise.
* g++.dg/cpp2a/concepts-pr87441.C: Likewise.
* g++.dg/cpp2a/concepts-requires5.C: Compile with -fconcepts.
Adjust dg-error. Add same_as.
* g++.dg/cpp2a/nontype-class50a.C: Compile with -fconcepts.
* g++.dg/concepts/auto1.C: Removed.
* g++.dg/concepts/auto4.C: Removed.
* g++.dg/concepts/auto6.C: Removed.
* g++.dg/concepts/fn-concept1.C: Removed.
* g++.dg/concepts/intro2.C: Removed.
* g++.dg/concepts/intro3.C: Removed.
* g++.dg/concepts/intro4.C: Removed.
* g++.dg/concepts/intro5.C: Removed.
* g++.dg/concepts/intro6.C: Removed.
* g++.dg/concepts/intro7.C: Removed.
* g++.dg/cpp2a/concepts-ts1.C: Removed.
* g++.dg/cpp2a/concepts-ts2.C: Removed.
* g++.dg/cpp2a/concepts-ts3.C: Removed.
* g++.dg/cpp2a/concepts-ts4.C: Removed.
* g++.dg/cpp2a/concepts-ts5.C: Removed.
* g++.dg/cpp2a/concepts-ts6.C: Removed.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/constraint.cc | 282 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 18 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 260 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 175 |
5 files changed, 44 insertions, 693 deletions
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index ebf4255..5472cc5 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -437,18 +437,6 @@ deduce_constrained_parameter (tree expr, tree& check, tree& proto) return false; } -/* Given a call expression or template-id expression to a concept, EXPR, - deduce the concept being checked and return the template arguments. - Returns NULL_TREE if deduction fails. */ -static tree -deduce_concept_introduction (tree check) -{ - tree info = resolve_concept_check (check); - if (info && info != error_mark_node) - return TREE_PURPOSE (info); - return NULL_TREE; -} - /* Build a constrained placeholder type where SPEC is a type-constraint. SPEC can be anything were concept_definition_p is true. @@ -1578,18 +1566,6 @@ finish_shorthand_constraint (tree decl, tree constr) tree con = CONSTRAINED_PARM_CONCEPT (constr); tree args = CONSTRAINED_PARM_EXTRA_ARGS (constr); - /* The TS lets use shorthand to constrain a pack of arguments, but the - standard does not. - - For the TS, consider: - - template<C... Ts> struct s; - - If C is variadic (and because Ts is a pack), we associate the - constraint C<Ts...>. In all other cases, we associate - the constraint (C<Ts> && ...). - - The standard behavior cannot be overridden by -fconcepts-ts. */ bool variadic_concept_p = template_parameter_pack_p (proto); bool declared_pack_p = template_parameter_pack_p (decl); bool apply_to_each_p = (cxx_dialect >= cxx20) ? true : !variadic_concept_p; @@ -1635,264 +1611,6 @@ get_shorthand_constraints (tree parms) return result; } -/* Get the deduced wildcard from a DEDUCED placeholder. If the deduced - wildcard is a pack, return the first argument of that pack. */ - -static tree -get_deduced_wildcard (tree wildcard) -{ - if (ARGUMENT_PACK_P (wildcard)) - wildcard = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (wildcard), 0); - gcc_assert (TREE_CODE (wildcard) == WILDCARD_DECL); - return wildcard; -} - -/* Returns the prototype parameter for the nth deduced wildcard. */ - -static tree -get_introduction_prototype (tree wildcards, int index) -{ - return TREE_TYPE (get_deduced_wildcard (TREE_VEC_ELT (wildcards, index))); -} - -/* Introduce a type template parameter. */ - -static tree -introduce_type_template_parameter (tree wildcard, bool& non_type_p) -{ - non_type_p = false; - return finish_template_type_parm (class_type_node, DECL_NAME (wildcard)); -} - -/* Introduce a template template parameter. */ - -static tree -introduce_template_template_parameter (tree wildcard, bool& non_type_p) -{ - non_type_p = false; - begin_template_parm_list (); - current_template_parms = DECL_TEMPLATE_PARMS (TREE_TYPE (wildcard)); - end_template_parm_list (); - return finish_template_template_parm (class_type_node, DECL_NAME (wildcard)); -} - -/* Introduce a template non-type parameter. */ - -static tree -introduce_nontype_template_parameter (tree wildcard, bool& non_type_p) -{ - non_type_p = true; - tree parm = copy_decl (TREE_TYPE (wildcard)); - DECL_NAME (parm) = DECL_NAME (wildcard); - return parm; -} - -/* Introduce a single template parameter. */ - -static tree -build_introduced_template_parameter (tree wildcard, bool& non_type_p) -{ - tree proto = TREE_TYPE (wildcard); - - tree parm; - if (TREE_CODE (proto) == TYPE_DECL) - parm = introduce_type_template_parameter (wildcard, non_type_p); - else if (TREE_CODE (proto) == TEMPLATE_DECL) - parm = introduce_template_template_parameter (wildcard, non_type_p); - else - parm = introduce_nontype_template_parameter (wildcard, non_type_p); - - /* Wrap in a TREE_LIST for process_template_parm. Note that introduced - parameters do not retain the defaults from the source parameter. */ - return build_tree_list (NULL_TREE, parm); -} - -/* Introduce a single template parameter. */ - -static tree -introduce_template_parameter (tree parms, tree wildcard) -{ - gcc_assert (!ARGUMENT_PACK_P (wildcard)); - tree proto = TREE_TYPE (wildcard); - location_t loc = DECL_SOURCE_LOCATION (wildcard); - - /* Diagnose the case where we have C{...Args}. */ - if (WILDCARD_PACK_P (wildcard)) - { - tree id = DECL_NAME (wildcard); - error_at (loc, "%qE cannot be introduced with an ellipsis %<...%>", id); - inform (DECL_SOURCE_LOCATION (proto), "prototype declared here"); - } - - bool non_type_p; - tree parm = build_introduced_template_parameter (wildcard, non_type_p); - return process_template_parm (parms, loc, parm, non_type_p, false); -} - -/* Introduce a template parameter pack. */ - -static tree -introduce_template_parameter_pack (tree parms, tree wildcard) -{ - bool non_type_p; - tree parm = build_introduced_template_parameter (wildcard, non_type_p); - location_t loc = DECL_SOURCE_LOCATION (wildcard); - return process_template_parm (parms, loc, parm, non_type_p, true); -} - -/* Introduce the nth template parameter. */ - -static tree -introduce_template_parameter (tree parms, tree wildcards, int& index) -{ - tree deduced = TREE_VEC_ELT (wildcards, index++); - return introduce_template_parameter (parms, deduced); -} - -/* Introduce either a template parameter pack or a list of template - parameters. */ - -static tree -introduce_template_parameters (tree parms, tree wildcards, int& index) -{ - /* If the prototype was a parameter, we better have deduced an - argument pack, and that argument must be the last deduced value - in the wildcard vector. */ - tree deduced = TREE_VEC_ELT (wildcards, index++); - gcc_assert (ARGUMENT_PACK_P (deduced)); - gcc_assert (index == TREE_VEC_LENGTH (wildcards)); - - /* Introduce each element in the pack. */ - tree args = ARGUMENT_PACK_ARGS (deduced); - for (int i = 0; i < TREE_VEC_LENGTH (args); ++i) - { - tree arg = TREE_VEC_ELT (args, i); - if (WILDCARD_PACK_P (arg)) - parms = introduce_template_parameter_pack (parms, arg); - else - parms = introduce_template_parameter (parms, arg); - } - - return parms; -} - -/* Builds the template parameter list PARMS by chaining introduced - parameters from the WILDCARD vector. INDEX is the position of - the current parameter. */ - -static tree -process_introduction_parms (tree parms, tree wildcards, int& index) -{ - tree proto = get_introduction_prototype (wildcards, index); - if (template_parameter_pack_p (proto)) - return introduce_template_parameters (parms, wildcards, index); - else - return introduce_template_parameter (parms, wildcards, index); -} - -/* Ensure that all template parameters have been introduced for the concept - named in CHECK. If not, emit a diagnostic. - - Note that implicitly introducing a parameter with a default argument - creates a case where a parameter is declared, but unnamed, making - it unusable in the definition. */ - -static bool -check_introduction_list (tree intros, tree check) -{ - check = unpack_concept_check (check); - tree tmpl = TREE_OPERAND (check, 0); - if (OVL_P (tmpl)) - tmpl = OVL_FIRST (tmpl); - - tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); - if (TREE_VEC_LENGTH (intros) < TREE_VEC_LENGTH (parms)) - { - error_at (input_location, "all template parameters of %qD must " - "be introduced", tmpl); - return false; - } - - return true; -} - -/* Associates a constraint check to the current template based on the - introduction parameters. INTRO_LIST must be a TREE_VEC of WILDCARD_DECLs - containing a chained PARM_DECL which contains the identifier as well as - the source location. TMPL_DECL is the decl for the concept being used. - If we take a concept, C, this will form a check in the form of - C<INTRO_LIST> filling in any extra arguments needed by the defaults - deduced. - - Returns NULL_TREE if no concept could be matched and error_mark_node if - an error occurred when matching. */ - -tree -finish_template_introduction (tree tmpl_decl, - tree intro_list, - location_t intro_loc) -{ - /* Build a concept check to deduce the actual parameters. */ - tree expr = build_concept_check (tmpl_decl, intro_list, tf_none); - if (expr == error_mark_node) - { - error_at (intro_loc, "cannot deduce template parameters from " - "introduction list"); - return error_mark_node; - } - - if (!check_introduction_list (intro_list, expr)) - return error_mark_node; - - tree parms = deduce_concept_introduction (expr); - if (!parms) - return NULL_TREE; - - /* Build template parameter scope for introduction. */ - tree parm_list = NULL_TREE; - begin_template_parm_list (); - int nargs = MIN (TREE_VEC_LENGTH (parms), TREE_VEC_LENGTH (intro_list)); - for (int n = 0; n < nargs; ) - parm_list = process_introduction_parms (parm_list, parms, n); - parm_list = end_template_parm_list (parm_list); - - /* Update the number of arguments to reflect the number of deduced - template parameter introductions. */ - nargs = TREE_VEC_LENGTH (parm_list); - - /* Determine if any errors occurred during matching. */ - for (int i = 0; i < TREE_VEC_LENGTH (parm_list); ++i) - if (TREE_VALUE (TREE_VEC_ELT (parm_list, i)) == error_mark_node) - { - end_template_decl (); - return error_mark_node; - } - - /* Build a concept check for our constraint. */ - tree check_args = make_tree_vec (nargs); - int n = 0; - for (; n < TREE_VEC_LENGTH (parm_list); ++n) - { - tree parm = TREE_VEC_ELT (parm_list, n); - TREE_VEC_ELT (check_args, n) = template_parm_to_arg (parm); - } - SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (check_args, n); - - /* If the template expects more parameters we should be able - to use the defaults from our deduced concept. */ - for (; n < TREE_VEC_LENGTH (parms); ++n) - TREE_VEC_ELT (check_args, n) = TREE_VEC_ELT (parms, n); - - /* Associate the constraint. */ - tree check = build_concept_check (tmpl_decl, - check_args, - tf_warning_or_error); - TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = check; - - return parm_list; -} - - /* Given the concept check T from a constrained-type-specifier, extract its TMPL and ARGS. FIXME why do we need two different forms of constrained-type-specifier? */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4bb3e9c..f270b0b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7490,7 +7490,6 @@ extern tree canonical_type_parameter (tree); extern void push_access_scope (tree); extern void pop_access_scope (tree); extern bool check_template_shadow (tree); -extern bool check_auto_in_tmpl_args (tree, tree); extern tree get_innermost_template_args (tree, int); extern void maybe_begin_member_template_processing (tree); extern void maybe_end_member_template_processing (void); @@ -8592,7 +8591,6 @@ extern hashval_t hash_placeholder_constraint (tree); extern bool deduce_constrained_parameter (tree, tree&, tree&); extern tree resolve_constraint_check (tree); extern tree check_function_concept (tree); -extern tree finish_template_introduction (tree, tree, location_t loc); extern bool valid_requirements_p (tree); extern tree finish_concept_name (tree); extern tree finish_shorthand_constraint (tree, tree); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 2961610..d4c65a1 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -1017,16 +1017,6 @@ member_like_constrained_friend_p (tree decl) static bool function_requirements_equivalent_p (tree newfn, tree oldfn) { - /* In the concepts TS, the combined constraints are compared. */ - if (cxx_dialect < cxx20) - { - tree ci1 = get_constraints (oldfn); - tree ci2 = get_constraints (newfn); - tree req1 = ci1 ? CI_ASSOCIATED_CONSTRAINTS (ci1) : NULL_TREE; - tree req2 = ci2 ? CI_ASSOCIATED_CONSTRAINTS (ci2) : NULL_TREE; - return cp_tree_equal (req1, req2); - } - /* [temp.friend]/9 "Such a constrained friend function does not declare the same function as a declaration in any other scope." So no need to actually compare the requirements. */ @@ -10661,9 +10651,8 @@ grokfndecl (tree ctype, template shall be a definition. */ if (ci && (block_local - || (!flag_concepts_ts - && (!processing_template_decl - || (friendp && !memtmpl && !funcdef_flag))))) + || !processing_template_decl + || (friendp && !memtmpl && !funcdef_flag))) { if (!friendp || !processing_template_decl) error_at (location, "constraints on a non-templated function"); @@ -11366,9 +11355,6 @@ grokvardecl (tree type, } else DECL_DECLARED_CONCEPT_P (decl) = true; - if (!same_type_ignoring_top_level_qualifiers_p (type, boolean_type_node)) - error_at (declspecs->locations[ds_type_spec], - "concept must have type %<bool%>"); if (TEMPLATE_PARMS_CONSTRAINTS (current_template_parms)) { error_at (location, "a variable concept cannot be constrained"); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 31ae9c2..6bf3f52 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -16624,16 +16624,15 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /* Warn for concept as a decl-specifier. We'll rewrite these as concept declarations later. */ - if (!flag_concepts_ts) - { - cp_token *next = cp_lexer_peek_token (parser->lexer); - if (next->keyword == RID_BOOL) - permerror (next->location, "the %<bool%> keyword is not " - "allowed in a C++20 concept definition"); - else - error_at (token->location, "C++20 concept definition syntax " - "is %<concept <name> = <expr>%>"); - } + { + cp_token *next = cp_lexer_peek_token (parser->lexer); + if (next->keyword == RID_BOOL) + permerror (next->location, "the %<bool%> keyword is not " + "allowed in a C++20 concept definition"); + else + error_at (token->location, "C++20 concept definition syntax " + "is %<concept <name> = <expr>%>"); + } /* In C++20 a concept definition is just 'concept name = expr;' Support that syntax as a TS extension by pretending we've seen @@ -18431,61 +18430,6 @@ cp_parser_template_parameter_list (cp_parser* parser) return end_template_parm_list (parameter_list); } -/* Parse a introduction-list. - - introduction-list: - introduced-parameter - introduction-list , introduced-parameter - - introduced-parameter: - ...[opt] identifier - - Returns a TREE_VEC of WILDCARD_DECLs. If the parameter is a pack - then the introduced parm will have WILDCARD_PACK_P set. In addition, the - WILDCARD_DECL will also have DECL_NAME set and token location in - DECL_SOURCE_LOCATION. */ - -static tree -cp_parser_introduction_list (cp_parser *parser) -{ - vec<tree, va_gc> *introduction_vec = make_tree_vector (); - - while (true) - { - bool is_pack = cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS); - if (is_pack) - cp_lexer_consume_token (parser->lexer); - - tree identifier = cp_parser_identifier (parser); - if (identifier == error_mark_node) - break; - - /* Build placeholder. */ - tree parm = build_nt (WILDCARD_DECL); - DECL_SOURCE_LOCATION (parm) - = cp_lexer_peek_token (parser->lexer)->location; - DECL_NAME (parm) = identifier; - WILDCARD_PACK_P (parm) = is_pack; - vec_safe_push (introduction_vec, parm); - - /* If the next token is not a `,', we're done. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) - break; - /* Otherwise, consume the `,' token. */ - cp_lexer_consume_token (parser->lexer); - } - - /* Convert the vec into a TREE_VEC. */ - tree introduction_list = make_tree_vec (introduction_vec->length ()); - unsigned int n; - tree parm; - FOR_EACH_VEC_ELT (*introduction_vec, n, parm) - TREE_VEC_ELT (introduction_list, n) = parm; - - release_tree_vector (introduction_vec); - return introduction_list; -} - /* Given a declarator, get the declarator-id part, or NULL_TREE if this is an abstract declarator. */ @@ -19218,16 +19162,8 @@ cp_parser_template_id (cp_parser *parser, location_t combined_loc = make_location (token->location, token->location, parser->lexer); - /* Check for concepts autos where they don't belong. We could - identify types in some cases of identifier TEMPL, looking ahead - for a CPP_SCOPE, but that would buy us nothing: we accept auto in - types. We reject them in functions, but if what we have is an - identifier, even with none_type we can't conclude it's NOT a - type, we have to wait for template substitution. */ - if (flag_concepts && check_auto_in_tmpl_args (templ, arguments)) - template_id = error_mark_node; /* Build a representation of the specialization. */ - else if (identifier_p (templ)) + if (identifier_p (templ)) template_id = build_min_nt_loc (combined_loc, TEMPLATE_ID_EXPR, templ, arguments); @@ -20549,10 +20485,9 @@ cp_parser_simple_type_specifier (cp_parser* parser, "only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); } - else if (!flag_concepts_ts && parser->in_template_argument_list_p) - pedwarn (token->location, 0, - "use of %<auto%> in template argument " - "only available with %<-fconcepts-ts%>"); + else if (parser->in_template_argument_list_p) + error_at (token->location, + "use of %<auto%> in template argument"); else if (!flag_concepts) pedwarn (token->location, 0, "use of %<auto%> in parameter declaration " @@ -20895,10 +20830,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, TENTATIVE is true if the type-specifier parsing is tentative; in that case, don't give an error if TMPL isn't a valid type-constraint, as the template-id - might actually be a concept-check, - - Note that the Concepts TS allows the auto or decltype(auto) to be - omitted in a constrained-type-specifier. */ + might actually be a concept-check. */ static tree cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, @@ -20929,38 +20861,29 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, if (con == error_mark_node) return error_mark_node; - /* As per the standard, require auto or decltype(auto), except in some - cases (template parameter lists, -fconcepts-ts enabled). */ + /* As per the standard, require auto or decltype(auto). */ cp_token *placeholder = NULL, *close_paren = NULL; - if (cxx_dialect >= cxx20) + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)) + placeholder = cp_lexer_consume_token (parser->lexer); + else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DECLTYPE)) { - if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO)) - placeholder = cp_lexer_consume_token (parser->lexer); - else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DECLTYPE)) - { - placeholder = cp_lexer_consume_token (parser->lexer); - matching_parens parens; - parens.require_open (parser); - cp_parser_require_keyword (parser, RID_AUTO, RT_AUTO); - close_paren = parens.require_close (parser); - } + placeholder = cp_lexer_consume_token (parser->lexer); + matching_parens parens; + parens.require_open (parser); + cp_parser_require_keyword (parser, RID_AUTO, RT_AUTO); + close_paren = parens.require_close (parser); } /* A type constraint constrains a contextually determined type or type - parameter pack. However, the Concepts TS does allow concepts - to introduce non-type and template template parameters. */ + parameter pack. */ if (TREE_CODE (proto) != TYPE_DECL) { - if (!flag_concepts_ts - || !processing_template_parmlist) + if (!tentative) { - if (!tentative) - { - error_at (loc, "%qE does not constrain a type", DECL_NAME (con)); - inform (DECL_SOURCE_LOCATION (con), "concept defined here"); - } - return error_mark_node; + error_at (loc, "%qE does not constrain a type", DECL_NAME (con)); + inform (DECL_SOURCE_LOCATION (con), "concept defined here"); } + return error_mark_node; } /* In a template parameter list, a type-parameter can be introduced @@ -20978,9 +20901,7 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, } /* Diagnose issues placeholder issues. */ - if (!flag_concepts_ts - && !parser->in_result_type_constraint_p - && !placeholder) + if (!parser->in_result_type_constraint_p && !placeholder) { if (tentative) /* Perhaps it's a concept-check expression (c++/91073). */ @@ -25245,14 +25166,11 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags, abstract_declarator = NULL; bool auto_typeid_ok = false; - /* The concepts TS allows 'auto' as a type-id. */ - if (flag_concepts_ts) - auto_typeid_ok = !parser->in_type_id_in_expr_p; /* DR 625 prohibits use of auto as a template-argument. We allow 'auto' outside the template-argument-list context here only for the sake of diagnostic: grokdeclarator then can emit a better error message for e.g. using T = auto. */ - else if (flag_concepts) + if (flag_concepts) auto_typeid_ok = (!parser->in_type_id_in_expr_p && !parser->in_template_argument_list_p); @@ -25326,7 +25244,7 @@ cp_parser_template_type_arg (cp_parser *parser) parser->type_definition_forbidden_message = saved_message; /* cp_parser_type_id_1 checks for auto, but only for ->auto_is_implicit_function_template_parm_p. */ - if (cxx_dialect >= cxx14 && !flag_concepts_ts && type_uses_auto (r)) + if (cxx_dialect >= cxx14 && type_uses_auto (r)) { error ("invalid use of %<auto%> in template argument"); r = error_mark_node; @@ -31618,8 +31536,7 @@ cp_parser_constraint_logical_or_expression (cp_parser *parser, bool lambda_p) return lhs; } -/* Parse the expression after a requires-clause. This has a different grammar - than that in the concepts TS. */ +/* Parse the expression after a requires-clause. */ static tree cp_parser_requires_clause_expression (cp_parser *parser, bool lambda_p) @@ -31704,10 +31621,7 @@ cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p) else cp_lexer_consume_token (parser->lexer); - if (!flag_concepts_ts) - return cp_parser_requires_clause_expression (parser, lambda_p); - else - return cp_parser_constraint_expression (parser); + return cp_parser_requires_clause_expression (parser, lambda_p); } /*--------------------------------------------------------------------------- @@ -32082,7 +31996,7 @@ cp_parser_compound_requirement (cp_parser *parser) return error_mark_node; } } - else if (!flag_concepts_ts) + else /* P1452R2 removed the trailing-return-type option. */ error_at (type_loc, "return-type-requirement is not a type-constraint"); @@ -33228,110 +33142,6 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, vec_safe_push (unparsed_funs_with_definitions, decl); } -/* Parse a template introduction header for a template-declaration. Returns - false if tentative parse fails. */ - -static bool -cp_parser_template_introduction (cp_parser* parser, bool member_p) -{ - cp_parser_parse_tentatively (parser); - - tree saved_scope = parser->scope; - tree saved_object_scope = parser->object_scope; - tree saved_qualifying_scope = parser->qualifying_scope; - bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; - - cp_token *start_token = cp_lexer_peek_token (parser->lexer); - - /* In classes don't parse valid unnamed bitfields as invalid - template introductions. */ - if (member_p) - parser->colon_corrects_to_scope_p = false; - - /* Look for the optional `::' operator. */ - cp_parser_global_scope_opt (parser, - /*current_scope_valid_p=*/false); - /* Look for the nested-name-specifier. */ - cp_parser_nested_name_specifier_opt (parser, - /*typename_keyword_p=*/false, - /*check_dependency_p=*/true, - /*type_p=*/false, - /*is_declaration=*/false); - - cp_token *token = cp_lexer_peek_token (parser->lexer); - tree concept_name = cp_parser_identifier (parser); - - /* Look up the concept for which we will be matching - template parameters. */ - tree tmpl_decl = cp_parser_lookup_name_simple (parser, concept_name, - token->location); - parser->scope = saved_scope; - parser->object_scope = saved_object_scope; - parser->qualifying_scope = saved_qualifying_scope; - parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; - - if (concept_name == error_mark_node - || (seen_error () && !concept_definition_p (tmpl_decl))) - cp_parser_simulate_error (parser); - - /* Look for opening brace for introduction. */ - matching_braces braces; - braces.require_open (parser); - location_t open_loc = input_location; - - if (!cp_parser_parse_definitely (parser)) - return false; - - push_deferring_access_checks (dk_deferred); - - /* Build vector of placeholder parameters and grab - matching identifiers. */ - tree introduction_list = cp_parser_introduction_list (parser); - - /* Look for closing brace for introduction. */ - if (!braces.require_close (parser)) - return true; - - /* The introduction-list shall not be empty. */ - int nargs = TREE_VEC_LENGTH (introduction_list); - if (nargs == 0) - { - /* In cp_parser_introduction_list we have already issued an error. */ - return true; - } - - if (tmpl_decl == error_mark_node) - { - cp_parser_name_lookup_error (parser, concept_name, tmpl_decl, NLE_NULL, - token->location); - return true; - } - - /* Build and associate the constraint. */ - location_t introduction_loc = make_location (open_loc, - start_token->location, - parser->lexer); - tree parms = finish_template_introduction (tmpl_decl, - introduction_list, - introduction_loc); - if (parms && parms != error_mark_node) - { - if (!flag_concepts_ts) - pedwarn (introduction_loc, 0, "template-introductions" - " are not part of C++20 concepts; use %qs to enable", - "-fconcepts-ts"); - - cp_parser_template_declaration_after_parameters (parser, parms, - member_p); - return true; - } - - if (parms == NULL_TREE) - error_at (token->location, "no matching concept for template-introduction"); - - return true; -} - /* Parse a normal template-declaration following the template keyword. */ static void @@ -33423,8 +33233,6 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) cp_parser_explicit_template_declaration (parser, member_p); return true; } - else if (flag_concepts) - return cp_parser_template_introduction (parser, member_p); return false; } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index d131648..e38e024 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -3476,10 +3476,6 @@ template_heads_equivalent_p (const_tree tmpl1, const_tree tmpl2) tree parms1 = DECL_TEMPLATE_PARMS (tmpl1); tree parms2 = DECL_TEMPLATE_PARMS (tmpl2); - /* Don't change the matching rules for pre-C++20. */ - if (cxx_dialect < cxx20) - return comp_template_parms (parms1, parms2); - /* ... have the same number of template parameters, and their corresponding parameters are equivalent. */ if (!template_parameter_lists_equivalent_p (parms1, parms2)) @@ -3887,9 +3883,6 @@ struct find_parameter_pack_data /* Set of AST nodes that have been visited by the traversal. */ hash_set<tree> *visited; - /* True iff we're making a type pack expansion. */ - bool type_pack_expansion_p; - /* True iff we found a subtree that has the extra args mechanism. */ bool found_extra_args_tree_p = false; }; @@ -3936,13 +3929,6 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) t = TYPE_MAIN_VARIANT (t); /* FALLTHRU */ case TEMPLATE_TEMPLATE_PARM: - /* If the placeholder appears in the decl-specifier-seq of a function - parameter pack (14.6.3), or the type-specifier-seq of a type-id that - is a pack expansion, the invented template parameter is a template - parameter pack. */ - if (flag_concepts_ts && ppd->type_pack_expansion_p && is_auto (t) - && TEMPLATE_TYPE_LEVEL (t) != 0) - TEMPLATE_TYPE_PARAMETER_PACK (t) = true; if (TEMPLATE_TYPE_PARAMETER_PACK (t)) parameter_pack_p = true; break; @@ -4061,18 +4047,10 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) } case DECLTYPE_TYPE: - { - /* When traversing a DECLTYPE_TYPE_EXPR, we need to set - type_pack_expansion_p to false so that any placeholders - within the expression don't get marked as parameter packs. */ - bool type_pack_expansion_p = ppd->type_pack_expansion_p; - ppd->type_pack_expansion_p = false; - cp_walk_tree (&DECLTYPE_TYPE_EXPR (t), &find_parameter_packs_r, - ppd, ppd->visited); - ppd->type_pack_expansion_p = type_pack_expansion_p; - *walk_subtrees = 0; - return NULL_TREE; - } + cp_walk_tree (&DECLTYPE_TYPE_EXPR (t), &find_parameter_packs_r, + ppd, ppd->visited); + *walk_subtrees = 0; + return NULL_TREE; case IF_STMT: cp_walk_tree (&IF_COND (t), &find_parameter_packs_r, @@ -4126,7 +4104,6 @@ uses_parameter_packs (tree t) struct find_parameter_pack_data ppd; ppd.parameter_packs = ¶meter_packs; ppd.visited = new hash_set<tree>; - ppd.type_pack_expansion_p = false; cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited); delete ppd.visited; return parameter_packs; @@ -4177,7 +4154,6 @@ make_pack_expansion (tree arg, tsubst_flags_t complain) class expansion. */ ppd.visited = new hash_set<tree>; ppd.parameter_packs = ¶meter_packs; - ppd.type_pack_expansion_p = false; gcc_assert (TYPE_P (TREE_PURPOSE (arg))); cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r, &ppd, ppd.visited); @@ -4243,7 +4219,6 @@ make_pack_expansion (tree arg, tsubst_flags_t complain) /* Determine which parameter packs will be expanded. */ ppd.parameter_packs = ¶meter_packs; ppd.visited = new hash_set<tree>; - ppd.type_pack_expansion_p = TYPE_P (arg); cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited); delete ppd.visited; @@ -4302,7 +4277,6 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */) ppd.parameter_packs = ¶meter_packs; ppd.visited = new hash_set<tree>; - ppd.type_pack_expansion_p = false; cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited); delete ppd.visited; @@ -5558,7 +5532,6 @@ fixed_parameter_pack_p (tree parm) struct find_parameter_pack_data ppd; ppd.parameter_packs = ¶meter_packs; ppd.visited = new hash_set<tree>; - ppd.type_pack_expansion_p = false; fixed_parameter_pack_p_1 (parm, &ppd); @@ -17355,15 +17328,6 @@ tsubst_qualified_id (tree qualified_id, tree args, if (is_template) { - /* We may be repeating a check already done during parsing, but - if it was well-formed and passed then, it will pass again - now, and if it didn't, we wouldn't have got here. The case - we want to catch is when we couldn't tell then, and can now, - namely when templ prior to substitution was an - identifier. */ - if (flag_concepts && check_auto_in_tmpl_args (expr, template_args)) - return error_mark_node; - if (variable_template_p (expr)) expr = lookup_and_finish_template_variable (expr, template_args, complain); @@ -29629,63 +29593,6 @@ auto_hash::equal (tree t1, tree t2) return equivalent_placeholder_constraints (c1, c2); } -/* for_each_template_parm callback for extract_autos: if t is a (possibly - constrained) auto, add it to the vector. */ - -static int -extract_autos_r (tree t, void *data) -{ - hash_table<auto_hash> &hash = *(hash_table<auto_hash>*)data; - if (is_auto (t) && !template_placeholder_p (t)) - { - /* All the autos were built with index 0; fix that up now. */ - tree *p = hash.find_slot (t, INSERT); - int idx; - if (*p) - /* If this is a repeated constrained-type-specifier, use the index we - chose before. */ - idx = TEMPLATE_TYPE_IDX (*p); - else - { - /* Otherwise this is new, so use the current count. */ - *p = t; - idx = hash.elements () - 1; - } - if (idx != TEMPLATE_TYPE_IDX (t)) - { - gcc_checking_assert (TEMPLATE_TYPE_IDX (t) == 0); - gcc_checking_assert (TYPE_CANONICAL (t) != t); - TEMPLATE_TYPE_IDX (t) = idx; - TYPE_CANONICAL (t) = canonical_type_parameter (t); - } - } - - /* Always keep walking. */ - return 0; -} - -/* Return a TREE_VEC of the 'auto's used in type under the Concepts TS, which - says they can appear anywhere in the type. */ - -static tree -extract_autos (tree type) -{ - hash_set<tree> visited; - hash_table<auto_hash> hash (2); - - for_each_template_parm (type, extract_autos_r, &hash, &visited, true); - - tree tree_vec = make_tree_vec (hash.elements()); - for (tree elt : hash) - { - unsigned i = TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (elt)); - TREE_VEC_ELT (tree_vec, i) - = build_tree_list (NULL_TREE, TYPE_NAME (elt)); - } - - return tree_vec; -} - /* The stem for deduction guide names. */ const char *const dguide_base = "__dguide_"; @@ -31227,16 +31134,9 @@ do_auto_deduction (tree type, tree init, tree auto_node, return error_mark_node; tree parms = build_tree_list (NULL_TREE, type); - tree tparms; - - if (flag_concepts_ts) - tparms = extract_autos (type); - else - { - tparms = make_tree_vec (1); - TREE_VEC_ELT (tparms, 0) - = build_tree_list (NULL_TREE, TYPE_NAME (auto_node)); - } + tree tparms = make_tree_vec (1); + TREE_VEC_ELT (tparms, 0) + = build_tree_list (NULL_TREE, TYPE_NAME (auto_node)); targs = make_tree_vec (TREE_VEC_LENGTH (tparms)); int val = type_unification_real (tparms, targs, parms, &init, 1, 0, @@ -31448,66 +31348,7 @@ type_uses_auto (tree type) if (PACK_EXPANSION_P (type)) type = PACK_EXPANSION_PATTERN (type); - if (flag_concepts_ts) - { - /* The Concepts TS allows multiple autos in one type-specifier; just - return the first one we find, do_auto_deduction will collect all of - them. */ - if (uses_template_parms (type)) - return for_each_template_parm (type, is_auto_r, /*data*/NULL, - /*visited*/NULL, /*nondeduced*/false); - else - return NULL_TREE; - } - else - return find_type_usage (type, is_auto); -} - -/* Report ill-formed occurrences of auto types in ARGUMENTS. If - concepts are enabled, auto is acceptable in template arguments, but - only when TEMPL identifies a template class. Return TRUE if any - such errors were reported. */ - -bool -check_auto_in_tmpl_args (tree tmpl, tree args) -{ - if (!flag_concepts_ts) - /* Only the concepts TS allows 'auto' as a type-id; it'd otherwise - have already been rejected by the parser more generally. */ - return false; - - /* If there were previous errors, nevermind. */ - if (!args || TREE_CODE (args) != TREE_VEC) - return false; - - /* If TMPL is an identifier, we're parsing and we can't tell yet - whether TMPL is supposed to be a type, a function or a variable. - We'll only be able to tell during template substitution, so we - expect to be called again then. If concepts are enabled and we - know we have a type, we're ok. */ - if (identifier_p (tmpl) - || (DECL_P (tmpl) - && (DECL_TYPE_TEMPLATE_P (tmpl) - || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))) - return false; - - /* Quickly search for any occurrences of auto; usually there won't - be any, and then we'll avoid allocating the vector. */ - if (!type_uses_auto (args)) - return false; - - bool errors = false; - - tree vec = extract_autos (args); - for (int i = 0; i < TREE_VEC_LENGTH (vec); i++) - { - tree xauto = TREE_VALUE (TREE_VEC_ELT (vec, i)); - error_at (DECL_SOURCE_LOCATION (xauto), - "invalid use of %qT in template argument", xauto); - errors = true; - } - - return errors; + return find_type_usage (type, is_auto); } /* Recursively walk over && expressions searching for EXPR. Return a reference |