[cfe-commits] r165082 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaStmtAttr.cpp test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp test/Parser/cxx0x-attributes.cpp test/Parser/cxx11-

Matthieu Monrocq matthieu.monrocq at gmail.com
Wed Oct 3 12:10:30 PDT 2012


On Wed, Oct 3, 2012 at 3:56 AM, Michael Han <Michael.Han at autodesk.com> wrote:
> Author: hanm
> Date: Tue Oct  2 20:56:22 2012
> New Revision: 165082
>
> URL: http://llvm.org/viewvc/llvm-project?rev=165082&view=rev
> Log:
> Improve C++11 attribute parsing.
>
> - General C++11 attributes were previously parsed and ignored. Now they are parsed and stored in AST.
> - Add support to parse arguments of attributes that in 'gnu' namespace.
> - Differentiate unknown attributes and known attributes that can't be applied to statements when emitting diagnostic.
>
>
> Modified:
>     cfe/trunk/include/clang/Parse/Parser.h
>     cfe/trunk/lib/Parse/ParseDecl.cpp
>     cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaStmtAttr.cpp
>     cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp
>     cfe/trunk/test/Parser/cxx0x-attributes.cpp
>     cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp
>     cfe/trunk/test/Parser/objcxx11-attributes.mm
>     cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp
>
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Tue Oct  2 20:56:22 2012
> @@ -1848,7 +1848,10 @@
>    void ParseGNUAttributeArgs(IdentifierInfo *AttrName,
>                               SourceLocation AttrNameLoc,
>                               ParsedAttributes &Attrs,
> -                             SourceLocation *EndLoc);
> +                             SourceLocation *EndLoc,
> +                             IdentifierInfo *ScopeName,
> +                             SourceLocation ScopeLoc,
> +                             AttributeList::Syntax Syntax);
>
>    void MaybeParseCXX0XAttributes(Declarator &D) {
>      if (getLangOpts().CPlusPlus0x && isCXX11AttributeSpecifier()) {
> @@ -1878,6 +1881,7 @@
>                                      SourceLocation *EndLoc = 0);
>    void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
>                              SourceLocation *EndLoc = 0);
> +
>    IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc);
>
>    void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Oct  2 20:56:22 2012
> @@ -154,7 +154,8 @@
>            Eof.setLocation(Tok.getLocation());
>            LA->Toks.push_back(Eof);
>          } else {
> -          ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc);
> +          ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc,
> +                                0, AttrNameLoc, AttributeList::AS_GNU);
>          }
>        } else {
>          attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc,
> @@ -173,11 +174,15 @@
>  }
>
>
> -/// Parse the arguments to a parameterized GNU attribute
> +/// Parse the arguments to a parameterized GNU attribute or
> +/// a C++11 attribute in "gnu" namespace.
>  void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
>                                     SourceLocation AttrNameLoc,
>                                     ParsedAttributes &Attrs,
> -                                   SourceLocation *EndLoc) {
> +                                   SourceLocation *EndLoc,
> +                                   IdentifierInfo *ScopeName,
> +                                   SourceLocation ScopeLoc,
> +                                   AttributeList::Syntax Syntax) {
>
>    assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
>
> @@ -278,9 +283,9 @@
>    SourceLocation RParen = Tok.getLocation();
>    if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
>      AttributeList *attr =
> -      Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc,
> -                   ParmName, ParmLoc, ArgExprs.data(), ArgExprs.size(),
> -                   AttributeList::AS_GNU);
> +      Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen),
> +                   ScopeName, ScopeLoc, ParmName, ParmLoc,
> +                   ArgExprs.data(), ArgExprs.size(), Syntax);
>      if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection)
>        Diag(Tok, diag::err_iboutletcollection_builtintype);
>    }
> @@ -923,7 +928,8 @@
>        if (HasFunScope)
>          Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
>
> -      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
> +      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
> +                            0, LA.AttrNameLoc, AttributeList::AS_GNU);
>
>        if (HasFunScope) {
>          Actions.ActOnExitFunctionContext();
> @@ -935,7 +941,8 @@
>      } else {
>        // If there are multiple decls, then the decl cannot be within the
>        // function scope.
> -      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
> +      ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
> +                            0, LA.AttrNameLoc, AttributeList::AS_GNU);
>      }
>    } else {
>      Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Oct  2 20:56:22 2012
> @@ -2879,6 +2879,21 @@
>    }
>  }
>
> +static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
> +                                               IdentifierInfo *ScopeName) {
> +  switch (AttributeList::getKind(AttrName, ScopeName,
> +                                 AttributeList::AS_CXX11)) {
> +  case AttributeList::AT_CarriesDependency:
> +  case AttributeList::AT_FallThrough:
> +  case AttributeList::AT_NoReturn: {
> +    return true;
> +  }
> +
> +  default:
> +    return false;
> +  }
> +}
> +
>  /// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently
>  /// only parses standard attributes.
>  ///
> @@ -2963,46 +2978,38 @@
>        }
>      }
>
> +    bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName);
>      bool AttrParsed = false;
> -    switch (AttributeList::getKind(AttrName, ScopeName,
> -                                   AttributeList::AS_CXX11)) {
> -    // No arguments
> -    case AttributeList::AT_CarriesDependency:
> -    // FIXME: implement generic support of attributes with C++11 syntax
> -    // see Parse/ParseDecl.cpp: ParseGNUAttributes
> -    case AttributeList::AT_FallThrough:
> -    case AttributeList::AT_NoReturn: {
> -      if (Tok.is(tok::l_paren)) {
> -        Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
> -          << AttrName->getName();
> -        break;
> +
> +    // Parse attribute arguments
> +    if (Tok.is(tok::l_paren)) {
> +      if (ScopeName && ScopeName->getName() == "gnu") {
> +        ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc,
> +                              ScopeName, ScopeLoc, AttributeList::AS_CXX11);
> +        AttrParsed = true;
> +      } else {
> +        if (StandardAttr)
> +          Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
> +            << AttrName->getName();
> +
> +        // FIXME: handle other formats of c++11 attribute arguments
> +        ConsumeParen();
> +        SkipUntil(tok::r_paren, false);
>        }
> +    }
>
> +    if (!AttrParsed)
>        attrs.addNew(AttrName,
>                     SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
>                                 AttrLoc),
>                     ScopeName, ScopeLoc, 0,
>                     SourceLocation(), 0, 0, AttributeList::AS_CXX11);
> -      AttrParsed = true;
> -      break;
> -    }
> -
> -    // Silence warnings
> -    default: break;
> -    }
> -
> -    // Skip the entire parameter clause, if any
> -    if (!AttrParsed && Tok.is(tok::l_paren)) {
> -      ConsumeParen();
> -      // SkipUntil maintains the balancedness of tokens.
> -      SkipUntil(tok::r_paren, false);
> -    }
>
>      if (Tok.is(tok::ellipsis)) {
> -      if (AttrParsed)
> -        Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
> -          << AttrName->getName();
>        ConsumeToken();
> +
> +      Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
> +        << AttrName->getName();
>      }
>    }
>
>
> Modified: cfe/trunk/lib/Sema/SemaStmtAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAttr.cpp?rev=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaStmtAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmtAttr.cpp Tue Oct  2 20:56:22 2012
> @@ -48,11 +48,16 @@
>  static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
>                                    SourceRange Range) {
>    switch (A.getKind()) {
> +  case AttributeList::UnknownAttribute:
> +    S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
> +           diag::warn_unhandled_ms_attribute_ignored :
> +           diag::warn_unknown_attribute_ignored) << A.getName();
> +    return 0;
>    case AttributeList::AT_FallThrough:
>      return handleFallThroughAttr(S, St, A, Range);
>    default:
> -    // if we're here, then we parsed an attribute, but didn't recognize it as a
> -    // statement attribute => it is declaration attribute
> +    // 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();
>      return 0;
>
> Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp
> URL: 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
> ==============================================================================
> --- cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp (original)
> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp Tue Oct  2 20:56:22 2012
> @@ -6,7 +6,8 @@
>  void f() {
>    int x = 42, y[5];
>    // FIXME: Produce a better diagnostic for this case.
> -  int(p[[x] { return x; }()]); // expected-error {{expected ']'}}
> +  int(p[[x] { return x; }()]); // expected-error {{expected ']'}} \
> +  // expected-warning {{unknown attribute 'x' ignored}}
>    y[[] { return 2; }()] = 2; // expected-error {{consecutive left square brackets}}
>  }
>
>
> Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
> +++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Tue Oct  2 20:56:22 2012
> @@ -44,10 +44,15 @@
>  int && [[]] rref_attr = 0;
>  int array_attr [1] [[]];
>  alignas(8) int aligned_attr;
> -[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]]
> -  int garbage_attr;
> -[[,,,static, class, namespace,, inline, constexpr, mutable,, bi\
> -tand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr;
> +[[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}}
> +[[,,,static, class, namespace,, inline, constexpr, mutable,, bitand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr; // expected-warning {{unknown attribute 'static' ignored}} \
> +       // expected-warning {{unknown attribute 'class' ignored}} \
> +       // expected-warning {{unknown attribute 'namespace' ignored}} \
> +       // expected-warning {{unknown attribute 'inline' ignored}} \
> +       // expected-warning {{unknown attribute 'constexpr' ignored}} \
> +       // expected-warning {{unknown attribute 'mutable' ignored}} \
> +       // expected-warning {{unknown attribute 'bitand' ignored}} \
> +        // expected-warning {{unknown attribute 'compl' ignored}}
>  [[u8"invalid!"]] int invalid_string_attr; // expected-error {{expected ']'}}
>  void fn_attr () [[]];
>  void noexcept_fn_attr () noexcept [[]];
> @@ -212,3 +217,9 @@
>    one, /* rest are deprecated */ two, three
>  };
>  enum class [[]] EvenMoreSecrets {};
> +
> +namespace arguments {
> +  // FIXME: remove the sema warnings after migrating existing gnu attributes to c++11 syntax.
> +  void f(const char*, ...) [[gnu::format(printf, 1, 2)]]; // expected-warning {{unknown attribute 'format' ignored}}
> +  void g() [[unknown::foo(currently arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' 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=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp (original)
> +++ cfe/trunk/test/Parser/cxx11-stmt-attributes.cpp Tue Oct  2 20:56:22 2012
> @@ -2,53 +2,78 @@
>
>  void foo(int i) {
>
> -  [[unknown_attribute]] ;
> -  [[unknown_attribute]] { }
> -  [[unknown_attribute]] if (0) { }
> -  [[unknown_attribute]] for (;;);
> -  [[unknown_attribute]] do {
> -    [[unknown_attribute]] continue;
> +  [[unknown_attribute]] ; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +  [[unknown_attribute]] { } // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +  [[unknown_attribute]] if (0) { } // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +  [[unknown_attribute]] for (;;); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +  [[unknown_attribute]] do { // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +    [[unknown_attribute]] continue; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
>    } while (0);
> -  [[unknown_attribute]] while (0);
> +  [[unknown_attribute]] while (0); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
>
> -  [[unknown_attribute]] switch (i) {
> -    [[unknown_attribute]] case 0:
> -    [[unknown_attribute]] default:
> -      [[unknown_attribute]] break;
> +  [[unknown_attribute]] switch (i) { // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +    [[unknown_attribute]] case 0: // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +    [[unknown_attribute]] default: // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +      [[unknown_attribute]] break; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
>    }
>
> -  [[unknown_attribute]] goto here;
> -  [[unknown_attribute]] here:
> +  [[unknown_attribute]] goto here; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +  [[unknown_attribute]] here: // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
>
> -  [[unknown_attribute]] try {
> +  [[unknown_attribute]] try { // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
>    } catch (...) {
>    }
>
> -  [[unknown_attribute]] return;
> -
> +  [[unknown_attribute]] return; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +
>
>    alignas(8) ; // expected-warning {{attribute aligned 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}}
> -    [[unavailable]] continue; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> +    [[unavailable]] continue; // expected-warning {{unknown attribute 'unavailable' ignored}}
> +  } while (0);
> +  [[unknown_attributqqq]] while (0); // expected-warning {{unknown attribute 'unknown_attributqqq' ignored}}
> +       // TODO: remove 'qqq' part and enjoy 'empty loop body' warning here (DiagnoseEmptyLoopBody)
> +
> +  [[unknown_attribute]] while (0); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
> +
> +  [[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}}
> +  }
> +
> +  [[fastcall]] goto there; // expected-warning {{unknown attribute 'fastcall' ignored}}
> +  [[noinline]] there: // expected-warning {{unknown attribute 'noinline' ignored}}
> +
> +  [[lock_returned]] try { // expected-warning {{unknown attribute 'lock_returned' ignored}}
> +  } catch (...) {
> +  }
> +
> +  [[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}}
>    } while (0);
> -  [[unknown_attributqqq]] while (0); // TODO: remove 'qqq' part and enjoy 'empty loop body' warning here (DiagnoseEmptyLoopBody)
> -  [[unknown_attribute]] while (0); // no warning here yet, just an unknown attribute
> +  [[carries_dependency]] while (0); // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
>
> -  [[unused]] switch (i) { // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> -    [[uuid]] case 0: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> -    [[visibility]] default: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> +  [[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}}
>    }
>
> -  [[fastcall]] goto there; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> -  [[noinline]] there: // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> +  [[carries_dependency]] goto here; // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
>
> -  [[lock_returned]] try { // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> +  [[carries_dependency]] try { // expected-warning {{attribute carries_dependency cannot be specified on a statement}}
>    } catch (...) {
>    }
>
> -  [[weakref]] return; // TODO: only noreturn, alignas and carries_dependency are parsed in C++ 11 syntax at the moment, hence no warning here
> +  [[carries_dependency]] return; // expected-warning {{attribute carries_dependency cannot be specified on 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=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/test/Parser/objcxx11-attributes.mm (original)
> +++ cfe/trunk/test/Parser/objcxx11-attributes.mm Tue Oct  2 20:56:22 2012
> @@ -31,9 +31,13 @@
>
>    // An attribute is OK.
>    [[]];
> -  [[int(), noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}}
> -  [[class, test(foo 'x' bar),,,]];
> -  [[bitand, noreturn]]; // expected-warning {{attribute noreturn cannot be specified on a statement}}
> +  [[int(), noreturn]]; // expected-warning {{unknown attribute 'int' ignored}} \
> +  // expected-warning {{attribute noreturn cannot be specified on 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}} \
> +  expected-warning {{unknown attribute 'bitand' ignored}}
>
>    // FIXME: Suppress vexing parse warning
>    [[noreturn]]int(e)(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}}
> @@ -52,7 +56,11 @@
>  }
>
>  template<typename...Ts> void f(Ts ...x) {
> -  [[test::foo(bar, baz)...]];
> -  [[used(x)...]];
> +  [[test::foo(bar, baz)...]]; // expected-error {{attribute 'foo' cannot be used as an attribute pack}} \
> +  // expected-warning {{unknown attribute 'foo' ignored}}
> +
> +  [[used(x)...]]; // expected-error {{attribute 'used' cannot be used as an attribute pack}} \
> +  // expected-warning {{unknown attribute 'used' ignored}}
> +
>    [[x...] { return [ X alloc ]; }() init];
>  }
>
> Modified: cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp?rev=165082&r1=165081&r2=165082&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp (original)
> +++ cfe/trunk/test/SemaCXX/switch-implicit-fallthrough-per-method.cpp Tue Oct  2 20:56:22 2012
> @@ -42,7 +42,7 @@
>    switch (n % 2) {
>      case 0:
>        // FIXME: This should be typo-corrected, probably.
> -      [[fallthrough]];
> +      [[fallthrough]]; // expected-warning{{unknown attribute 'fallthrough' ignored}}
>      case 2: // expected-warning{{unannotated fall-through}} expected-note{{clang::fallthrough}} expected-note{{break;}}
>        [[clang::fallthrough]];
>      case 1:
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Thanks Michael!

I have one nit: the warning is on by default. Is this intentional ? I
expect it will produce quite a lot of noise on codebases annotated for
another compiler (gcc for example) if clang ever miss one or two gcc
attributes. Since the Standard explicitly asks compilers to ignore
unknown attributes it also seems strange to warn aggressively on
unknown ones.

What do you think ?

-- Matthieu



More information about the cfe-commits mailing list