erik.pilkington created this revision.
erik.pilkington added reviewers: aaron.ballman, rsmith, ldionne, Mordante.
Herald added subscribers: jdoerfert, ributzka, jkorous.
erik.pilkington requested review of this revision.
This is split off from D90188 <https://reviews.llvm.org/D90188>.
https://reviews.llvm.org/D91630
Files:
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Parse/Parser.h
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/test/Parser/cxx0x-attributes.cpp
Index: clang/test/Parser/cxx0x-attributes.cpp
===================================================================
--- clang/test/Parser/cxx0x-attributes.cpp
+++ clang/test/Parser/cxx0x-attributes.cpp
@@ -131,7 +131,7 @@
[[]] static_assert(true, ""); //expected-error {{an attribute list cannot appear here}}
[[]] asm(""); // expected-error {{an attribute list cannot appear here}}
-[[]] using ns::i; // expected-error {{an attribute list cannot appear here}}
+[[]] using ns::i;
[[unknown]] using namespace ns; // expected-warning {{unknown attribute 'unknown' ignored}}
[[noreturn]] using namespace ns; // expected-error {{'noreturn' attribute only applies to functions}}
namespace [[]] ns2 {} // expected-warning {{attributes on a namespace declaration are a C++17 extension}}
@@ -157,7 +157,16 @@
[[]] using T = int; // expected-error {{an attribute list cannot appear here}}
using T [[]] = int; // ok
template<typename T> using U [[]] = T;
-using ns::i [[]]; // expected-error {{an attribute list cannot appear here}}
+using ns::i [[]];
+using ns::i [[]], ns::i [[]]; // expected-warning {{use of multiple declarators in a single using declaration is a C++17 extension}}
+struct using_in_struct_base {
+ typedef int i, j, k, l;
+};
+struct using_in_struct : using_in_struct_base {
+ [[]] using using_in_struct_base::i;
+ using using_in_struct_base::j [[]];
+ [[]] using using_in_struct_base::k [[]], using_in_struct_base::l [[]]; // expected-warning {{use of multiple declarators in a single using declaration is a C++17 extension}}
+};
using [[]] ns::i; // expected-error {{an attribute list cannot appear here}}
using T [[unknown]] = int; // expected-warning {{unknown attribute 'unknown' ignored}}
using T [[noreturn]] = int; // expected-error {{'noreturn' attribute only applies to functions}}
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -497,12 +497,8 @@
}
// Otherwise, it must be a using-declaration or an alias-declaration.
-
- // Using declarations can't have attributes.
- ProhibitAttributes(attrs);
-
return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd,
- AS_none);
+ attrs, AS_none);
}
/// ParseUsingDirective - Parse C++ using-directive, assumes
@@ -675,6 +671,7 @@
Parser::ParseUsingDeclaration(DeclaratorContext Context,
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &PrefixAttrs,
AccessSpecifier AS) {
// Check for misplaced attributes before the identifier in an
// alias-declaration.
@@ -695,6 +692,8 @@
return nullptr;
}
+ ProhibitAttributes(PrefixAttrs);
+
// If we had any misplaced attributes from earlier, this is where they
// should have been written.
if (MisplacedAttrs.Range.isValid()) {
@@ -712,10 +711,8 @@
return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);
}
- // C++11 attributes are not allowed on a using-declaration, but GNU ones
- // are.
ProhibitAttributes(MisplacedAttrs);
- ProhibitAttributes(Attrs);
+ DiagnoseCXX11AttributeExtension(PrefixAttrs);
// Diagnose an attempt to declare a templated using-declaration.
// In C++11, alias-declarations can be templates:
@@ -733,8 +730,11 @@
SmallVector<Decl *, 8> DeclsInGroup;
while (true) {
- // Parse (optional) attributes (most likely GNU strong-using extension).
+ // Parse (optional) attributes.
MaybeParseGNUAttributes(Attrs);
+ MaybeParseCXX11Attributes(Attrs);
+ DiagnoseCXX11AttributeExtension(Attrs);
+ Attrs.addAll(PrefixAttrs.begin(), PrefixAttrs.end());
if (InvalidDeclarator)
SkipUntil(tok::comma, tok::semi, StopBeforeMatch);
@@ -2590,8 +2590,6 @@
MaybeParseMicrosoftAttributes(attrs);
if (Tok.is(tok::kw_using)) {
- ProhibitAttributes(attrs);
-
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
@@ -2610,7 +2608,7 @@
SourceLocation DeclEnd;
// Otherwise, it must be a using-declaration or an alias-declaration.
return ParseUsingDeclaration(DeclaratorContext::MemberContext, TemplateInfo,
- UsingLoc, DeclEnd, AS);
+ UsingLoc, DeclEnd, attrs, AS);
}
// Hold late-parsed attributes so we can attach a Decl to them later.
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -1601,6 +1601,13 @@
}
}
+void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributesWithRange &Attrs) {
+ for (const ParsedAttr &PA : Attrs) {
+ if (PA.isCXX11Attribute())
+ Diag(PA.getLoc(), diag::ext_cxx11_attr_placement) << PA;
+ }
+}
+
// Usually, `__attribute__((attrib)) class Foo {} var` means that attribute
// applies to var, not the type Foo.
// As an exception to the rule, __declspec(align(...)) before the
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2645,6 +2645,10 @@
void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
unsigned DiagID);
+ /// Emit warnings for C++11 attributes that are in a position that clang
+ /// accepts as an extension.
+ void DiagnoseCXX11AttributeExtension(ParsedAttributesWithRange &Attrs);
+
/// Skip C++11 and C2x attributes and return the end location of the
/// last one.
/// \returns SourceLocation() if there are no attributes.
@@ -2993,6 +2997,7 @@
const ParsedTemplateInfo &TemplateInfo,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &Attrs,
AccessSpecifier AS = AS_none);
Decl *ParseAliasDeclarationAfterDeclarator(
const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -686,6 +686,9 @@
def err_using_attribute_ns_conflict : Error<
"attribute with scope specifier cannot follow default scope specifier">;
def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
+def ext_cxx11_attr_placement : ExtWarn<
+ "ISO C++ does not allow an attribute list to appear here">,
+ InGroup<DiagGroup<"cxx-attribute-extension">>;
def err_attributes_misplaced : Error<"misplaced attributes; expected attributes here">;
def err_l_square_l_square_not_attribute : Error<
"C++11 only allows consecutive left square brackets when "
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits