aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-04-14 16:17:34 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-04-14 16:17:34 -0400
commit943f82e7681224a36aadf743b6572ef55ec9e7ec (patch)
tree15fb63d52eb5842deac30924073c0b3cdfc5783f /gcc
parent17fb1a8ce7ef03fcd293c16fc2e5bf087b165802 (diff)
downloadgcc-943f82e7681224a36aadf743b6572ef55ec9e7ec.zip
gcc-943f82e7681224a36aadf743b6572ef55ec9e7ec.tar.gz
gcc-943f82e7681224a36aadf743b6572ef55ec9e7ec.tar.bz2
re PR c++/36625 (bogus error on __attribute__((aligned(N))) in template code)
PR c++/36625 * c-common.c (attribute_takes_identifier_p): New fn. * c-common.h: Declare it. cp/ * parser.c (cp_parser_parenthesized_expression_list): Change is_attribute_list parm to int to indicate whether or not to handle initial identifier specially. (cp_parser_attribute_list): Use attribute_takes_identifier_p. From-SVN: r158355
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/c-common.c11
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/parser.c36
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ext/attrib38.C11
7 files changed, 64 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 60f16e9..f29c405 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2010-04-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/36625
+ * c-common.c (attribute_takes_identifier_p): New fn.
+ * c-common.h: Declare it.
+
2010-04-14 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (*divmod<mode>4): Remove stray "&&" from
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 0669ba0..ac11367 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -5809,6 +5809,17 @@ c_init_attributes (void)
#undef DEF_ATTR_TREE_LIST
}
+/* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
+ identifier as an argument, so the front end shouldn't look it up. */
+
+bool
+attribute_takes_identifier_p (tree attr_id)
+{
+ return (is_attribute_p ("mode", attr_id)
+ || is_attribute_p ("format", attr_id)
+ || is_attribute_p ("cleanup", attr_id));
+}
+
/* Attribute handlers common to C front ends. */
/* Handle a "packed" attribute; arguments as in
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 6f8d832..6ed3849 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -822,6 +822,7 @@ extern void check_function_format (tree, int, tree *);
extern void set_Wformat (int);
extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
+extern bool attribute_takes_identifier_p (tree);
extern int c_common_handle_option (size_t code, const char *arg, int value);
extern bool c_common_missing_argument (const char *opt, size_t code);
extern tree c_common_type_for_mode (enum machine_mode, int);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d6be4b4..6a11a94 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2010-04-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/36625
+ * parser.c (cp_parser_parenthesized_expression_list): Change
+ is_attribute_list parm to int to indicate whether or not to
+ handle initial identifier specially.
+ (cp_parser_attribute_list): Use attribute_takes_identifier_p.
+
2010-04-13 Jason Merrill <jason@redhat.com>
* call.c (type_decays_to): Check MAYBE_CLASS_TYPE_P instead of
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e41a6d7..720a632 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1596,7 +1596,9 @@ static tree cp_parser_postfix_open_square_expression
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
static VEC(tree,gc) *cp_parser_parenthesized_expression_list
- (cp_parser *, bool, bool, bool, bool *);
+ (cp_parser *, int, bool, bool, bool *);
+/* Values for the second parameter of cp_parser_parenthesized_expression_list. */
+enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
static void cp_parser_pseudo_destructor_name
(cp_parser *, tree *, tree *);
static tree cp_parser_unary_expression
@@ -4806,7 +4808,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
parser->integral_constant_expression_p = false;
}
args = (cp_parser_parenthesized_expression_list
- (parser, /*is_attribute_list=*/false,
+ (parser, non_attr,
/*cast_p=*/false, /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
if (is_builtin_constant_p)
@@ -5244,20 +5246,22 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
Returns a vector of trees. Each element is a representation of an
assignment-expression. NULL is returned if the ( and or ) are
missing. An empty, but allocated, vector is returned on no
- expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is true
- if this is really an attribute list being parsed. If
+ expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is id_attr
+ if we are parsing an attribute list for an attribute that wants a
+ plain identifier argument, normal_attr for an attribute that wants
+ an expression, or non_attr if we aren't parsing an attribute list. If
NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or
not all of the expressions in the list were constant. */
static VEC(tree,gc) *
cp_parser_parenthesized_expression_list (cp_parser* parser,
- bool is_attribute_list,
+ int is_attribute_list,
bool cast_p,
bool allow_expansion_p,
bool *non_constant_p)
{
VEC(tree,gc) *expression_list;
- bool fold_expr_p = is_attribute_list;
+ bool fold_expr_p = is_attribute_list != non_attr;
tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
@@ -5284,7 +5288,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
/* At the beginning of attribute lists, check to see if the
next token is an identifier. */
- if (is_attribute_list
+ if (is_attribute_list == id_attr
&& cp_lexer_peek_token (parser->lexer)->type == CPP_NAME)
{
cp_token *token;
@@ -5345,7 +5349,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
/* After the first item, attribute lists look the same as
expression lists. */
- is_attribute_list = false;
+ is_attribute_list = non_attr;
get_comma:;
/* If the next token isn't a `,', then we are done. */
@@ -5820,7 +5824,8 @@ cp_parser_new_placement (cp_parser* parser)
/* Parse the expression-list. */
expression_list = (cp_parser_parenthesized_expression_list
- (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+ (parser, non_attr, /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
return expression_list;
@@ -6026,7 +6031,8 @@ cp_parser_new_initializer (cp_parser* parser)
}
else
expression_list = (cp_parser_parenthesized_expression_list
- (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+ (parser, non_attr, /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
return expression_list;
@@ -9967,7 +9973,7 @@ cp_parser_mem_initializer (cp_parser* parser)
else
{
VEC(tree,gc)* vec;
- vec = cp_parser_parenthesized_expression_list (parser, false,
+ vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false,
/*allow_expansion_p=*/true,
/*non_constant_p=*/NULL);
@@ -15453,7 +15459,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
else if (token->type == CPP_OPEN_PAREN)
{
VEC(tree,gc) *vec;
- vec = cp_parser_parenthesized_expression_list (parser, false,
+ vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false,
/*allow_expansion_p=*/true,
non_constant_p);
@@ -17768,8 +17774,10 @@ cp_parser_attribute_list (cp_parser* parser)
if (token->type == CPP_OPEN_PAREN)
{
VEC(tree,gc) *vec;
+ int attr_flag = (attribute_takes_identifier_p (identifier)
+ ? id_attr : normal_attr);
vec = cp_parser_parenthesized_expression_list
- (parser, true, /*cast_p=*/false,
+ (parser, attr_flag, /*cast_p=*/false,
/*allow_expansion_p=*/false,
/*non_constant_p=*/NULL);
if (vec == NULL)
@@ -18971,7 +18979,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
}
- vec = cp_parser_parenthesized_expression_list (parser, false,
+ vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/true,
/*allow_expansion_p=*/true,
/*non_constant_p=*/NULL);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b594279..e505fe7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/36625
+ * g++.dg/ext/attrib38.C: New.
+
2010-04-14 Steve Ellcey <sje@cup.hp.com>
PR testsuite/43739
diff --git a/gcc/testsuite/g++.dg/ext/attrib38.C b/gcc/testsuite/g++.dg/ext/attrib38.C
new file mode 100644
index 0000000..be3c7f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attrib38.C
@@ -0,0 +1,11 @@
+// PR c++/36625
+
+template <int N>
+struct A {
+ struct S { short f[3]; } __attribute__ ((aligned (N)));
+};
+
+int main ()
+{
+ A<4>::S s;
+}