On Wed, Oct 3, 2012 at 12:10 PM, Matthieu Monrocq <span dir="ltr"><<a href="mailto:matthieu.monrocq@gmail.com" target="_blank">matthieu.monrocq@gmail.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On Wed, Oct 3, 2012 at 3:56 AM, Michael Han <<a href="mailto:Michael.Han@autodesk.com">Michael.Han@autodesk.com</a>> wrote:<br>
> Author: hanm<br>
> Date: Tue Oct  2 20:56:22 2012<br>
> New Revision: 165082<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=165082&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=165082&view=rev</a><br>
> Log:<br>
> Improve C++11 attribute parsing.<br>
><br>
> - General C++11 attributes were previously parsed and ignored. Now they are parsed and stored in AST.<br>
> - Add support to parse arguments of attributes that in 'gnu' namespace.<br>
> - Differentiate unknown attributes and known attributes that can't be applied to statements when emitting diagnostic.<br>
><br>
><br>
> Modified:<br>
>     cfe/trunk/include/clang/Parse/Parser.h<br>
>     cfe/trunk/lib/Parse/ParseDecl.cpp<br>
>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
>     cfe/trunk/lib/Sema/SemaStmtAttr.cpp<br>
>     cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp<br>
>     cfe/trunk/test/Parser/cxx0x-attributes.cpp<br>
>     cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp<br>
>     cfe/trunk/test/Parser/<a href="http://objcxx11-attributes.mm" target="_blank">objcxx11-attributes.mm</a><br>
>     cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/Parse/Parser.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Parse/Parser.h (original)<br>
> +++ cfe/trunk/include/clang/Parse/Parser.h Tue Oct  2 20:56:22 2012<br>
> @@ -1848,7 +1848,10 @@<br>
>    void ParseGNUAttributeArgs(IdentifierInfo *AttrName,<br>
>                               SourceLocation AttrNameLoc,<br>
>                               ParsedAttributes &Attrs,<br>
> -                             SourceLocation *EndLoc);<br>
> +                             SourceLocation *EndLoc,<br>
> +                             IdentifierInfo *ScopeName,<br>
> +                             SourceLocation ScopeLoc,<br>
> +                             AttributeList::Syntax Syntax);<br>
><br>
>    void MaybeParseCXX0XAttributes(Declarator &D) {<br>
>      if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) {<br>
> @@ -1878,6 +1881,7 @@<br>
>                                      SourceLocation *EndLoc = 0);<br>
>    void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,<br>
>                              SourceLocation *EndLoc = 0);<br>
> +<br>
>    IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc);<br>
><br>
>    void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,<br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Oct  2 20:56:22 2012<br>
> @@ -154,7 +154,8 @@<br>
>            Eof.setLocation(Tok.getLocation());<br>
>            LA->Toks.push_back(Eof);<br>
>          } else {<br>
> -          ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc);<br>
> +          ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc,<br>
> +                                0, AttrNameLoc, AttributeList::AS_GNU);<br>
>          }<br>
>        } else {<br>
>          attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc,<br>
> @@ -173,11 +174,15 @@<br>
>  }<br>
><br>
><br>
> -/// Parse the arguments to a parameterized GNU attribute<br>
> +/// Parse the arguments to a parameterized GNU attribute or<br>
> +/// a C++11 attribute in "gnu" namespace.<br>
>  void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,<br>
>                                     SourceLocation AttrNameLoc,<br>
>                                     ParsedAttributes &Attrs,<br>
> -                                   SourceLocation *EndLoc) {<br>
> +                                   SourceLocation *EndLoc,<br>
> +                                   IdentifierInfo *ScopeName,<br>
> +                                   SourceLocation ScopeLoc,<br>
> +                                   AttributeList::Syntax Syntax) {<br>
><br>
>    assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");<br>
><br>
> @@ -278,9 +283,9 @@<br>
>    SourceLocation RParen = Tok.getLocation();<br>
>    if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {<br>
>      AttributeList *attr =<br>
> -      Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc,<br>
> -                   ParmName, ParmLoc, ArgExprs.data(), ArgExprs.size(),<br>
> -                   AttributeList::AS_GNU);<br>
> +      Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen),<br>
> +                   ScopeName, ScopeLoc, ParmName, ParmLoc,<br>
> +                   ArgExprs.data(), ArgExprs.size(), Syntax);<br>
>      if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection)<br>
>        Diag(Tok, diag::err_iboutletcollection_builtintype);<br>
>    }<br>
> @@ -923,7 +928,8 @@<br>
>        if (HasFunScope)<br>
>          Actions.ActOnReenterFunctionContext(Actions.CurScope, D);<br>
><br>
> -      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);<br>
> +      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,<br>
> +                            0, LA.AttrNameLoc, AttributeList::AS_GNU);<br>
><br>
>        if (HasFunScope) {<br>
>          Actions.ActOnExitFunctionContext();<br>
> @@ -935,7 +941,8 @@<br>
>      } else {<br>
>        // If there are multiple decls, then the decl cannot be within the<br>
>        // function scope.<br>
> -      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);<br>
> +      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,<br>
> +                            0, LA.AttrNameLoc, AttributeList::AS_GNU);<br>
>      }<br>
>    } else {<br>
>      Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();<br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Oct  2 20:56:22 2012<br>
> @@ -2879,6 +2879,21 @@<br>
>    }<br>
>  }<br>
><br>
> +static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,<br>
> +                                               IdentifierInfo *ScopeName) {<br>
> +  switch (AttributeList::getKind(AttrName, ScopeName,<br>
> +                                 AttributeList::AS_CXX11)) {<br>
> +  case AttributeList::AT_CarriesDependency:<br>
> +  case AttributeList::AT_FallThrough:<br>
> +  case AttributeList::AT_NoReturn: {<br>
> +    return true;<br>
> +  }<br>
> +<br>
> +  default:<br>
> +    return false;<br>
> +  }<br>
> +}<br>
> +<br>
>  /// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently<br>
>  /// only parses standard attributes.<br>
>  ///<br>
> @@ -2963,46 +2978,38 @@<br>
>        }<br>
>      }<br>
><br>
> +    bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName);<br>
>      bool AttrParsed = false;<br>
> -    switch (AttributeList::getKind(AttrName, ScopeName,<br>
> -                                   AttributeList::AS_CXX11)) {<br>
> -    // No arguments<br>
> -    case AttributeList::AT_CarriesDependency:<br>
> -    // FIXME: implement generic support of attributes with C++11 syntax<br>
> -    // see Parse/ParseDecl.cpp: ParseGNUAttributes<br>
> -    case AttributeList::AT_FallThrough:<br>
> -    case AttributeList::AT_NoReturn: {<br>
> -      if (Tok.is(tok::l_paren)) {<br>
> -        Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)<br>
> -          << AttrName->getName();<br>
> -        break;<br>
> +<br>
> +    // Parse attribute arguments<br>
> +    if (Tok.is(tok::l_paren)) {<br>
> +      if (ScopeName && ScopeName->getName() == "gnu") {<br>
> +        ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc,<br>
> +                              ScopeName, ScopeLoc, AttributeList::AS_CXX11);<br>
> +        AttrParsed = true;<br>
> +      } else {<br>
> +        if (StandardAttr)<br>
> +          Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)<br>
> +            << AttrName->getName();<br>
> +<br>
> +        // FIXME: handle other formats of c++11 attribute arguments<br>
> +        ConsumeParen();<br>
> +        SkipUntil(tok::r_paren, false);<br>
>        }<br>
> +    }<br>
><br>
> +    if (!AttrParsed)<br>
>        attrs.addNew(AttrName,<br>
>                     SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,<br>
>                                 AttrLoc),<br>
>                     ScopeName, ScopeLoc, 0,<br>
>                     SourceLocation(), 0, 0, AttributeList::AS_CXX11);<br>
> -      AttrParsed = true;<br>
> -      break;<br>
> -    }<br>
> -<br>
> -    // Silence warnings<br>
> -    default: break;<br>
> -    }<br>
> -<br>
> -    // Skip the entire parameter clause, if any<br>
> -    if (!AttrParsed && Tok.is(tok::l_paren)) {<br>
> -      ConsumeParen();<br>
> -      // SkipUntil maintains the balancedness of tokens.<br>
> -      SkipUntil(tok::r_paren, false);<br>
> -    }<br>
><br>
>      if (Tok.is(tok::ellipsis)) {<br>
> -      if (AttrParsed)<br>
> -        Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)<br>
> -          << AttrName->getName();<br>
>        ConsumeToken();<br>
> +<br>
> +      Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)<br>
> +        << AttrName->getName();<br>
>      }<br>
>    }<br>
><br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaStmtAttr.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaStmtAttr.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaStmtAttr.cpp Tue Oct  2 20:56:22 2012<br>
> @@ -48,11 +48,16 @@<br>
>  static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,<br>
>                                    SourceRange Range) {<br>
>    switch (A.getKind()) {<br>
> +  case AttributeList::UnknownAttribute:<br>
> +    S.Diag(A.getLoc(), A.isDeclspecAttribute() ?<br>
> +           diag::warn_unhandled_ms_attribute_ignored :<br>
> +           diag::warn_unknown_attribute_ignored) << A.getName();<br>
> +    return 0;<br>
>    case AttributeList::AT_FallThrough:<br>
>      return handleFallThroughAttr(S, St, A, Range);<br>
>    default:<br>
> -    // if we're here, then we parsed an attribute, but didn't recognize it as a<br>
> -    // statement attribute => it is declaration attribute<br>
> +    // if we're here, then we parsed a known attribute, but didn't recognize<br>
> +    // it as a statement attribute => it is declaration attribute<br>
>      S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt)<br>
>          << A.getName()->getName() << St->getLocStart();<br>
>      return 0;<br>
><br>
> Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp (original)<br>
> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp Tue Oct  2 20:56:22 2012<br>
> @@ -6,7 +6,8 @@<br>
>  void f() {<br>
>    int x = 42, y[5];<br>
>    // FIXME: Produce a better diagnostic for this case.<br>
> -  int(p[[x] { return x; }()]); // expected-error {{expected ']'}}<br>
> +  int(p[[x] { return x; }()]); // expected-error {{expected ']'}} \<br>
> +  // expected-warning {{unknown attribute 'x' ignored}}<br>
>    y[[] { return 2; }()] = 2; // expected-error {{consecutive left square brackets}}<br>
>  }<br>
><br>
><br>
> Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)<br>
> +++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Tue Oct  2 20:56:22 2012<br>
> @@ -44,10 +44,15 @@<br>
>  int && [[]] rref_attr = 0;<br>
>  int array_attr [1] [[]];<br>
>  alignas(8) int aligned_attr;<br>
> -[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]]<br>
> -  int garbage_attr;<br>
> -[[,,,static, class, namespace,, inline, constexpr, mutable,, bi\<br>
> -tand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr;<br>
> +[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr; // expected-warning {{unknown attribute 'valid' ignored}}<br>
> +[[,,,static, class, namespace,, inline, constexpr, mutable,, bitand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr; // expected-warning {{unknown attribute 'static' ignored}} \<br>
> +       // expected-warning {{unknown attribute 'class' ignored}} \<br>
> +       // expected-warning {{unknown attribute 'namespace' ignored}} \<br>
> +       // expected-warning {{unknown attribute 'inline' ignored}} \<br>
> +       // expected-warning {{unknown attribute 'constexpr' ignored}} \<br>
> +       // expected-warning {{unknown attribute 'mutable' ignored}} \<br>
> +       // expected-warning {{unknown attribute 'bitand' ignored}} \<br>
> +        // expected-warning {{unknown attribute 'compl' ignored}}<br>
>  [[u8"invalid!"]] int invalid_string_attr; // expected-error {{expected ']'}}<br>
>  void fn_attr () [[]];<br>
>  void noexcept_fn_attr () noexcept [[]];<br>
> @@ -212,3 +217,9 @@<br>
>    one, /* rest are deprecated */ two, three<br>
>  };<br>
>  enum class [[]] EvenMoreSecrets {};<br>
> +<br>
> +namespace arguments {<br>
> +  // FIXME: remove the sema warnings after migrating existing gnu attributes to c++11 syntax.<br>
> +  void f(const char*, ...) [[gnu::format(printf, 1, 2)]]; // expected-warning {{unknown attribute 'format' ignored}}<br>
> +  void g() [[unknown::foo(currently arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' ignored}}<br>
> +}<br>
><br>
> Modified: cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp (original)<br>
> +++ cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp Tue Oct  2 20:56:22 2012<br>
> @@ -2,53 +2,78 @@<br>
><br>
>  void foo(int i) {<br>
><br>
> -  [[unknown_attribute]] ;<br>
> -  [[unknown_attribute]] { }<br>
> -  [[unknown_attribute]] if (0) { }<br>
> -  [[unknown_attribute]] for (;;);<br>
> -  [[unknown_attribute]] do {<br>
> -    [[unknown_attribute]] continue;<br>
> +  [[unknown_attribute]] ; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +  [[unknown_attribute]] { } // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +  [[unknown_attribute]] if (0) { } // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +  [[unknown_attribute]] for (;;); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +  [[unknown_attribute]] do { // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +    [[unknown_attribute]] continue; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
>    } while (0);<br>
> -  [[unknown_attribute]] while (0);<br>
> +  [[unknown_attribute]] while (0); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
><br>
> -  [[unknown_attribute]] switch (i) {<br>
> -    [[unknown_attribute]] case 0:<br>
> -    [[unknown_attribute]] default:<br>
> -      [[unknown_attribute]] break;<br>
> +  [[unknown_attribute]] switch (i) { // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +    [[unknown_attribute]] case 0: // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +    [[unknown_attribute]] default: // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +      [[unknown_attribute]] break; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
>    }<br>
><br>
> -  [[unknown_attribute]] goto here;<br>
> -  [[unknown_attribute]] here:<br>
> +  [[unknown_attribute]] goto here; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +  [[unknown_attribute]] here: // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
><br>
> -  [[unknown_attribute]] try {<br>
> +  [[unknown_attribute]] try { // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
>    } catch (...) {<br>
>    }<br>
><br>
> -  [[unknown_attribute]] return;<br>
> -<br>
> +  [[unknown_attribute]] return; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +<br>
><br>
>    alignas(8) ; // expected-warning {{attribute aligned cannot be specified on a statement}}<br>
>    [[noreturn]] { } // expected-warning {{attribute noreturn cannot be specified on a statement}}<br>
>    [[noreturn]] if (0) { } // expected-warning {{attribute noreturn cannot be specified on a statement}}<br>
>    [[noreturn]] for (;;); // expected-warning {{attribute noreturn cannot be specified on a statement}}<br>
>    [[noreturn]] do { // expected-warning {{attribute noreturn cannot be specified on a statement}}<br>
> -    [[unavailable]] continue; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> +    [[unavailable]] continue; // expected-warning {{unknown attribute 'unavailable' ignored}}<br>
> +  } while (0);<br>
> +  [[unknown_attributqqq]] while (0); // expected-warning {{unknown attribute 'unknown_attributqqq' ignored}}<br>
> +       // TODO: remove 'qqq' part and enjoy 'empty loop body' warning here (DiagnoseEmptyLoopBody)<br>
> +<br>
> +  [[unknown_attribute]] while (0); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}<br>
> +<br>
> +  [[unused]] switch (i) { // expected-warning {{unknown attribute 'unused' ignored}}<br>
> +    [[uuid]] case 0: // expected-warning {{unknown attribute 'uuid' ignored}}<br>
> +    [[visibility]] default: // expected-warning {{unknown attribute 'visibility' ignored}}<br>
> +      [[carries_dependency]] break; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
> +  }<br>
> +<br>
> +  [[fastcall]] goto there; // expected-warning {{unknown attribute 'fastcall' ignored}}<br>
> +  [[noinline]] there: // expected-warning {{unknown attribute 'noinline' ignored}}<br>
> +<br>
> +  [[lock_returned]] try { // expected-warning {{unknown attribute 'lock_returned' ignored}}<br>
> +  } catch (...) {<br>
> +  }<br>
> +<br>
> +  [[weakref]] return; // expected-warning {{unknown attribute 'weakref' ignored}}<br>
> +<br>
> +  [[carries_dependency]] ; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
> +  [[carries_dependency]] { } // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
> +  [[carries_dependency]] if (0) { } // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
> +  [[carries_dependency]] for (;;); // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
> +  [[carries_dependency]] do { // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
> +    [[carries_dependency]] continue; // expected-warning {{attribute carries_dependency cannot be specified on a statement}} ignored}}<br>
>    } while (0);<br>
> -  [[unknown_attributqqq]] while (0); // TODO: remove 'qqq' part and enjoy 'empty loop body' warning here (DiagnoseEmptyLoopBody)<br>
> -  [[unknown_attribute]] while (0); // no warning here yet, just an unknown attribute<br>
> +  [[carries_dependency]] while (0); // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
><br>
> -  [[unused]] switch (i) { // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> -    [[uuid]] case 0: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> -    [[visibility]] default: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> +  [[carries_dependency]] switch (i) { // expected-warning {{attribute carries_dependency cannot be specified on a statement}} ignored}}<br>
> +    [[carries_dependency]] case 0: // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
> +    [[carries_dependency]] default: // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
>        [[carries_dependency]] break; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
>    }<br>
><br>
> -  [[fastcall]] goto there; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> -  [[noinline]] there: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> +  [[carries_dependency]] goto here; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
><br>
> -  [[lock_returned]] try { // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> +  [[carries_dependency]] try { // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
>    } catch (...) {<br>
>    }<br>
><br>
> -  [[weakref]] return; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here<br>
> +  [[carries_dependency]] return; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}<br>
>  }<br>
><br>
> Modified: cfe/trunk/test/Parser/<a href="http://objcxx11-attributes.mm" target="_blank">objcxx11-attributes.mm</a><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx11-attributes.mm?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx11-attributes.mm?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Parser/<a href="http://objcxx11-attributes.mm" target="_blank">objcxx11-attributes.mm</a> (original)<br>
> +++ cfe/trunk/test/Parser/<a href="http://objcxx11-attributes.mm" target="_blank">objcxx11-attributes.mm</a> Tue Oct  2 20:56:22 2012<br>
> @@ -31,9 +31,13 @@<br>
><br>
>    // An attribute is OK.<br>
>    [[]];<br>
> -  [[int(), noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}}<br>
> -  [[class, test(foo 'x' bar),,,]];<br>
> -  [[bitand, noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}}<br>
> +  [[int(), noreturn]]; // expected-warning {{unknown attribute 'int' ignored}} \<br>
> +  // expected-warning {{attribute noreturn cannot be specified on a statement}}<br>
> +  [[class, test(foo 'x' bar),,,]]; // expected-warning {{unknown attribute 'test' ignored}}\<br>
> +  // expected-warning {{unknown attribute 'class' ignored}}<br>
> +<br>
> +  [[bitand, noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}} \<br>
> +  expected-warning {{unknown attribute 'bitand' ignored}}<br>
><br>
>    // FIXME: Suppress vexing parse warning<br>
>    [[noreturn]]int(e)(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}}<br>
> @@ -52,7 +56,11 @@<br>
>  }<br>
><br>
>  template<typename...Ts> void f(Ts ...x) {<br>
> -  [[test::foo(bar, baz)...]];<br>
> -  [[used(x)...]];<br>
> +  [[test::foo(bar, baz)...]]; // expected-error {{attribute 'foo' cannot be used as an attribute pack}} \<br>
> +  // expected-warning {{unknown attribute 'foo' ignored}}<br>
> +<br>
> +  [[used(x)...]]; // expected-error {{attribute 'used' cannot be used as an attribute pack}} \<br>
> +  // expected-warning {{unknown attribute 'used' ignored}}<br>
> +<br>
>    [[x...] { return [ X alloc ]; }() init];<br>
>  }<br>
><br>
> Modified: cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp?rev=165082&r1=165081&r2=165082&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp?rev=165082&r1=165081&r2=165082&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp (original)<br>
> +++ cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp Tue Oct  2 20:56:22 2012<br>
> @@ -42,7 +42,7 @@<br>
>    switch (n % 2) {<br>
>      case 0:<br>
>        // FIXME: This should be typo-corrected, probably.<br>
> -      [[fallthrough]];<br>
> +      [[fallthrough]]; // expected-warning{{unknown attribute 'fallthrough' ignored}}<br>
>      case 2: // expected-warning{{unannotated fall-through}} expected-note{{clang::fallthrough}} expected-note{{break;}}<br>
>        [[clang::fallthrough]];<br>
>      case 1:<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
<br>
Thanks Michael!<br>
<br>
I have one nit: the warning is on by default. Is this intentional ? I<br>
expect it will produce quite a lot of noise on codebases annotated for<br>
another compiler (gcc for example) if clang ever miss one or two gcc<br>
attributes. Since the Standard explicitly asks compilers to ignore<br>
unknown attributes it also seems strange to warn aggressively on<br>
unknown ones.<br>
<br>
What do you think ?</blockquote><div><br></div><div>The current behavior matches our existing behavior for __attribute__((unknown)). The standard doesn't say to ignore unknown attributes, it just says the behavior of non-standard attributes is implementation-defined, so we're well within our rights to issue a warning. I don't think we should silently ignore typo'd attributes!</div>
</div>