aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c5
-rw-r--r--gcc/cp/decl2.c14
-rw-r--r--gcc/cp/parser.c23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/friend7.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C10
-rw-r--r--gcc/testsuite/g++.dg/ext/attrib63.C16
9 files changed, 112 insertions, 3 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 122dadf..580db91 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6763,6 +6763,7 @@ extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, tree, tree);
extern tree splice_template_attributes (tree *, tree);
extern bool any_dependent_type_attributes_p (tree);
+extern bool any_non_type_attribute_p (tree);
extern tree cp_reconstruct_complex_type (tree, tree);
extern bool attributes_naming_typedef_ok (tree);
extern void cplus_decl_attributes (tree *, tree, int);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bc3928d..17511f0 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13741,6 +13741,11 @@ grokdeclarator (const cp_declarator *declarator,
if (friendp)
{
+ if (attrlist && !funcdef_flag
+ /* Hack to allow attributes like vector_size on a friend. */
+ && any_non_type_attribute_p (*attrlist))
+ error_at (id_loc, "attribute appertains to a friend "
+ "declaration that is not a definition");
/* Friends are treated specially. */
if (ctype == current_class_type)
; /* We already issued a permerror. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 89f874a..8e4dd6b 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1331,6 +1331,20 @@ any_dependent_type_attributes_p (tree attrs)
return false;
}
+/* True if ATTRS contains any attribute that does not require a type. */
+
+bool
+any_non_type_attribute_p (tree attrs)
+{
+ for (tree a = attrs; a; a = TREE_CHAIN (a))
+ {
+ const attribute_spec *as = lookup_attribute_spec (get_attribute_name (a));
+ if (as && !as->type_required)
+ return true;
+ }
+ return false;
+}
+
/* Return true iff ATTRS are acceptable attributes to be applied in-place
to a typedef which gives a previously unnamed class or enum a name for
linkage purposes. */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 41df5dd..c0b5795 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15146,6 +15146,16 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
if (!found_decl_spec)
break;
+ if (decl_specs->std_attributes)
+ {
+ error_at (decl_specs->locations[ds_std_attribute],
+ "standard attributes in middle of decl-specifiers");
+ inform (decl_specs->locations[ds_std_attribute],
+ "standard attributes must precede the decl-specifiers to "
+ "apply to the declaration, or follow them to apply to "
+ "the type");
+ }
+
decl_specs->any_specifiers_p = true;
/* After we see one decl-specifier, further decl-specifiers are
always optional. */
@@ -19764,11 +19774,15 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
&& ! processing_explicit_instantiation)
warning (OPT_Wattributes,
"attributes ignored on template instantiation");
+ else if (is_friend && attributes)
+ error ("attribute appertains to a friend declaration that is not "
+ "a definition");
else if (is_declaration && cp_parser_declares_only_class_p (parser))
cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
else
warning (OPT_Wattributes,
- "attributes ignored on elaborated-type-specifier that is not a forward declaration");
+ "attributes ignored on elaborated-type-specifier that is "
+ "not a forward declaration");
}
if (tag_type == enum_type)
@@ -26054,6 +26068,13 @@ cp_parser_member_declaration (cp_parser* parser)
error_at (decl_spec_token_start->location,
"friend declaration does not name a class or "
"function");
+ /* Give an error if an attribute cannot appear here, as per
+ [dcl.attr.grammar]/5. But not when declares_class_or_enum:
+ we ignore attributes in elaborated-type-specifiers. */
+ else if (!declares_class_or_enum && decl_specifiers.attributes)
+ error_at (decl_spec_token_start->location,
+ "attribute appertains to a friend declaration "
+ "that is not a definition");
else
make_friend_class (current_class_type, type,
/*complain=*/true);
diff --git a/gcc/testsuite/g++.dg/cpp0x/friend7.C b/gcc/testsuite/g++.dg/cpp0x/friend7.C
new file mode 100644
index 0000000..734b367
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/friend7.C
@@ -0,0 +1,40 @@
+// PR c++/99032
+// { dg-do compile { target c++11 } }
+
+class X { };
+template<typename T1, typename T2>
+void foo (T1, T2);
+
+struct S {
+ [[deprecated]] friend void f(); // { dg-error "attribute appertains" }
+ [[deprecated]] friend void f2() { }
+ __attribute__((deprecated)) friend void f3(); // { dg-error "attribute appertains" }
+ friend void f3 [[deprecated]] (); // { dg-error "attribute appertains" }
+ friend void f4 [[deprecated]] () { }
+ [[deprecated]] friend void; // { dg-error "attribute appertains" }
+ __attribute__((deprecated)) friend int; // { dg-error "attribute appertains" }
+ friend __attribute__((deprecated)) int; // { dg-error "attribute appertains" }
+ friend int __attribute__((deprecated)); // { dg-error "attribute appertains" }
+ [[deprecated]] friend X; // { dg-error "attribute appertains" }
+ [[deprecated]] friend class N; // { dg-warning "attribute ignored" }
+ friend class [[deprecated]] N2; // { dg-error "attribute appertains" }
+ friend class __attribute__((deprecated)) N3; // { dg-error "attribute appertains" }
+ [[deprecated]] friend void foo<>(int, int); // { dg-error "attribute appertains" }
+ [[deprecated]] friend void ::foo(int, int); // { dg-error "attribute appertains" }
+ // { dg-bogus "should have" "PR100339" { xfail *-*-* } .-1 }
+};
+
+template<typename T>
+class node { };
+
+template<typename T>
+struct A {
+ [[deprecated]] friend T; // { dg-error "attribute appertains" }
+ [[deprecated]] friend class node<T>; // { dg-warning "attribute ignored" }
+ template<typename>
+ [[deprecated]] friend class A; // { dg-warning "attribute ignored" }
+ template<typename>
+ [[deprecated]] friend void bar () { }
+ template<typename>
+ [[deprecated]] friend void baz (); // { dg-error "attribute appertains" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
index 453fc01..4010ba7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
@@ -2,7 +2,8 @@
int fragile_block(void) {
typedef
- [[gnu::aligned (16)]] // { dg-warning "ignored" }
+ [[gnu::aligned (16)]] // { dg-error "standard attributes in middle of decl-specifiers" }
+// { dg-warning "attribute ignored" "" { target *-*-* } .-1 }
struct {
int i;
} XmmUint16;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
index b401c69..c120aed 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -13,7 +13,8 @@ int one_third [[noreturn]] [[gnu::unused]] (void);
int [[gnu::unused]] one_half(); // { dg-warning "ignored" }
static
-[[noreturn]] // { dg-warning "ignored" }
+[[noreturn]] // { dg-error "standard attributes in middle of decl-specifiers" }
+// { dg-warning "attribute ignored" "" { target *-*-* } .-1 }
void two [[gnu::unused]] (void) {}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C
new file mode 100644
index 0000000..7e17bc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-74.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+// A C++11 attribute cannot appear in the middle of the decl-specifier-seq,
+// only before it (in which case it appertains to the declaration) or at
+// the end (in which case it appertains to the type).
+
+struct S {
+ friend [[deprecated]] void; // { dg-error "standard attributes in middle of decl-specifiers" }
+ friend [[deprecated]] int fn(); // { dg-error "standard attributes in middle of decl-specifiers" }
+ // { dg-warning "attribute ignored" "" { target *-*-* } .-1 }
+};
diff --git a/gcc/testsuite/g++.dg/ext/attrib63.C b/gcc/testsuite/g++.dg/ext/attrib63.C
new file mode 100644
index 0000000..e515a2b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attrib63.C
@@ -0,0 +1,16 @@
+// { dg-do compile }
+
+#define vector __attribute__((vector_size(16)))
+class A {
+ friend vector float f();
+ __attribute__((deprecated)) friend void f2(); // { dg-error "attribute appertains" }
+ friend __attribute__((deprecated, vector_size(16))) float f3(); // { dg-error "attribute appertains" }
+ friend __attribute__((vector_size(16), deprecated)) float f4(); // { dg-error "attribute appertains" }
+};
+
+vector float vf;
+vector float
+f ()
+{
+ return vf;
+}