Hi again, On 9/28/18 9:15 PM, Paolo Carlini wrote:
Thanks. About the location, you are certainly right, but doesn't seem trivial. Something we can do *now* is using declspecs->locations[ds_typedef] and declspecs->locations[ds_alias], but that gives us the location of the keyword 'typedef' and 'using', respectively, whereas I think that we would like to have the location of 'auto' itself. I could look into that as a follow-up piece work
In fact, completing the work turned out to be easy: ensure that cp_parser_alias_declaration saves the location of the defining-type-id too and then consistently use locations[ds_type_spec] in the error messages. Tested x86_64-linux. Still Ok? ;)
Thanks, Paolo. ///////////////////
/cp 2018-09-29 Paolo Carlini <paolo.carl...@oracle.com> PR c++/84423 * pt.c (convert_template_argument): Immediately return error_mark_node if the second argument is erroneous. * parser.c (cp_parser_alias_declaration): Save the location of the type-id too. * decl.c (grokdeclarator): Improve error message for 'auto' in alias declaration. /testsuite 2018-09-29 Paolo Carlini <paolo.carl...@oracle.com> PR c++/84423 * g++.dg/concepts/pr84423.C: New.
Index: cp/decl.c =================================================================== --- cp/decl.c (revision 264687) +++ cp/decl.c (working copy) @@ -11879,6 +11879,7 @@ grokdeclarator (const cp_declarator *declarator, /* If this is declaring a typedef name, return a TYPE_DECL. */ if (typedef_p && decl_context != TYPENAME) { + bool alias_p = decl_spec_seq_has_spec_p (declspecs, ds_alias); tree decl; /* This declaration: @@ -11901,7 +11902,12 @@ grokdeclarator (const cp_declarator *declarator, if (type_uses_auto (type)) { - error ("typedef declared %<auto%>"); + if (alias_p) + error_at (declspecs->locations[ds_type_spec], + "%<auto%> not allowed in alias declaration"); + else + error_at (declspecs->locations[ds_type_spec], + "typedef declared %<auto%>"); type = error_mark_node; } @@ -11961,7 +11967,7 @@ grokdeclarator (const cp_declarator *declarator, inlinep, friendp, raises != NULL_TREE, declspecs->locations); - if (decl_spec_seq_has_spec_p (declspecs, ds_alias)) + if (alias_p) /* Acknowledge that this was written: `using analias = atype;'. */ TYPE_DECL_ALIAS_P (decl) = 1; Index: cp/parser.c =================================================================== --- cp/parser.c (revision 264687) +++ cp/parser.c (working copy) @@ -19073,6 +19073,7 @@ cp_parser_alias_declaration (cp_parser* parser) G_("types may not be defined in alias template declarations"); } + cp_token *type_token = cp_lexer_peek_token (parser->lexer); type = cp_parser_type_id (parser); /* Restore the error message if need be. */ @@ -19107,6 +19108,9 @@ cp_parser_alias_declaration (cp_parser* parser) set_and_check_decl_spec_loc (&decl_specs, ds_alias, using_token); + set_and_check_decl_spec_loc (&decl_specs, + ds_type_spec, + type_token); if (parser->num_template_parameter_lists && !cp_parser_check_template_parameters (parser, Index: cp/pt.c =================================================================== --- cp/pt.c (revision 264687) +++ cp/pt.c (working copy) @@ -7776,7 +7776,7 @@ convert_template_argument (tree parm, tree val; int is_type, requires_type, is_tmpl_type, requires_tmpl_type; - if (parm == error_mark_node) + if (parm == error_mark_node || error_operand_p (arg)) return error_mark_node; /* Trivially convert placeholders. */ Index: testsuite/g++.dg/concepts/pr84423.C =================================================================== --- testsuite/g++.dg/concepts/pr84423.C (nonexistent) +++ testsuite/g++.dg/concepts/pr84423.C (working copy) @@ -0,0 +1,10 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options "-fconcepts" } + +template<typename> using A = auto; // { dg-error "30:.auto. not allowed in alias declaration" } + +template<template<typename> class> struct B {}; + +B<A> b; + +typedef auto C; // { dg-error "9:typedef declared .auto." }