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