r175575 - PR15300: Support C++11 attributes on base-specifiers. We don't support any such
Richard Smith
richard-llvm at metafoo.co.uk
Tue Feb 19 15:47:16 PST 2013
Author: rsmith
Date: Tue Feb 19 17:47:15 2013
New Revision: 175575
URL: http://llvm.org/viewvc/llvm-project?rev=175575&view=rev
Log:
PR15300: Support C++11 attributes on base-specifiers. We don't support any such
attributes yet, so just issue the appropriate diagnostics. Also generalize the
fixit for attributes-in-the-wrong-place code and reuse it here, if attributes
are placed after the access-specifier or 'virtual' in a base specifier.
Added:
cfe/trunk/test/Parser/cxx11-base-spec-attributes.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaStmtAttr.cpp
cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp
cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp
cfe/trunk/test/Parser/objcxx11-attributes.mm
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 19 17:47:15 2013
@@ -1801,9 +1801,8 @@ def warn_cxx11_gnu_attribute_on_type : W
def warn_unhandled_ms_attribute_ignored : Warning<
"__declspec attribute %0 is not supported">,
InGroup<IgnoredAttributes>;
-def warn_attribute_invalid_on_stmt : Warning<
- "attribute %0 cannot be specified on a statement">,
- InGroup<IgnoredAttributes>;
+def err_attribute_invalid_on_stmt : Error<
+ "%0 attribute cannot be applied to a statement">;
def warn_declspec_attribute_ignored : Warning<
"attribute %0 is ignored, place it after "
"\"%select{class|struct|union|interface|enum}1\" to apply attribute to "
@@ -1905,6 +1904,8 @@ def err_attribute_can_be_applied_only_to
"%0 attribute can only be applied to value declarations">;
def warn_attribute_not_on_decl : Warning<
"%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
+def err_base_specifier_attribute : Error<
+ "%0 attribute cannot be applied to a base specifier">;
// Availability attribute
def warn_availability_unknown_platform : Warning<
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Feb 19 17:47:15 2013
@@ -1814,6 +1814,17 @@ private:
return DiagnoseProhibitedCXX11Attribute();
}
bool DiagnoseProhibitedCXX11Attribute();
+ void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+ if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) &&
+ Tok.isNot(tok::kw_alignas))
+ return;
+ DiagnoseMisplacedCXX11Attribute(Attrs, CorrectLocation);
+ }
+ void DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation);
void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
if (!attrs.Range.isValid()) return;
@@ -2059,7 +2070,7 @@ private:
ParsedAttributesWithRange &Attributes);
void ParseCXXMemberSpecification(SourceLocation StartLoc,
SourceLocation AttrFixitLoc,
- ParsedAttributes &Attrs,
+ ParsedAttributesWithRange &Attrs,
unsigned TagType,
Decl *TagDecl);
ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction,
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 19 17:47:15 2013
@@ -4526,6 +4526,7 @@ public:
BaseResult ActOnBaseSpecifier(Decl *classdecl,
SourceRange SpecifierRange,
+ ParsedAttributes &Attrs,
bool Virtual, AccessSpecifier Access,
ParsedType basetype,
SourceLocation BaseLoc,
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Feb 19 17:47:15 2013
@@ -1144,6 +1144,25 @@ bool Parser::DiagnoseProhibitedCXX11Attr
llvm_unreachable("All cases handled above.");
}
+/// DiagnoseMisplacedCXX11Attribute - We have found the opening square brackets
+/// of a C++11 attribute-specifier in a location where an attribute is not
+/// permitted, but we know where the attributes ought to be written. Parse them
+/// anyway, and provide a fixit moving them to the right place.
+void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation) {
+ assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
+ Tok.is(tok::kw_alignas));
+
+ // Consume the attributes.
+ SourceLocation Loc = Tok.getLocation();
+ ParseCXX11Attributes(Attrs);
+ CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
+
+ Diag(Loc, diag::err_attributes_not_allowed)
+ << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)
+ << FixItHint::CreateRemoval(AttrRange);
+}
+
void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
<< attrs.Range;
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Feb 19 17:47:15 2013
@@ -802,15 +802,18 @@ void Parser::ParseUnderlyingTypeSpecifie
/// class. The result is either a type or null, depending on whether a type
/// name was found.
///
-/// base-type-specifier: [C++ 10.1]
+/// base-type-specifier: [C++11 class.derived]
/// class-or-decltype
-/// class-or-decltype: [C++ 10.1]
+/// class-or-decltype: [C++11 class.derived]
/// nested-name-specifier[opt] class-name
/// decltype-specifier
-/// class-name: [C++ 9.1]
+/// class-name: [C++ class.name]
/// identifier
/// simple-template-id
///
+/// In C++98, instead of base-type-specifier, we have:
+///
+/// ::[opt] nested-name-specifier[opt] class-name
Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
SourceLocation &EndLocation) {
// Ignore attempts to use typename
@@ -1636,26 +1639,33 @@ void Parser::ParseBaseClause(Decl *Class
/// 'public bar' and 'virtual private baz' are each base-specifiers.
///
/// base-specifier: [C++ class.derived]
-/// ::[opt] nested-name-specifier[opt] class-name
-/// 'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
-/// base-type-specifier
-/// access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
-/// base-type-specifier
+/// attribute-specifier-seq[opt] base-type-specifier
+/// attribute-specifier-seq[opt] 'virtual' access-specifier[opt]
+/// base-type-specifier
+/// attribute-specifier-seq[opt] access-specifier 'virtual'[opt]
+/// base-type-specifier
Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
bool IsVirtual = false;
SourceLocation StartLoc = Tok.getLocation();
+ ParsedAttributesWithRange Attributes(AttrFactory);
+ MaybeParseCXX11Attributes(Attributes);
+
// Parse the 'virtual' keyword.
if (Tok.is(tok::kw_virtual)) {
ConsumeToken();
IsVirtual = true;
}
+ CheckMisplacedCXX11Attribute(Attributes, StartLoc);
+
// Parse an (optional) access specifier.
AccessSpecifier Access = getAccessSpecifierIfPresent();
if (Access != AS_none)
ConsumeToken();
+ CheckMisplacedCXX11Attribute(Attributes, StartLoc);
+
// Parse the 'virtual' keyword (again!), in case it came after the
// access specifier.
if (Tok.is(tok::kw_virtual)) {
@@ -1669,6 +1679,8 @@ Parser::BaseResult Parser::ParseBaseSpec
IsVirtual = true;
}
+ CheckMisplacedCXX11Attribute(Attributes, StartLoc);
+
// Parse the class-name.
SourceLocation EndLocation;
SourceLocation BaseLoc;
@@ -1688,8 +1700,9 @@ Parser::BaseResult Parser::ParseBaseSpec
// Notify semantic analysis that we have parsed a complete
// base-specifier.
- return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
- BaseType.get(), BaseLoc, EllipsisLoc);
+ return Actions.ActOnBaseSpecifier(ClassDecl, Range, Attributes, IsVirtual,
+ Access, BaseType.get(), BaseLoc,
+ EllipsisLoc);
}
/// getAccessSpecifierIfPresent - Determine whether the next token is
@@ -2384,7 +2397,7 @@ ExprResult Parser::ParseCXXMemberInitial
///
void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
SourceLocation AttrFixitLoc,
- ParsedAttributes &Attrs,
+ ParsedAttributesWithRange &Attrs,
unsigned TagType, Decl *TagDecl) {
assert((TagType == DeclSpec::TST_struct ||
TagType == DeclSpec::TST_interface ||
@@ -2457,20 +2470,7 @@ void Parser::ParseCXXMemberSpecification
// These attributes are not allowed to appear here,
// and the only possible place for them to appertain
// to the class would be between class-key and class-name.
- ParsedAttributesWithRange Attributes(AttrFactory);
- MaybeParseCXX11Attributes(Attributes);
- SourceRange AttrRange = Attributes.Range;
- if (AttrRange.isValid()) {
- Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed)
- << AttrRange
- << FixItHint::CreateInsertionFromRange(AttrFixitLoc,
- CharSourceRange(AttrRange, true))
- << FixItHint::CreateRemoval(AttrRange);
-
- // Recover by adding attributes to the attribute list of the class
- // so they can be applied on the class later.
- Attrs.takeAllFrom(Attributes);
- }
+ CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);
}
if (Tok.is(tok::colon)) {
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Feb 19 17:47:15 2013
@@ -1172,6 +1172,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *
/// 'public bar' and 'virtual private baz' are each base-specifiers.
BaseResult
Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+ ParsedAttributes &Attributes,
bool Virtual, AccessSpecifier Access,
ParsedType basetype, SourceLocation BaseLoc,
SourceLocation EllipsisLoc) {
@@ -1183,6 +1184,22 @@ Sema::ActOnBaseSpecifier(Decl *classdecl
if (!Class)
return true;
+ // We do not support any C++11 attributes on base-specifiers yet.
+ // Diagnose any attributes we see.
+ if (!Attributes.empty()) {
+ for (AttributeList *Attr = Attributes.getList(); Attr;
+ Attr = Attr->getNext()) {
+ if (Attr->isInvalid() ||
+ Attr->getKind() == AttributeList::IgnoredAttribute)
+ continue;
+ Diag(Attr->getLoc(),
+ Attr->getKind() == AttributeList::UnknownAttribute
+ ? diag::warn_unknown_attribute_ignored
+ : diag::err_base_specifier_attribute)
+ << Attr->getName();
+ }
+ }
+
TypeSourceInfo *TInfo = 0;
GetTypeFromParser(basetype, &TInfo);
Modified: cfe/trunk/lib/Sema/SemaStmtAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmtAttr.cpp Tue Feb 19 17:47:15 2013
@@ -58,8 +58,8 @@ static Attr *ProcessStmtAttribute(Sema &
default:
// if we're here, then we parsed a known attribute, but didn't recognize
// it as a statement attribute => it is declaration attribute
- S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt)
- << A.getName()->getName() << St->getLocStart();
+ S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
+ << A.getName() << St->getLocStart();
return 0;
}
}
Modified: cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp (original)
+++ cfe/trunk/test/FixIt/fixit-cxx11-attributes.cpp Tue Feb 19 17:47:15 2013
@@ -32,3 +32,20 @@ namespace ClassSpecifier {
// CHECK: fix-it:{{.*}}:{27:19-27:19}
// CHECK: fix-it:{{.*}}:{29:5-29:31}
}
+
+namespace BaseSpecifier {
+ struct base1 {};
+ struct base2 {};
+ class with_base_spec : public [[a]] // expected-error {{an attribute list cannot appear here}} expected-warning {{unknown}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:26-[[@LINE-1]]:26}:"[{{\[}}a]]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:33-[[@LINE-2]]:39}:""
+ virtual [[b]] base1, // expected-error {{an attribute list cannot appear here}} expected-warning {{unknown}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:26}:"[{{\[}}b]]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:34-[[@LINE-2]]:40}:""
+ virtual [[c]] // expected-error {{an attribute list cannot appear here}} expected-warning {{unknown}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:26-[[@LINE-1]]:26}:"[{{\[}}c]]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:34-[[@LINE-2]]:40}:""
+ public [[d]] base2 {}; // expected-error {{an attribute list cannot appear here}} expected-warning {{unknown}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:26}:"[{{\[}}d]]"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:33-[[@LINE-2]]:39}:""
+}
Added: cfe/trunk/test/Parser/cxx11-base-spec-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-base-spec-attributes.cpp?rev=175575&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx11-base-spec-attributes.cpp (added)
+++ cfe/trunk/test/Parser/cxx11-base-spec-attributes.cpp Tue Feb 19 17:47:15 2013
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+struct A {};
+struct B : [[]] A {};
+struct C : [[]] virtual A {};
+struct D : [[]] public virtual A {};
+struct E : public [[]] virtual A {}; // expected-error {{an attribute list cannot appear here}}
+struct F : virtual [[]] public A {}; // expected-error {{an attribute list cannot appear here}}
+struct G : [[noreturn]] A {}; // expected-error {{'noreturn' attribute cannot be applied to a base specifier}}
+struct H : [[unknown::foobar]] A {}; // expected-warning {{unknown attribute 'foobar' ignored}}
Modified: cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp (original)
+++ cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp Tue Feb 19 17:47:15 2013
@@ -27,11 +27,11 @@ void foo(int i) {
[[unknown_attribute]] return; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
- alignas(8) ; // expected-warning {{attribute alignas cannot be specified on a statement}}
- [[noreturn]] { } // expected-warning {{attribute noreturn cannot be specified on a statement}}
- [[noreturn]] if (0) { } // expected-warning {{attribute noreturn cannot be specified on a statement}}
- [[noreturn]] for (;;); // expected-warning {{attribute noreturn cannot be specified on a statement}}
- [[noreturn]] do { // expected-warning {{attribute noreturn cannot be specified on a statement}}
+ alignas(8) ; // expected-error {{'alignas' attribute cannot be applied to a statement}}
+ [[noreturn]] { } // expected-error {{'noreturn' attribute cannot be applied to a statement}}
+ [[noreturn]] if (0) { } // expected-error {{'noreturn' attribute cannot be applied to a statement}}
+ [[noreturn]] for (;;); // expected-error {{'noreturn' attribute cannot be applied to a statement}}
+ [[noreturn]] do { // expected-error {{'noreturn' attribute cannot be applied to a statement}}
[[unavailable]] continue; // expected-warning {{unknown attribute 'unavailable' ignored}}
} while (0);
[[unknown_attributqqq]] while (0); // expected-warning {{unknown attribute 'unknown_attributqqq' ignored}}
@@ -42,7 +42,7 @@ void foo(int i) {
[[unused]] switch (i) { // expected-warning {{unknown attribute 'unused' ignored}}
[[uuid]] case 0: // expected-warning {{unknown attribute 'uuid' ignored}}
[[visibility]] default: // expected-warning {{unknown attribute 'visibility' ignored}}
- [[carries_dependency]] break; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
+ [[carries_dependency]] break; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
}
[[fastcall]] goto there; // expected-warning {{unknown attribute 'fastcall' ignored}}
@@ -54,26 +54,26 @@ void foo(int i) {
[[weakref]] return; // expected-warning {{unknown attribute 'weakref' ignored}}
- [[carries_dependency]] ; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
- [[carries_dependency]] { } // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
- [[carries_dependency]] if (0) { } // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
- [[carries_dependency]] for (;;); // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
- [[carries_dependency]] do { // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
- [[carries_dependency]] continue; // expected-warning {{attribute carries_dependency cannot be specified on a statement}} ignored}}
+ [[carries_dependency]] ; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ [[carries_dependency]] { } // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ [[carries_dependency]] if (0) { } // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ [[carries_dependency]] for (;;); // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ [[carries_dependency]] do { // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ [[carries_dependency]] continue; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}} ignored}}
} while (0);
- [[carries_dependency]] while (0); // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
+ [[carries_dependency]] while (0); // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
- [[carries_dependency]] switch (i) { // expected-warning {{attribute carries_dependency cannot be specified on a statement}} ignored}}
- [[carries_dependency]] case 0: // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
- [[carries_dependency]] default: // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
- [[carries_dependency]] break; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
+ [[carries_dependency]] switch (i) { // expected-error {{'carries_dependency' attribute cannot be applied to a statement}} ignored}}
+ [[carries_dependency]] case 0: // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ [[carries_dependency]] default: // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ [[carries_dependency]] break; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
}
- [[carries_dependency]] goto here; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
+ [[carries_dependency]] goto here; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
- [[carries_dependency]] try { // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
+ [[carries_dependency]] try { // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
} catch (...) {
}
- [[carries_dependency]] return; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
+ [[carries_dependency]] return; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
}
Modified: cfe/trunk/test/Parser/objcxx11-attributes.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx11-attributes.mm?rev=175575&r1=175574&r2=175575&view=diff
==============================================================================
--- cfe/trunk/test/Parser/objcxx11-attributes.mm (original)
+++ cfe/trunk/test/Parser/objcxx11-attributes.mm Tue Feb 19 17:47:15 2013
@@ -32,11 +32,11 @@ void f(X *noreturn) {
// An attribute is OK.
[[]];
[[int(), noreturn]]; // expected-warning {{unknown attribute 'int' ignored}} \
- // expected-warning {{attribute noreturn cannot be specified on a statement}}
+ // expected-error {{'noreturn' attribute cannot be applied to a statement}}
[[class, test(foo 'x' bar),,,]]; // expected-warning {{unknown attribute 'test' ignored}}\
// expected-warning {{unknown attribute 'class' ignored}}
- [[bitand, noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}} \
+ [[bitand, noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to a statement}} \
expected-warning {{unknown attribute 'bitand' ignored}}
// FIXME: Suppress vexing parse warning
More information about the cfe-commits
mailing list