[cfe-commits] r159072 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/ParseObjc.cpp lib/Parse/ParseStmt.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp test/Parser/cxx0x-attributes.cpp

David Dean david_dean at apple.com
Sat Jun 23 11:24:15 PDT 2012


Hi Sean,
	Testing of libcxx built after this change has resulted in a build failure:

In file included from ../include/__mutex_base:16:
../include/system_error:247:1: error: expected identifier or '{'
_LIBCPP_DECLARE_STRONG_ENUM(errc)
^
../include/__config:411:51: note: expanded from macro '_LIBCPP_DECLARE_STRONG_ENUM'
#define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_VISIBLE x
                                                  ^
../include/__config:125:25: note: expanded from macro '_LIBCPP_VISIBLE'
#define _LIBCPP_VISIBLE __attribute__ ((__visibility__("default")))
                        ^



On 22 Jun 2012, at 10:07 PM, Sean Hunt wrote:

> Author: coppro
> Date: Sat Jun 23 00:07:58 2012
> New Revision: 159072
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=159072&view=rev
> Log:
> Clean up a large number of C++11 attribute parse issues, including parsing
> attributes in more places where we didn't and catching a lot more issues.
> 
> This implements nearly every aspect of C++11 attribute parsing, except for:
> - Attributes are permitted on explicit instantiations inside the declarator
>   (but not preceding the decl-spec)
> - Attributes are permitted on friend declarations of functions.
> - Multiple instances of the same attribute in an attribute-list (e.g.
>   [[noreturn, noreturn]], not [[noreturn]] [[noreturn]] which is conforming)
>   are allowed.
> The first two are marked as expected-FIXME in the test file and the latter
> is probably a defect and is currently untested.
> 
> Thanks to Richard Smith for providing the lion's share of the testcases.
> 
> Modified:
>    cfe/trunk/include/clang/Parse/Parser.h
>    cfe/trunk/lib/Parse/ParseDecl.cpp
>    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
>    cfe/trunk/lib/Parse/ParseExprCXX.cpp
>    cfe/trunk/lib/Parse/ParseObjc.cpp
>    cfe/trunk/lib/Parse/ParseStmt.cpp
>    cfe/trunk/lib/Parse/ParseTemplate.cpp
>    cfe/trunk/lib/Parse/Parser.cpp
>    cfe/trunk/test/Parser/cxx0x-attributes.cpp
> 
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Sat Jun 23 00:07:58 2012
> @@ -1045,10 +1045,13 @@
>                                           ParsingDeclSpec *DS = 0);
>   bool isDeclarationAfterDeclarator();
>   bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
> -  DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
> -                                                  AccessSpecifier AS = AS_none);
> -  DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
> +  DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
> +                                                  ParsedAttributesWithRange &attrs,
> +                                                  ParsingDeclSpec *DS = 0,
>                                                   AccessSpecifier AS = AS_none);
> +  DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
> +                                                ParsingDeclSpec &DS,
> +                                                AccessSpecifier AS);
> 
>   Decl *ParseFunctionDefinition(ParsingDeclarator &D,
>                  const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
> @@ -1496,7 +1499,7 @@
>   DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts,
>                                         unsigned Context,
>                                         SourceLocation &DeclEnd,
> -                                        ParsedAttributes &attrs,
> +                                        ParsedAttributesWithRange &attrs,
>                                         bool RequireSemi,
>                                         ForRangeInit *FRI = 0);
>   bool MightBeDeclarator(unsigned Context);
> 
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Jun 23 00:07:58 2012
> @@ -1126,10 +1126,12 @@
> 
> ///       simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
> ///         declaration-specifiers init-declarator-list[opt] ';'
> +/// [C++11] attribute-specifier-seq decl-specifier-seq[opt]
> +///             init-declarator-list ';'
> ///[C90/C++]init-declarator-list ';'                             [TODO]
> /// [OMP]   threadprivate-directive                              [TODO]
> ///
> -///       for-range-declaration: [C++0x 6.5p1: stmt.ranged]
> +///       for-range-declaration: [C++11 6.5p1: stmt.ranged]
> ///         attribute-specifier-seq[opt] type-specifier-seq declarator
> ///
> /// If RequireSemi is false, this does not check for a ';' at the end of the
> @@ -1138,12 +1140,11 @@
> /// If FRI is non-null, we might be parsing a for-range-declaration instead
> /// of a simple-declaration. If we find that we are, we also parse the
> /// for-range-initializer, and place it here.
> -Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, 
> -                                                      unsigned Context,
> -                                                      SourceLocation &DeclEnd,
> -                                                      ParsedAttributes &attrs,
> -                                                      bool RequireSemi,
> -                                                      ForRangeInit *FRI) {
> +Parser::DeclGroupPtrTy
> +Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context,
> +                               SourceLocation &DeclEnd,
> +                               ParsedAttributesWithRange &attrs,
> +                               bool RequireSemi, ForRangeInit *FRI) {
>   // Parse the common declaration-specifiers piece.
>   ParsingDeclSpec DS(*this);
>   DS.takeAttributesFrom(attrs);
> @@ -2026,6 +2027,8 @@
>   }
> 
>   bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
> +  bool AttrsLastTime = false;
> +  ParsedAttributesWithRange attrs(AttrFactory);
>   while (1) {
>     bool isInvalid = false;
>     const char *PrevSpec = 0;
> @@ -2036,14 +2039,32 @@
>     switch (Tok.getKind()) {
>     default:
>     DoneWithDeclSpec:
> -      // [C++0x] decl-specifier-seq: decl-specifier attribute-specifier-seq[opt]
> -      MaybeParseCXX0XAttributes(DS.getAttributes());
> +      if (!AttrsLastTime)
> +        ProhibitAttributes(attrs);
> +      else
> +        DS.takeAttributesFrom(attrs);
> 
>       // If this is not a declaration specifier token, we're done reading decl
>       // specifiers.  First verify that DeclSpec's are consistent.
>       DS.Finish(Diags, PP);
>       return;
> 
> +    case tok::l_square:
> +    case tok::kw_alignas:
> +      if (!isCXX11AttributeSpecifier())
> +        goto DoneWithDeclSpec;
> +
> +      ProhibitAttributes(attrs);
> +      // FIXME: It would be good to recover by accepting the attributes,
> +      //        but attempting to do that now would cause serious
> +      //        madness in terms of diagnostics.
> +      attrs.clear();
> +      attrs.Range = SourceRange();
> +
> +      ParseCXX11Attributes(attrs);
> +      AttrsLastTime = true;
> +      continue; 
> +
>     case tok::code_completion: {
>       Sema::ParserCompletionContext CCC = Sema::PCC_Namespace;
>       if (DS.hasTypeSpecifier()) {
> @@ -2696,6 +2717,8 @@
>     DS.SetRangeEnd(Tok.getLocation());
>     if (DiagID != diag::err_bool_redeclaration)
>       ConsumeToken();
> +
> +    AttrsLastTime = false;
>   }
> }
> 
> @@ -2941,6 +2964,15 @@
>     return cutOffParsing();
>   }
> 
> +  // If attributes exist after tag, parse them.
> +  ParsedAttributesWithRange attrs(AttrFactory);
> +  MaybeParseGNUAttributes(attrs);
> +  MaybeParseCXX0XAttributes(attrs);
> +
> +  // If declspecs exist after tag, parse them.
> +  while (Tok.is(tok::kw___declspec))
> +    ParseMicrosoftDeclSpec(attrs);
> +
>   SourceLocation ScopedEnumKWLoc;
>   bool IsScopedUsingClassTag = false;
> 
> @@ -2949,6 +2981,10 @@
>     Diag(Tok, diag::warn_cxx98_compat_scoped_enum);
>     IsScopedUsingClassTag = Tok.is(tok::kw_class);
>     ScopedEnumKWLoc = ConsumeToken();
> +    
> +    ProhibitAttributes(attrs);
> +    // Recovery: assume that the attributes came after the tag.
> +    MaybeParseCXX0XAttributes(attrs);
>   }
> 
>   // C++11 [temp.explicit]p12:
> @@ -2962,14 +2998,6 @@
>      TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
>   SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
> 
> -  // If attributes exist after tag, parse them.
> -  ParsedAttributes attrs(AttrFactory);
> -  MaybeParseGNUAttributes(attrs);
> -
> -  // If declspecs exist after tag, parse them.
> -  while (Tok.is(tok::kw___declspec))
> -    ParseMicrosoftDeclSpec(attrs);
> -
>   // Enum definitions should not be parsed in a trailing-return-type.
>   bool AllowDeclaration = DSC != DSC_trailing;
> 
> @@ -3154,6 +3182,9 @@
>     TParams = MultiTemplateParamsArg(TemplateInfo.TemplateParams->data(),
>                                      TemplateInfo.TemplateParams->size());
>   }
> +  
> +  if (TUK == Sema::TUK_Reference)
> +    ProhibitAttributes(attrs);
> 
>   if (!Name && TUK != Sema::TUK_Definition) {
>     Diag(Tok, diag::err_enumerator_unnamed_no_def);
> @@ -3252,8 +3283,10 @@
>     SourceLocation IdentLoc = ConsumeToken();
> 
>     // If attributes exist after the enumerator, parse them.
> -    ParsedAttributes attrs(AttrFactory);
> +    ParsedAttributesWithRange attrs(AttrFactory);
>     MaybeParseGNUAttributes(attrs);
> +    MaybeParseCXX0XAttributes(attrs);
> +    ProhibitAttributes(attrs);
> 
>     SourceLocation EqualLoc;
>     ExprResult AssignedVal;
> 
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Jun 23 00:07:58 2012
> @@ -444,6 +444,13 @@
>   CXXScopeSpec SS;
>   SourceLocation TypenameLoc;
>   bool IsTypeName;
> +  ParsedAttributesWithRange attrs(AttrFactory);
> +
> +  // FIXME: Simply skip the attributes and diagnose, don't bother parsing them.
> +  MaybeParseCXX0XAttributes(attrs);
> +  ProhibitAttributes(attrs);
> +  attrs.clear();
> +  attrs.Range = SourceRange();
> 
>   // Ignore optional 'typename'.
>   // FIXME: This is wrong; we should parse this as a typename-specifier.
> @@ -480,7 +487,7 @@
>     return 0;
>   }
> 
> -  ParsedAttributes attrs(AttrFactory);
> +  MaybeParseCXX0XAttributes(attrs);
> 
>   // Maybe this is an alias-declaration.
>   bool IsAliasDecl = Tok.is(tok::equal);
> @@ -533,9 +540,14 @@
>     TypeAlias = ParseTypeName(0, TemplateInfo.Kind ?
>                               Declarator::AliasTemplateContext :
>                               Declarator::AliasDeclContext, AS, OwnedType);
> -  } else
> +  } else {
> +    // C++11 attributes are not allowed on a using-declaration, but GNU ones
> +    // are.
> +    ProhibitAttributes(attrs);
> +
>     // Parse (optional) attributes (most likely GNU strong-using extension).
>     MaybeParseGNUAttributes(attrs);
> +  }
> 
>   // Eat ';'.
>   DeclEnd = Tok.getLocation();
> @@ -572,6 +584,7 @@
>     MultiTemplateParamsArg TemplateParamsArg(Actions,
>       TemplateParams ? TemplateParams->data() : 0,
>       TemplateParams ? TemplateParams->size() : 0);
> +    // FIXME: Propagate attributes.
>     return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
>                                          UsingLoc, Name, TypeAlias);
>   }
> @@ -989,7 +1002,7 @@
>      TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
>   SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
> 
> -  ParsedAttributes attrs(AttrFactory);
> +  ParsedAttributesWithRange attrs(AttrFactory);
>   // If attributes exist after tag, parse them.
>   if (Tok.is(tok::kw___attribute))
>     ParseGNUAttributes(attrs);
> @@ -1202,6 +1215,8 @@
>     if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
>         TUK == Sema::TUK_Declaration) {
>       // This is an explicit instantiation of a class template.
> +      ProhibitAttributes(attrs);
> +
>       TagOrTempResult
>         = Actions.ActOnExplicitInstantiation(getCurScope(),
>                                              TemplateInfo.ExternLoc,
> @@ -1223,6 +1238,7 @@
>     } else if (TUK == Sema::TUK_Reference ||
>                (TUK == Sema::TUK_Friend &&
>                 TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
> +      ProhibitAttributes(attrs);
>       TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc,
>                                                   TemplateId->SS,
>                                                   TemplateId->TemplateKWLoc,
> @@ -1287,6 +1303,8 @@
>     //
>     //   template struct Outer<int>::Inner;
>     //
> +    ProhibitAttributes(attrs);
> +
>     TagOrTempResult
>       = Actions.ActOnExplicitInstantiation(getCurScope(),
>                                            TemplateInfo.ExternLoc,
> @@ -1295,6 +1313,8 @@
>                                            NameLoc, attrs.getList());
>   } else if (TUK == Sema::TUK_Friend &&
>              TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
> +    ProhibitAttributes(attrs);
> +
>     TagOrTempResult =
>       Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(),
>                                       TagType, StartLoc, SS,
> @@ -1308,6 +1328,9 @@
>       // FIXME: Diagnose this particular error.
>     }
> 
> +    if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
> +      ProhibitAttributes(attrs);
> +
>     bool IsDependent = false;
> 
>     // Don't pass down template parameter lists if this is just a tag
> @@ -2951,7 +2974,7 @@
>     SkipUntil(tok::r_square, false);
> }
> 
> -/// ParseCXX11Attributes - Parse a C++0x attribute-specifier-seq.
> +/// ParseCXX11Attributes - Parse a C++11 attribute-specifier-seq.
> ///
> /// attribute-specifier-seq:
> ///       attribute-specifier-seq[opt] attribute-specifier
> 
> Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Jun 23 00:07:58 2012
> @@ -1296,7 +1296,12 @@
>     return true;
>   }
> 
> +  ParsedAttributesWithRange attrs(AttrFactory);
> +  MaybeParseCXX0XAttributes(attrs);
> +
>   if (!isCXXConditionDeclaration()) {
> +    ProhibitAttributes(attrs);
> +
>     // Parse the expression.
>     ExprOut = ParseExpression(); // expression
>     DeclOut = 0;
> 
> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Sat Jun 23 00:07:58 2012
> @@ -420,7 +420,7 @@
>       // erroneous r_brace would cause an infinite loop if not handled here.
>       if (Tok.is(tok::r_brace))
>         break;
> -      ParsedAttributes attrs(AttrFactory);
> +      ParsedAttributesWithRange attrs(AttrFactory);
>       allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
>       continue;
>     }
> 
> Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseStmt.cpp Sat Jun 23 00:07:58 2012
> @@ -1259,6 +1259,12 @@
>   // Parse the parenthesized condition.
>   BalancedDelimiterTracker T(*this, tok::l_paren);
>   T.consumeOpen();
> +  
> +  // FIXME: Do not just parse the attribute contents and throw them away
> +  ParsedAttributesWithRange attrs(AttrFactory);
> +  MaybeParseCXX0XAttributes(attrs);
> +  ProhibitAttributes(attrs);
> +
>   ExprResult Cond = ParseExpression();
>   T.consumeClose();
>   DoScope.Exit();
> @@ -1347,8 +1353,12 @@
>     return StmtError();
>   }
> 
> +  ParsedAttributesWithRange attrs(AttrFactory);
> +  MaybeParseCXX0XAttributes(attrs);
> +
>   // Parse the first part of the for specifier.
>   if (Tok.is(tok::semi)) {  // for (;
> +    ProhibitAttributes(attrs);
>     // no first part, eat the ';'.
>     ConsumeToken();
>   } else if (isForInitDeclaration()) {  // for (int X = 4;
> @@ -1393,6 +1403,7 @@
>       Diag(Tok, diag::err_expected_semi_for);
>     }
>   } else {
> +    ProhibitAttributes(attrs);
>     Value = ParseExpression();
> 
>     ForEach = isTokIdentifier_in();
> 
> Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Sat Jun 23 00:07:58 2012
> @@ -219,7 +219,10 @@
>   ParsingDeclSpec DS(*this, &DiagsFromTParams);
> 
>   // Move the attributes from the prefix into the DS.
> -  DS.takeAttributesFrom(prefixAttrs);
> +  if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
> +    ProhibitAttributes(prefixAttrs);
> +  else
> +    DS.takeAttributesFrom(prefixAttrs);
> 
>   ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
>                              getDeclSpecContextFromDeclaratorContext(Context));
> 
> Modified: cfe/trunk/lib/Parse/Parser.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/Parser.cpp (original)
> +++ cfe/trunk/lib/Parse/Parser.cpp Sat Jun 23 00:07:58 2012
> @@ -746,8 +746,7 @@
>   dont_know:
>     // We can't tell whether this is a function-definition or declaration yet.
>     if (DS) {
> -      DS->takeAttributesFrom(attrs);
> -      return ParseDeclarationOrFunctionDefinition(*DS);
> +      return ParseDeclarationOrFunctionDefinition(attrs, DS);
>     } else {
>       return ParseDeclarationOrFunctionDefinition(attrs);
>     }
> @@ -815,20 +814,24 @@
> /// [OMP]   threadprivate-directive                              [TODO]
> ///
> Parser::DeclGroupPtrTy
> -Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
> -                                             AccessSpecifier AS) {
> +Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
> +                                       ParsingDeclSpec &DS,
> +                                       AccessSpecifier AS) {
>   // Parse the common declaration-specifiers piece.
>   ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
> 
>   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
>   // declaration-specifiers init-declarator-list[opt] ';'
>   if (Tok.is(tok::semi)) {
> +    ProhibitAttributes(attrs);
>     ConsumeToken();
>     Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
>     DS.complete(TheDecl);
>     return Actions.ConvertDeclToDeclGroup(TheDecl);
>   }
> 
> +  DS.takeAttributesFrom(attrs);
> +
>   // ObjC2 allows prefix attributes on class interfaces and protocols.
>   // FIXME: This still needs better diagnostics. We should only accept
>   // attributes here, no types, etc.
> @@ -869,16 +872,20 @@
> }
> 
> Parser::DeclGroupPtrTy
> -Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
> +Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs,
> +                                             ParsingDeclSpec *DS,
>                                              AccessSpecifier AS) {
> -  ParsingDeclSpec DS(*this);
> -  DS.takeAttributesFrom(attrs);
> -  // Must temporarily exit the objective-c container scope for
> -  // parsing c constructs and re-enter objc container scope
> -  // afterwards.
> -  ObjCDeclContextSwitch ObjCDC(*this);
> -    
> -  return ParseDeclarationOrFunctionDefinition(DS, AS);
> +  if (DS) {
> +    return ParseDeclOrFunctionDefInternal(attrs, *DS, AS);
> +  } else {
> +    ParsingDeclSpec PDS(*this);
> +    // Must temporarily exit the objective-c container scope for
> +    // parsing c constructs and re-enter objc container scope
> +    // afterwards.
> +    ObjCDeclContextSwitch ObjCDC(*this);
> +      
> +    return ParseDeclOrFunctionDefInternal(attrs, PDS, AS);
> +  }
> }
> 
> /// ParseFunctionDefinition - We parsed and verified that the specified
> 
> Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=159072&r1=159071&r2=159072&view=diff
> ==============================================================================
> --- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
> +++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Sat Jun 23 00:07:58 2012
> @@ -1,15 +1,50 @@
> // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
> 
> +// Need std::initializer_list
> +namespace std {
> +  typedef decltype(sizeof(int)) size_t;
> +
> +  // libc++'s implementation
> +  template <class _E>
> +  class initializer_list
> +  {
> +    const _E* __begin_;
> +    size_t    __size_;
> +
> +    initializer_list(const _E* __b, size_t __s)
> +      : __begin_(__b),
> +        __size_(__s)
> +    {}
> +
> +  public:
> +    typedef _E        value_type;
> +    typedef const _E& reference;
> +    typedef const _E& const_reference;
> +    typedef size_t    size_type;
> +
> +    typedef const _E* iterator;
> +    typedef const _E* const_iterator;
> +
> +    initializer_list() : __begin_(nullptr), __size_(0) {}
> +
> +    size_t    size()  const {return __size_;}
> +    const _E* begin() const {return __begin_;}
> +    const _E* end()   const {return __begin_ + __size_;}
> +  };
> +}
> +
> +
> // Declaration syntax checks
> [[]] int before_attr;
> int [[]] between_attr;
> +const [[]] int between_attr_2 = 0; // expected-error {{an attribute list cannot appear here}}
> int after_attr [[]];
> int * [[]] ptr_attr;
> int & [[]] ref_attr = after_attr;
> int && [[]] rref_attr = 0;
> int array_attr [1] [[]];
> alignas(8) int aligned_attr;
> -[[test::valid(for 42 [very] **** '+' symbols went on a trip; the end.)]]
> +[[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;
> @@ -19,7 +54,18 @@
> struct MemberFnOrder {
>   virtual void f() const volatile && noexcept [[]] final = 0;
> };
> +struct [[]] struct_attr;
> class [[]] class_attr {};
> +union [[]] union_attr;
> +[[]] struct with_init_declarators {} init_declarator;
> +[[]] struct no_init_declarators; // expected-error {{an attribute list cannot appear here}}
> +[[]];
> +struct ctordtor {
> +  [[]] ctordtor();
> +  [[]] ~ctordtor();
> +};
> +[[]] ctordtor::ctordtor() {}
> +[[]] ctordtor::~ctordtor() {}
> extern "C++" [[]] int extern_attr;
> template <typename T> [[]] void template_attr ();
> [[]] [[]] int [[]] [[]] multi_attr [[]] [[]];
> @@ -27,7 +73,8 @@
> int comma_attr [[,]];
> int scope_attr [[foo::]]; // expected-error {{expected identifier}}
> int (paren_attr) [[]]; // expected-error {{an attribute list cannot appear here}}
> -unsigned [[]] int attr_in_decl_spec; // expected-error {{expected unqualified-id}}
> +unsigned [[]] int attr_in_decl_spec; // expected-error {{an attribute list cannot appear here}}
> +unsigned [[]] int [[]] const double_decl_spec = 0; // expected-error 2{{an attribute list cannot appear here}}
> class foo {
>   void const_after_attr () [[]] const; // expected-error {{expected ';'}}
> };
> @@ -40,6 +87,52 @@
> [[]] using ns::i; // expected-error {{an attribute list cannot appear here}}
> [[]] using namespace ns;
> 
> +[[]] using T = int; // expected-error {{an attribute list cannot appear here}}
> +using T [[]] = int; // ok
> +template<typename T> using U [[]] = T;
> +using ns::i [[]]; // expected-error {{an attribute list cannot appear here}}
> +using [[]] ns::i; // expected-error {{an attribute list cannot appear here}}
> +
> +auto trailing() -> [[]] const int; // expected-error {{an attribute list cannot appear here}}
> +auto trailing() -> const [[]] int; // expected-error {{an attribute list cannot appear here}}
> +auto trailing() -> const int [[]];
> +auto trailing_2() -> struct struct_attr [[]];
> +
> +namespace N {
> +  struct S {};
> +};
> +template<typename> struct Template {};
> +
> +// FIXME: Improve this diagnostic
> +struct [[]] N::S s; // expected-error {{an attribute list cannot appear here}}
> +struct [[]] Template<int> t; // expected-error {{an attribute list cannot appear here}}
> +struct [[]] ::template Template<int> u; // expected-error {{an attribute list cannot appear here}}
> +template struct [[]] Template<char>; // expected-error {{an attribute list cannot appear here}}
> +template <> struct [[]] Template<void>;
> +
> +enum [[]] E1 {};
> +enum [[]] E2; // expected-error {{forbids forward references}}
> +enum [[]] E1;
> +enum [[]] E3 : int;
> +enum [[]] {
> +  k_123 [[]] = 123 // expected-error {{an attribute list cannot appear here}}
> +};
> +enum [[]] E1 e; // expected-error {{an attribute list cannot appear here}}
> +enum [[]] class E4 { }; // expected-error {{an attribute list cannot appear here}}
> +enum struct [[]] E5;
> +
> +struct S {
> +  friend int f [[]] (); // expected-FIXME{{an attribute list cannot appear here}}
> +  [[]] friend int g(); // expected-FIXME{{an attribute list cannot appear here}}
> +  [[]] friend int h() {
> +  }
> +  friend class [[]] C; // expected-error{{an attribute list cannot appear here}}
> +};
> +template<typename T> void tmpl(T) {}
> +template void tmpl [[]] (int); // expected-FIXME {{an attribute list cannot appear here}}
> +template [[]] void tmpl(char); // expected-error {{an attribute list cannot appear here}}
> +template void [[]] tmpl(short);
> +
> // Argument tests
> alignas int aligned_no_params; // expected-error {{expected '('}}
> alignas(i) int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}} expected-note {{read of non-const variable 'i'}}
> @@ -81,3 +174,36 @@
> template<typename...Ts> void variadic() {
>   void bar [[noreturn...]] (); // expected-error {{attribute 'noreturn' cannot be used as an attribute pack}}
> }
> +
> +// Expression tests
> +void bar () {
> +  [] () [[noreturn]] { return; } (); // expected-error {{should not return}}
> +  [] () [[noreturn]] { throw; } ();
> +  new int[42][[]][5][[]]{};
> +}
> +
> +// Condition tests
> +void baz () {
> +  if ([[]] bool b = true) {
> +    switch ([[]] int n { 42 }) {
> +    default:
> +      for ([[]] int n = 0; [[]] char b = n < 5; ++b) {
> +      }
> +    }
> +  }
> +  int x;
> +  // An attribute can be applied to an expression-statement, such as the first
> +  // statement in a for. But it can't be applied to a condition which is an
> +  // expression.
> +  for ([[]] x = 0; ; ) {} // expected-error {{an attribute list cannot appear here}}
> +  for (; [[]] x < 5; ) {} // expected-error {{an attribute list cannot appear here}}
> +  while ([[]] bool k { false }) {
> +  }
> +  while ([[]] true) { // expected-error {{an attribute list cannot appear here}}
> +  }
> +  do {
> +  } while ([[]] false); // expected-error {{an attribute list cannot appear here}}
> +
> +  for ([[]] int n : { 1, 2, 3 }) {
> +  }
> +}
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

-David





More information about the cfe-commits mailing list