Re: [PATCH 2/4] c-family, C: handle clang attributes [PR109877].

2023-11-13 Thread Joseph Myers
On Sun, 12 Nov 2023, Iain Sandoe wrote:

> This adds the ability to defer the validation of numeric attribute
> arguments until the sequence is parsed if the attribute being
> handled is one known to be 'clang form'.

This is only for __attribute__ and not [[]]-style attributes, is that as 
intended?  (Doing it for [[]] might be harder because of how the tokens 
after [[ have to be lexed early for Objective-C to see whether there is a 
matching ]] and thus whether it's an attribute at all.)

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [PATCH 2/4] c-family, C: handle clang attributes [PR109877].

2023-11-13 Thread Marek Polacek
On Sun, Nov 12, 2023 at 08:02:42PM -1000, Iain Sandoe wrote:
> This adds the ability to defer the validation of numeric attribute
> arguments until the sequence is parsed if the attribute being
> handled is one known to be 'clang form'.
> 
> We do this by considering the arguments to be strings regardless
> of content and defer the interpretation of those strings until the
> argument processing.

I don't see any tests here nor in the C++ part of the patch.  Is it
possible to add some (I suppose for now only attribute availability)?

FWIW, for chaining attributes it's best to use attr_chainon since that
handles error_mark_node.  Unfortunately that's currently only in cp/.
 
>   PR c++/109877
> 
> gcc/c-family/ChangeLog:
> 
>   * c-lex.cc (c_lex_with_flags): Allow for the case where
>   we wish to defer interpretation of numeric values until
>   parse time.
>   * c-pragma.h (C_LEX_NUMBER_AS_STRING): New.
> 
> gcc/c/ChangeLog:
> 
>   * c-parser.cc (struct c_parser): Provide a flag to notify
> that argument parsing should return attribute arguments
> as string constants.
>   (c_lex_one_token): Act to defer numeric value validation.
>   (c_parser_clang_attribute_arguments): New.
>   (c_parser_gnu_attribute): Allow for clang-form GNU-style
>   attributes.
> 
> Signed-off-by: Iain Sandoe 
> ---
>  gcc/c-family/c-lex.cc   |  15 ++
>  gcc/c-family/c-pragma.h |   3 ++
>  gcc/c/c-parser.cc   | 109 ++--
>  3 files changed, 122 insertions(+), 5 deletions(-)
> 
> diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
> index 06c2453c89a..d535f5b460c 100644
> --- a/gcc/c-family/c-lex.cc
> +++ b/gcc/c-family/c-lex.cc
> @@ -533,6 +533,21 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned 
> char *cpp_flags,
>  
>  case CPP_NUMBER:
>{
> + /* If the user wants number-like entities to be returned as a raw
> +string, then don't try to classify them, which emits unwanted
> +diagnostics.  */
> + if (lex_flags & C_LEX_NUMBER_AS_STRING)
> +   {
> + /* build_string adds a trailing NUL at [len].  */
> + tree num_string = build_string (tok->val.str.len + 1,
> + (const char *) tok->val.str.text);
> + TREE_TYPE (num_string) = char_array_type_node;
> + *value = num_string;
> + /* We will effectively note this as CPP_N_INVALID, because we
> +made no checks here.  */
> + break;
> +   }
> +
>   const char *suffix = NULL;
>   unsigned int flags = cpp_classify_number (parse_in, tok, , *loc);
>  
> diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
> index 98177913053..11cde74f9f0 100644
> --- a/gcc/c-family/c-pragma.h
> +++ b/gcc/c-family/c-pragma.h
> @@ -276,6 +276,9 @@ extern void pragma_lex_discard_to_eol ();
>  #define C_LEX_STRING_NO_JOIN   2 /* Do not concatenate strings
>  nor translate them into execution
>  character set.  */
> +#define C_LEX_NUMBER_AS_STRING 4 /* Do not classify a number, but
> +instead return it as a raw
> +string.  */
>  
>  /* This is not actually available to pragma parsers.  It's merely a
> convenient location to declare this function for c-lex, after
> diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
> index 703f9570dbc..16cc05d 100644
> --- a/gcc/c/c-parser.cc
> +++ b/gcc/c/c-parser.cc
> @@ -217,6 +217,9 @@ struct GTY(()) c_parser {
>   should translate them to the execution character set (false
>   inside attributes).  */
>BOOL_BITFIELD translate_strings_p : 1;
> +  /* True if we want to lex arbitrary number-like sequences as their
> + string representation.  */
> +  BOOL_BITFIELD lex_number_as_string : 1;
>  
>/* Objective-C specific parser/lexer information.  */
>  
> @@ -308,10 +311,10 @@ c_lex_one_token (c_parser *parser, c_token *token, bool 
> raw = false)
>  
>if (raw || vec_safe_length (parser->raw_tokens) == 0)
>  {
> +  int lex_flags = parser->lex_joined_string ? 0 : C_LEX_STRING_NO_JOIN;
> +  lex_flags |= parser->lex_number_as_string ? C_LEX_NUMBER_AS_STRING : 0;
>token->type = c_lex_with_flags (>value, >location,
> -   >flags,
> -   (parser->lex_joined_string
> -? 0 : C_LEX_STRING_NO_JOIN));
> +   >flags, lex_flags);
>token->id_kind = C_ID_NONE;
>token->keyword = RID_MAX;
>token->pragma_kind = PRAGMA_NONE;
> @@ -5210,6 +5213,98 @@ c_parser_gnu_attribute_any_word (c_parser *parser)
>return attr_name;
>  }
>  
> +/* Handle parsing clang-form attribute arguments, where we need to adjust
> +   the parsing rules to relate to a specific attribute.  */
> +
> +static tree

[PATCH 2/4] c-family, C: handle clang attributes [PR109877].

2023-11-12 Thread Iain Sandoe
This adds the ability to defer the validation of numeric attribute
arguments until the sequence is parsed if the attribute being
handled is one known to be 'clang form'.

We do this by considering the arguments to be strings regardless
of content and defer the interpretation of those strings until the
argument processing.

PR c++/109877

gcc/c-family/ChangeLog:

* c-lex.cc (c_lex_with_flags): Allow for the case where
we wish to defer interpretation of numeric values until
parse time.
* c-pragma.h (C_LEX_NUMBER_AS_STRING): New.

gcc/c/ChangeLog:

* c-parser.cc (struct c_parser): Provide a flag to notify
that argument parsing should return attribute arguments
as string constants.
(c_lex_one_token): Act to defer numeric value validation.
(c_parser_clang_attribute_arguments): New.
(c_parser_gnu_attribute): Allow for clang-form GNU-style
attributes.

Signed-off-by: Iain Sandoe 
---
 gcc/c-family/c-lex.cc   |  15 ++
 gcc/c-family/c-pragma.h |   3 ++
 gcc/c/c-parser.cc   | 109 ++--
 3 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index 06c2453c89a..d535f5b460c 100644
--- a/gcc/c-family/c-lex.cc
+++ b/gcc/c-family/c-lex.cc
@@ -533,6 +533,21 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned 
char *cpp_flags,
 
 case CPP_NUMBER:
   {
+   /* If the user wants number-like entities to be returned as a raw
+  string, then don't try to classify them, which emits unwanted
+  diagnostics.  */
+   if (lex_flags & C_LEX_NUMBER_AS_STRING)
+ {
+   /* build_string adds a trailing NUL at [len].  */
+   tree num_string = build_string (tok->val.str.len + 1,
+   (const char *) tok->val.str.text);
+   TREE_TYPE (num_string) = char_array_type_node;
+   *value = num_string;
+   /* We will effectively note this as CPP_N_INVALID, because we
+  made no checks here.  */
+   break;
+ }
+
const char *suffix = NULL;
unsigned int flags = cpp_classify_number (parse_in, tok, , *loc);
 
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 98177913053..11cde74f9f0 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -276,6 +276,9 @@ extern void pragma_lex_discard_to_eol ();
 #define C_LEX_STRING_NO_JOIN 2 /* Do not concatenate strings
   nor translate them into execution
   character set.  */
+#define C_LEX_NUMBER_AS_STRING   4 /* Do not classify a number, but
+  instead return it as a raw
+  string.  */
 
 /* This is not actually available to pragma parsers.  It's merely a
convenient location to declare this function for c-lex, after
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 703f9570dbc..16cc05d 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -217,6 +217,9 @@ struct GTY(()) c_parser {
  should translate them to the execution character set (false
  inside attributes).  */
   BOOL_BITFIELD translate_strings_p : 1;
+  /* True if we want to lex arbitrary number-like sequences as their
+ string representation.  */
+  BOOL_BITFIELD lex_number_as_string : 1;
 
   /* Objective-C specific parser/lexer information.  */
 
@@ -308,10 +311,10 @@ c_lex_one_token (c_parser *parser, c_token *token, bool 
raw = false)
 
   if (raw || vec_safe_length (parser->raw_tokens) == 0)
 {
+  int lex_flags = parser->lex_joined_string ? 0 : C_LEX_STRING_NO_JOIN;
+  lex_flags |= parser->lex_number_as_string ? C_LEX_NUMBER_AS_STRING : 0;
   token->type = c_lex_with_flags (>value, >location,
- >flags,
- (parser->lex_joined_string
-  ? 0 : C_LEX_STRING_NO_JOIN));
+ >flags, lex_flags);
   token->id_kind = C_ID_NONE;
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
@@ -5210,6 +5213,98 @@ c_parser_gnu_attribute_any_word (c_parser *parser)
   return attr_name;
 }
 
+/* Handle parsing clang-form attribute arguments, where we need to adjust
+   the parsing rules to relate to a specific attribute.  */
+
+static tree
+c_parser_clang_attribute_arguments (c_parser *parser, tree /*attr_id*/)
+{
+  /* We can, if required, alter the parsing on the basis of the attribute.
+ At present, we handle the availability attr, where ach entry can be :
+   identifier
+   identifier=N.MM.Z
+   identifier="string"
+   followed by ',' or ) for the last entry*/
+
+  tree attr_args = NULL_TREE;
+  if (c_parser_next_token_is (parser, CPP_NAME)
+  && c_parser_peek_token (parser)->id_kind == C_ID_ID
+