aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-11-21 02:50:02 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-11-20 19:50:02 -0700
commit98f08eb8939735c1e9cbc1ec5cadebe79e935c90 (patch)
tree9fb2084c7e170349abee1d8f950047936556b98a /gcc/cp
parent48d1f31d1b7131e8f809ede8256e4f1eb6c5c3ae (diff)
downloadgcc-98f08eb8939735c1e9cbc1ec5cadebe79e935c90.zip
gcc-98f08eb8939735c1e9cbc1ec5cadebe79e935c90.tar.gz
gcc-98f08eb8939735c1e9cbc1ec5cadebe79e935c90.tar.bz2
c-parser.c (c_parser_has_attribute_expression): New function.
gcc/c/ChangeLog: * c-parser.c (c_parser_has_attribute_expression): New function. (c_parser_attribute): New function. (c_parser_attributes): Move code into c_parser_attribute. (c_parser_unary_expression): Handle RID_HAS_ATTRIBUTE_EXPRESSION. gcc/c-family/ChangeLog: * c-attribs.c (type_for_vector_size): New function. (type_valid_for_vector_size): Same. (handle_vector_size_attribute): Move code to the functions above and call them. (validate_attribute, has_attribute): New functions. * c-common.h (has_attribute): Declare. (rid): Add RID_HAS_ATTRIBUTE_EXPRESSION. * c-common.c (c_common_resword): Same. gcc/cp/ChangeLog: * cp-tree.h (cp_check_const_attributes): Declare. * decl2.c (cp_check_const_attributes): Declare extern. * parser.c (cp_parser_has_attribute_expression): New function. (cp_parser_unary_expression): Handle RID_HAS_ATTRIBUTE_EXPRESSION. (cp_parser_gnu_attribute_list): Add argument. gcc/ChangeLog: * doc/extend.texi (Other Builtins): Add __builtin_has_attribute. gcc/testsuite/ChangeLog: * c-c++-common/builtin-has-attribute-2.c: New test. * c-c++-common/builtin-has-attribute-3.c: New test. * c-c++-common/builtin-has-attribute-4.c: New test. * c-c++-common/builtin-has-attribute.c: New test. * gcc.dg/builtin-has-attribute.c: New test. * gcc/testsuite/gcc.target/i386/builtin-has-attribute.c: New test. From-SVN: r266335
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/parser.c130
4 files changed, 135 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a5ee86e..a8e0544 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2018-11-20 Martin Sebor <msebor@redhat.com>
+
+ * cp-tree.h (cp_check_const_attributes): Declare.
+ * decl2.c (cp_check_const_attributes): Declare extern.
+ * parser.c (cp_parser_has_attribute_expression): New function.
+ (cp_parser_unary_expression): Handle RID_HAS_ATTRIBUTE_EXPRESSION.
+ (cp_parser_gnu_attribute_list): Add argument.
+
2018-11-20 Jakub Jelinek <jakub@redhat.com>
PR c++/88110
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index edb9494..111a123 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6491,6 +6491,7 @@ extern int parm_index (tree);
extern tree vtv_start_verification_constructor_init_function (void);
extern tree vtv_finish_verification_constructor_init_function (tree);
extern bool cp_omp_mappable_type (tree);
+extern void cp_check_const_attributes (tree);
/* in error.c */
extern const char *type_as_string (tree, int);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 7686a90..ffc0d0d 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1368,7 +1368,7 @@ cp_reconstruct_complex_type (tree type, tree bottom)
/* Replaces any constexpr expression that may be into the attributes
arguments with their reduced value. */
-static void
+void
cp_check_const_attributes (tree attributes)
{
if (attributes == error_mark_node)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 292cce1..0617f56 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2048,6 +2048,8 @@ static cp_expr cp_parser_unary_expression
(cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false);
static enum tree_code cp_parser_unary_operator
(cp_token *);
+static tree cp_parser_has_attribute_expression
+ (cp_parser *);
static tree cp_parser_new_expression
(cp_parser *);
static vec<tree, va_gc> *cp_parser_new_placement
@@ -2381,7 +2383,7 @@ static tree cp_parser_attributes_opt
static tree cp_parser_gnu_attributes_opt
(cp_parser *);
static tree cp_parser_gnu_attribute_list
- (cp_parser *);
+ (cp_parser *, bool = false);
static tree cp_parser_std_attribute
(cp_parser *, tree);
static tree cp_parser_std_attribute_spec
@@ -8110,6 +8112,9 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
return ret_expr;
}
+ case RID_BUILTIN_HAS_ATTRIBUTE:
+ return cp_parser_has_attribute_expression (parser);
+
case RID_NEW:
return cp_parser_new_expression (parser);
@@ -8407,6 +8412,121 @@ cp_parser_unary_operator (cp_token* token)
}
}
+/* Parse a __builtin_has_attribute([expr|type], attribute-spec) expression.
+ Returns a representation of the expression. */
+
+static tree
+cp_parser_has_attribute_expression (cp_parser *parser)
+{
+ location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ /* Consume the __builtin_has_attribute token. */
+ cp_lexer_consume_token (parser->lexer);
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return error_mark_node;
+
+ /* Types cannot be defined in a `sizeof' expression. Save away the
+ old message. */
+ const char *saved_message = parser->type_definition_forbidden_message;
+ /* And create the new one. */
+ const int kwd = RID_BUILTIN_HAS_ATTRIBUTE;
+ char *tmp = concat ("types may not be defined in %<",
+ IDENTIFIER_POINTER (ridpointers[kwd]),
+ "%> expressions", NULL);
+ parser->type_definition_forbidden_message = tmp;
+
+ /* The restrictions on constant-expressions do not apply inside
+ sizeof expressions. */
+ bool saved_integral_constant_expression_p
+ = parser->integral_constant_expression_p;
+ bool saved_non_integral_constant_expression_p
+ = parser->non_integral_constant_expression_p;
+ parser->integral_constant_expression_p = false;
+
+ /* Do not actually evaluate the expression. */
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+
+ tree oper = NULL_TREE;
+
+ /* We can't be sure yet whether we're looking at a type-id or an
+ expression. */
+ cp_parser_parse_tentatively (parser);
+
+ bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+ parser->in_type_id_in_expr_p = true;
+ /* Look for the type-id. */
+ oper = cp_parser_type_id (parser);
+ parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
+
+ cp_parser_parse_definitely (parser);
+
+ /* If the type-id production did not work out, then we must be
+ looking at the unary-expression production. */
+ if (!oper || oper == error_mark_node)
+ oper = cp_parser_unary_expression (parser);
+
+ /* Go back to evaluating expressions. */
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+
+ /* Free the message we created. */
+ free (tmp);
+ /* And restore the old one. */
+ parser->type_definition_forbidden_message = saved_message;
+ parser->integral_constant_expression_p
+ = saved_integral_constant_expression_p;
+ parser->non_integral_constant_expression_p
+ = saved_non_integral_constant_expression_p;
+
+ /* Consume the comma if it's there. */
+ if (!cp_parser_require (parser, CPP_COMMA, RT_COMMA))
+ {
+ cp_parser_skip_to_closing_parenthesis (parser, false, false,
+ /*consume_paren=*/true);
+ return error_mark_node;
+ }
+
+ /* Parse the attribute specification. */
+ bool ret = false;
+ location_t atloc = cp_lexer_peek_token (parser->lexer)->location;
+ if (tree attr = cp_parser_gnu_attribute_list (parser, /*exactly_one=*/true))
+ {
+ if (oper != error_mark_node)
+ {
+ /* Fold constant expressions used in attributes first. */
+ cp_check_const_attributes (attr);
+
+ /* Finally, see if OPER has been declared with ATTR. */
+ ret = has_attribute (atloc, oper, attr, default_conversion);
+ }
+
+ parens.require_close (parser);
+ }
+ else
+ {
+ error_at (atloc, "expected identifier");
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+ }
+
+ /* Construct a location e.g. :
+ __builtin_has_attribute (oper, attr)
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ with start == caret at the start of the built-in token,
+ and with the endpoint at the final closing paren. */
+ location_t finish_loc
+ = cp_lexer_previous_token (parser->lexer)->location;
+ location_t compound_loc
+ = make_location (start_loc, start_loc, finish_loc);
+
+ cp_expr ret_expr (ret ? boolean_true_node : boolean_false_node);
+ ret_expr.set_location (compound_loc);
+ ret_expr = ret_expr.maybe_add_location_wrapper ();
+ return ret_expr;
+}
+
/* Parse a new-expression.
new-expression:
@@ -25376,7 +25496,7 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
the arguments, if any. */
static tree
-cp_parser_gnu_attribute_list (cp_parser* parser)
+cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
{
tree attribute_list = NULL_TREE;
bool save_translate_strings_p = parser->translate_strings_p;
@@ -25443,9 +25563,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
token = cp_lexer_peek_token (parser->lexer);
}
- /* Now, look for more attributes. If the next token isn't a
- `,', we're done. */
- if (token->type != CPP_COMMA)
+ /* Unless EXACTLY_ONE is set look for more attributes.
+ If the next token isn't a `,', we're done. */
+ if (exactly_one || token->type != CPP_COMMA)
break;
/* Consume the comma and keep going. */