diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2011-06-05 12:23:16 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2011-06-05 12:23:16 +0000 |
commit | dbef1bb8a8118b7b73e184e08fccfe0eaf914dda (patch) | |
tree | 43c42e9a9d8a1e05b2405b5b753c4aae76a845c3 | |
parent | 262b62b8f4d9495ad411941b10cffe92317fc9b8 (diff) |
Parse C++0x generalized initializers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132662 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 1 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 27 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 49 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 38 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 60 | ||||
-rw-r--r-- | test/SemaCXX/generalized-initializers.cpp | 7 |
6 files changed, 128 insertions, 54 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index d6077a4535..efac2b7d77 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -108,6 +108,7 @@ def err_expected_ident_lparen : Error<"expected identifier or '('">; def err_expected_ident_lbrace : Error<"expected identifier or '{'">; def err_expected_lbrace : Error<"expected '{'">; def err_expected_lparen : Error<"expected '('">; +def err_expected_lparen_or_lbrace : Error<"expected '('or '{'">; def err_expected_rparen : Error<"expected ')'">; def err_expected_lsquare : Error<"expected '['">; def err_expected_rsquare : Error<"expected ']'">; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index eadd5464f2..ad3fcfe0d3 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -814,8 +814,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // analyzed. if (FRI && Tok.is(tok::colon)) { FRI->ColonLoc = ConsumeToken(); - // FIXME: handle braced-init-list here. - FRI->RangeExpr = ParseExpression(); + if (Tok.is(tok::l_brace)) + FRI->RangeExpr = ParseBraceInitializer(); + else + FRI->RangeExpr = ParseExpression(); Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); Actions.ActOnCXXForRangeDecl(ThisDecl); Actions.FinalizeDeclaration(ThisDecl); @@ -914,6 +916,7 @@ bool Parser::ParseAttributesAfterDeclarator(Declarator &D) { /// [C++] '(' expression-list ')' /// [C++0x] '=' 'default' [TODO] /// [C++0x] '=' 'delete' +/// [C++0x] braced-init-list /// /// According to the standard grammar, =default and =delete are function /// definitions, but that definitely doesn't fit with the parser here. @@ -1041,6 +1044,26 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, RParenLoc, TypeContainsAuto); } + } else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { + // Parse C++0x braced-init-list. + if (D.getCXXScopeSpec().isSet()) { + EnterScope(0); + Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl); + } + + ExprResult Init(ParseBraceInitializer()); + + if (D.getCXXScopeSpec().isSet()) { + Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl); + ExitScope(); + } + + if (Init.isInvalid()) { + Actions.ActOnInitializerError(ThisDecl); + } else + Actions.AddInitializerToDecl(ThisDecl, Init.take(), + /*DirectInit=*/true, TypeContainsAuto); + } else { Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto); } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index d9bb0aa2d3..dca7f903d2 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2157,6 +2157,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { /// /// [C++] mem-initializer: /// mem-initializer-id '(' expression-list[opt] ')' +/// [C++0x] mem-initializer-id braced-init-list /// /// [C++] mem-initializer-id: /// '::'[opt] nested-name-specifier[opt] class-name @@ -2187,31 +2188,37 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { SourceLocation IdLoc = ConsumeToken(); // Parse the '('. - if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen); + if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { + // FIXME: Do something with the braced-init-list. + ParseBraceInitializer(); return true; - } - SourceLocation LParenLoc = ConsumeParen(); + } else if(Tok.is(tok::l_paren)) { + SourceLocation LParenLoc = ConsumeParen(); - // Parse the optional expression-list. - ExprVector ArgExprs(Actions); - CommaLocsTy CommaLocs; - if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { - SkipUntil(tok::r_paren); - return true; - } + // Parse the optional expression-list. + ExprVector ArgExprs(Actions); + CommaLocsTy CommaLocs; + if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { + SkipUntil(tok::r_paren); + return true; + } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); - - return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, - TemplateTypeTy, IdLoc, - LParenLoc, ArgExprs.take(), - ArgExprs.size(), RParenLoc, - EllipsisLoc); + SourceLocation EllipsisLoc; + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); + + return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, + TemplateTypeTy, IdLoc, + LParenLoc, ArgExprs.take(), + ArgExprs.size(), RParenLoc, + EllipsisLoc); + } + + Diag(Tok, getLang().CPlusPlus0x ? diag::err_expected_lparen_or_lbrace + : diag::err_expected_lparen); + return true; } /// \brief Parse a C++ exception-specification if present (C++0x [except.spec]). diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 89422b97fc..4e94ed9323 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -480,7 +480,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [OBJC] '@encode' '(' type-name ')' /// [OBJC] objc-string-literal /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] +/// [C++0x] simple-type-specifier braced-init-list [C++ 5.2.3] /// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3] +/// [C++0x] typename-specifier braced-init-list [C++ 5.2.3] /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] @@ -923,15 +925,18 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (SavedKind == tok::kw_typename) { // postfix-expression: typename-specifier '(' expression-list[opt] ')' + // typename-specifier braced-init-list if (TryAnnotateTypeOrScopeToken()) return ExprError(); } // postfix-expression: simple-type-specifier '(' expression-list[opt] ')' + // simple-type-specifier braced-init-list // DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); - if (Tok.isNot(tok::l_paren)) + if (Tok.isNot(tok::l_paren) && + (!getLang().CPlusPlus0x || Tok.isNot(tok::l_brace))) return ExprError(Diag(Tok, diag::err_expected_lparen_after_type) << DS.getSourceRange()); @@ -1122,6 +1127,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// postfix-expression: [C99 6.5.2] /// primary-expression /// postfix-expression '[' expression ']' +/// postfix-expression '[' braced-init-list ']' /// postfix-expression '(' argument-expression-list[opt] ')' /// postfix-expression '.' identifier /// postfix-expression '->' identifier @@ -1177,7 +1183,11 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { return move(LHS); Loc = ConsumeBracket(); - ExprResult Idx(ParseExpression()); + ExprResult Idx; + if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) + Idx = ParseBraceInitializer(); + else + Idx = ParseExpression(); SourceLocation RLoc = Tok.getLocation(); @@ -2021,8 +2031,19 @@ ExprResult Parser::ParseGenericSelectionExpression() { /// argument-expression-list , assignment-expression /// /// [C++] expression-list: -/// [C++] assignment-expression ...[opt] -/// [C++] expression-list , assignment-expression ...[opt] +/// [C++] assignment-expression +/// [C++] expression-list , assignment-expression +/// +/// [C++0x] expression-list: +/// [C++0x] initializer-list +/// +/// [C++0x] initializer-list +/// [C++0x] initializer-clause ...[opt] +/// [C++0x] initializer-list , initializer-clause ...[opt] +/// +/// [C++0x] initializer-clause: +/// [C++0x] assignment-expression +/// [C++0x] braced-init-list /// bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, llvm::SmallVectorImpl<SourceLocation> &CommaLocs, @@ -2039,8 +2060,13 @@ bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); ConsumeCodeCompletionToken(); } - - ExprResult Expr(ParseAssignmentExpression()); + + ExprResult Expr; + if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) + Expr = ParseBraceInitializer(); + else + Expr = ParseAssignmentExpression(); + if (Tok.is(tok::ellipsis)) Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken()); if (Expr.isInvalid()) diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 0862af323e..eab7114284 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -809,42 +809,55 @@ ExprResult Parser::ParseCXXThis() { /// Can be interpreted either as function-style casting ("int(x)") /// or class type construction ("ClassType(x,y,z)") /// or creation of a value-initialized type ("int()"). +/// See [C++ 5.2.3]. /// /// postfix-expression: [C++ 5.2p1] -/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] -/// typename-specifier '(' expression-list[opt] ')' [TODO] +/// simple-type-specifier '(' expression-list[opt] ')' +/// [C++0x] simple-type-specifier braced-init-list +/// typename-specifier '(' expression-list[opt] ')' +/// [C++0x] typename-specifier braced-init-list /// ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); - assert(Tok.is(tok::l_paren) && "Expected '('!"); - GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); + assert((Tok.is(tok::l_paren) || + (getLang().CPlusPlus0x && Tok.is(tok::l_brace))) + && "Expected '(' or '{'!"); - SourceLocation LParenLoc = ConsumeParen(); + if (Tok.is(tok::l_brace)) { - ExprVector Exprs(Actions); - CommaLocsTy CommaLocs; + // FIXME: Convert to a proper type construct expression. + return ParseBraceInitializer(); - if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(Exprs, CommaLocs)) { - SkipUntil(tok::r_paren); - return ExprError(); + } else { + GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); + + SourceLocation LParenLoc = ConsumeParen(); + + ExprVector Exprs(Actions); + CommaLocsTy CommaLocs; + + if (Tok.isNot(tok::r_paren)) { + if (ParseExpressionList(Exprs, CommaLocs)) { + SkipUntil(tok::r_paren); + return ExprError(); + } } - } - // Match the ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + // Match the ')'. + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - // TypeRep could be null, if it references an invalid typedef. - if (!TypeRep) - return ExprError(); + // TypeRep could be null, if it references an invalid typedef. + if (!TypeRep) + return ExprError(); - assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& - "Unexpected number of commas!"); - return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs), - RParenLoc); + assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& + "Unexpected number of commas!"); + return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs), + RParenLoc); + } } /// ParseCXXCondition - if/switch/while condition expression. @@ -1727,7 +1740,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, /// /// new-initializer: /// '(' expression-list[opt] ')' -/// [C++0x] braced-init-list [TODO] +/// [C++0x] braced-init-list /// ExprResult Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { @@ -1816,6 +1829,9 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); return ExprError(); } + } else if (Tok.is(tok::l_brace)) { + // FIXME: Have to communicate the init-list to ActOnCXXNew. + ParseBraceInitializer(); } return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp index 2f13151a53..fc903f0016 100644 --- a/test/SemaCXX/generalized-initializers.cpp +++ b/test/SemaCXX/generalized-initializers.cpp @@ -45,8 +45,9 @@ namespace integral { { const int a = {}; static_assert(a == 0, ""); } { const int a{1}; static_assert(a == 1, ""); } { const int a = {1}; static_assert(a == 1, ""); } - { const int a{1, 2}; } // expected-error {{ too many initializers}} - { const int a = {1, 2}; } // expected-error {{ too many initializers}} + { const int a{1, 2}; } // expected-error {{excess elements}} + { const int a = {1, 2}; } // expected-error {{excess elements}} + { const short a{100000}; } // expected-error {{narrowing conversion}} { const short a = {100000}; } // expected-error {{narrowing conversion}} } @@ -158,7 +159,7 @@ namespace litb { struct B { template<typename ...T> - B(initializer_list<int>, T ...); + B(std::initializer_list<int>, T ...); }; // invalid (the first phase only considers init-list ctors) |