[v20,03/40] c++: Accept the use of built-in trait identifiers
Checks
Commit Message
This patch accepts the use of built-in trait identifiers when they are
actually not used as traits. Specifically, we check if the subsequent token
is '(' for ordinary built-in traits or is '<' only for the special
__type_pack_element built-in trait. If those identifiers are used
differently, the parser treats them as normal identifiers. This allows
us to accept code like: struct __is_pointer {};.
gcc/cp/ChangeLog:
* parser.cc (cp_lexer_lookup_trait): Rename to ...
(cp_lexer_peek_trait): ... this. Handle a subsequent token for
the corresponding built-in trait.
(cp_lexer_lookup_trait_expr): Rename to ...
(cp_lexer_peek_trait_expr): ... this.
(cp_lexer_lookup_trait_type): Rename to ...
(cp_lexer_peek_trait_type): ... this.
(cp_lexer_next_token_is_decl_specifier_keyword): Call
cp_lexer_peek_trait_type.
(cp_parser_simple_type_specifier): Likewise.
(cp_parser_primary_expression): Call cp_lexer_peek_trait_expr.
Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
---
gcc/cp/parser.cc | 48 ++++++++++++++++++++++++++++++------------------
1 file changed, 30 insertions(+), 18 deletions(-)
Comments
On Sun, 15 Oct 2023, Ken Matsui wrote:
> This patch accepts the use of built-in trait identifiers when they are
> actually not used as traits. Specifically, we check if the subsequent token
> is '(' for ordinary built-in traits or is '<' only for the special
> __type_pack_element built-in trait. If those identifiers are used
> differently, the parser treats them as normal identifiers. This allows
> us to accept code like: struct __is_pointer {};.
LGTM, thanks
>
> gcc/cp/ChangeLog:
>
> * parser.cc (cp_lexer_lookup_trait): Rename to ...
> (cp_lexer_peek_trait): ... this. Handle a subsequent token for
> the corresponding built-in trait.
> (cp_lexer_lookup_trait_expr): Rename to ...
> (cp_lexer_peek_trait_expr): ... this.
> (cp_lexer_lookup_trait_type): Rename to ...
> (cp_lexer_peek_trait_type): ... this.
> (cp_lexer_next_token_is_decl_specifier_keyword): Call
> cp_lexer_peek_trait_type.
> (cp_parser_simple_type_specifier): Likewise.
> (cp_parser_primary_expression): Call cp_lexer_peek_trait_expr.
>
> Signed-off-by: Ken Matsui <kmatsui@gcc.gnu.org>
> ---
> gcc/cp/parser.cc | 48 ++++++++++++++++++++++++++++++------------------
> 1 file changed, 30 insertions(+), 18 deletions(-)
>
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index eba5272be03..0f2a1baee6a 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -246,12 +246,12 @@ static void cp_lexer_start_debugging
> (cp_lexer *) ATTRIBUTE_UNUSED;
> static void cp_lexer_stop_debugging
> (cp_lexer *) ATTRIBUTE_UNUSED;
> -static const cp_trait *cp_lexer_lookup_trait
> - (const cp_token *);
> -static const cp_trait *cp_lexer_lookup_trait_expr
> - (const cp_token *);
> -static const cp_trait *cp_lexer_lookup_trait_type
> - (const cp_token *);
> +static const cp_trait *cp_lexer_peek_trait
> + (cp_lexer *lexer, const cp_token *);
> +static const cp_trait *cp_lexer_peek_trait_expr
> + (cp_lexer *lexer, const cp_token *);
> +static const cp_trait *cp_lexer_peek_trait_type
> + (cp_lexer *lexer, const cp_token *);
>
> static cp_token_cache *cp_token_cache_new
> (cp_token *, cp_token *);
> @@ -1195,19 +1195,31 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
> }
> }
>
> -/* Look ups the corresponding built-in trait if a given token is
> +/* Peeks the corresponding built-in trait if a given token is
> a built-in trait. Otherwise, returns nullptr. */
>
> static const cp_trait *
> -cp_lexer_lookup_trait (const cp_token *token)
> +cp_lexer_peek_trait (cp_lexer *lexer, const cp_token *token1)
> {
> - tree id = token->u.value;
> + tree id = token1->u.value;
>
> - if (token->type == CPP_NAME
> + if (token1->type == CPP_NAME
> && TREE_CODE (id) == IDENTIFIER_NODE
> && IDENTIFIER_TRAIT_P (id))
> - return &cp_traits[IDENTIFIER_CP_INDEX (id)];
> + {
> + const cp_trait &trait = cp_traits[IDENTIFIER_CP_INDEX (id)];
> + const bool is_pack_element = (trait.kind == CPTK_TYPE_PACK_ELEMENT);
>
> + /* Check if the subsequent token is a `<' token to
> + __type_pack_element or is a `(' token to everything else. */
> + const cp_token *token2 = cp_lexer_peek_nth_token (lexer, 2);
> + if (is_pack_element && token2->type != CPP_LESS)
> + return nullptr;
> + if (!is_pack_element && token2->type != CPP_OPEN_PAREN)
> + return nullptr;
> +
> + return &trait;
> + }
> return nullptr;
> }
>
> @@ -1215,9 +1227,9 @@ cp_lexer_lookup_trait (const cp_token *token)
> built-in trait. */
>
> static const cp_trait *
> -cp_lexer_lookup_trait_expr (const cp_token *token)
> +cp_lexer_peek_trait_expr (cp_lexer *lexer, const cp_token *token1)
> {
> - const cp_trait *trait = cp_lexer_lookup_trait (token);
> + const cp_trait *trait = cp_lexer_peek_trait (lexer, token1);
> if (trait && !trait->type)
> return trait;
>
> @@ -1228,9 +1240,9 @@ cp_lexer_lookup_trait_expr (const cp_token *token)
> built-in trait. */
>
> static const cp_trait *
> -cp_lexer_lookup_trait_type (const cp_token *token)
> +cp_lexer_peek_trait_type (cp_lexer *lexer, const cp_token *token1)
> {
> - const cp_trait *trait = cp_lexer_lookup_trait (token);
> + const cp_trait *trait = cp_lexer_peek_trait (lexer, token1);
> if (trait && trait->type)
> return trait;
>
> @@ -1245,7 +1257,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
> cp_token *token;
>
> token = cp_lexer_peek_token (lexer);
> - if (cp_lexer_lookup_trait_type (token))
> + if (cp_lexer_peek_trait_type (lexer, token))
> return true;
> return cp_keyword_starts_decl_specifier_p (token->keyword);
> }
> @@ -6117,7 +6129,7 @@ cp_parser_primary_expression (cp_parser *parser,
> keyword. */
> case CPP_NAME:
> {
> - const cp_trait* trait = cp_lexer_lookup_trait_expr (token);
> + const cp_trait* trait = cp_lexer_peek_trait_expr (parser->lexer, token);
> if (trait)
> return cp_parser_trait (parser, trait);
> }
> @@ -20126,7 +20138,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
> }
>
> /* If token is a type-yielding built-in traits, parse it. */
> - const cp_trait* trait = cp_lexer_lookup_trait_type (token);
> + const cp_trait* trait = cp_lexer_peek_trait_type (parser->lexer, token);
> if (trait)
> {
> type = cp_parser_trait (parser, trait);
> --
> 2.42.0
>
>
@@ -246,12 +246,12 @@ static void cp_lexer_start_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
static void cp_lexer_stop_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
-static const cp_trait *cp_lexer_lookup_trait
- (const cp_token *);
-static const cp_trait *cp_lexer_lookup_trait_expr
- (const cp_token *);
-static const cp_trait *cp_lexer_lookup_trait_type
- (const cp_token *);
+static const cp_trait *cp_lexer_peek_trait
+ (cp_lexer *lexer, const cp_token *);
+static const cp_trait *cp_lexer_peek_trait_expr
+ (cp_lexer *lexer, const cp_token *);
+static const cp_trait *cp_lexer_peek_trait_type
+ (cp_lexer *lexer, const cp_token *);
static cp_token_cache *cp_token_cache_new
(cp_token *, cp_token *);
@@ -1195,19 +1195,31 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
}
}
-/* Look ups the corresponding built-in trait if a given token is
+/* Peeks the corresponding built-in trait if a given token is
a built-in trait. Otherwise, returns nullptr. */
static const cp_trait *
-cp_lexer_lookup_trait (const cp_token *token)
+cp_lexer_peek_trait (cp_lexer *lexer, const cp_token *token1)
{
- tree id = token->u.value;
+ tree id = token1->u.value;
- if (token->type == CPP_NAME
+ if (token1->type == CPP_NAME
&& TREE_CODE (id) == IDENTIFIER_NODE
&& IDENTIFIER_TRAIT_P (id))
- return &cp_traits[IDENTIFIER_CP_INDEX (id)];
+ {
+ const cp_trait &trait = cp_traits[IDENTIFIER_CP_INDEX (id)];
+ const bool is_pack_element = (trait.kind == CPTK_TYPE_PACK_ELEMENT);
+ /* Check if the subsequent token is a `<' token to
+ __type_pack_element or is a `(' token to everything else. */
+ const cp_token *token2 = cp_lexer_peek_nth_token (lexer, 2);
+ if (is_pack_element && token2->type != CPP_LESS)
+ return nullptr;
+ if (!is_pack_element && token2->type != CPP_OPEN_PAREN)
+ return nullptr;
+
+ return &trait;
+ }
return nullptr;
}
@@ -1215,9 +1227,9 @@ cp_lexer_lookup_trait (const cp_token *token)
built-in trait. */
static const cp_trait *
-cp_lexer_lookup_trait_expr (const cp_token *token)
+cp_lexer_peek_trait_expr (cp_lexer *lexer, const cp_token *token1)
{
- const cp_trait *trait = cp_lexer_lookup_trait (token);
+ const cp_trait *trait = cp_lexer_peek_trait (lexer, token1);
if (trait && !trait->type)
return trait;
@@ -1228,9 +1240,9 @@ cp_lexer_lookup_trait_expr (const cp_token *token)
built-in trait. */
static const cp_trait *
-cp_lexer_lookup_trait_type (const cp_token *token)
+cp_lexer_peek_trait_type (cp_lexer *lexer, const cp_token *token1)
{
- const cp_trait *trait = cp_lexer_lookup_trait (token);
+ const cp_trait *trait = cp_lexer_peek_trait (lexer, token1);
if (trait && trait->type)
return trait;
@@ -1245,7 +1257,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
cp_token *token;
token = cp_lexer_peek_token (lexer);
- if (cp_lexer_lookup_trait_type (token))
+ if (cp_lexer_peek_trait_type (lexer, token))
return true;
return cp_keyword_starts_decl_specifier_p (token->keyword);
}
@@ -6117,7 +6129,7 @@ cp_parser_primary_expression (cp_parser *parser,
keyword. */
case CPP_NAME:
{
- const cp_trait* trait = cp_lexer_lookup_trait_expr (token);
+ const cp_trait* trait = cp_lexer_peek_trait_expr (parser->lexer, token);
if (trait)
return cp_parser_trait (parser, trait);
}
@@ -20126,7 +20138,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
}
/* If token is a type-yielding built-in traits, parse it. */
- const cp_trait* trait = cp_lexer_lookup_trait_type (token);
+ const cp_trait* trait = cp_lexer_peek_trait_type (parser->lexer, token);
if (trait)
{
type = cp_parser_trait (parser, trait);