[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