diff options
Diffstat (limited to 'clang/lib/Parse')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 72 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 54 |
2 files changed, 97 insertions, 29 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 8674485d5f8..5e6c51c1ee9 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -705,13 +705,21 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, ///[C90/C++]init-declarator-list ';' [TODO] /// [OMP] threadprivate-directive [TODO] /// +/// for-range-declaration: [C++0x 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 /// declaration. If it is true, it checks for and eats it. +/// +/// 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) { + bool RequireSemi, + ForRangeInit *FRI) { // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); DS.takeAttributesFrom(attrs); @@ -731,7 +739,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, return Actions.ConvertDeclToDeclGroup(TheDecl); } - return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd); + return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd, FRI); } /// ParseDeclGroup - Having concluded that this is either a function @@ -740,7 +748,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, - SourceLocation *DeclEnd) { + SourceLocation *DeclEnd, + ForRangeInit *FRI) { // Parse the first declarator. ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context)); ParseDeclarator(D); @@ -786,8 +795,24 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } } + if (ParseAttributesAfterDeclarator(D)) + return DeclGroupPtrTy(); + + // C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we + // must parse and analyze the for-range-initializer before the declaration is + // analyzed. + if (FRI && Tok.is(tok::colon)) { + FRI->ColonLoc = ConsumeToken(); + // FIXME: handle braced-init-list here. + FRI->RangeExpr = ParseExpression(); + Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); + Actions.ActOnCXXForRangeDecl(ThisDecl); + Actions.FinalizeDeclaration(ThisDecl); + return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, &ThisDecl, 1); + } + llvm::SmallVector<Decl *, 8> DeclsInGroup; - Decl *FirstDecl = ParseDeclarationAfterDeclarator(D); + Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D); D.complete(FirstDecl); if (FirstDecl) DeclsInGroup.push_back(FirstDecl); @@ -841,6 +866,26 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, DeclsInGroup.size()); } +/// Parse an optional simple-asm-expr and attributes, and attach them to a +/// declarator. Returns true on an error. +bool Parser::ParseAttributesAfterDeclarator(Declarator &D) { + // If a simple-asm-expr is present, parse it. + if (Tok.is(tok::kw_asm)) { + SourceLocation Loc; + ExprResult AsmLabel(ParseSimpleAsm(&Loc)); + if (AsmLabel.isInvalid()) { + SkipUntil(tok::semi, true, true); + return true; + } + + D.setAsmLabel(AsmLabel.release()); + D.SetRangeEnd(Loc); + } + + MaybeParseGNUAttributes(D); + return false; +} + /// \brief Parse 'declaration' after parsing 'declaration-specifiers /// declarator'. This method parses the remainder of the declaration /// (including any attributes or initializer, among other things) and @@ -864,21 +909,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, /// Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo) { - // If a simple-asm-expr is present, parse it. - if (Tok.is(tok::kw_asm)) { - SourceLocation Loc; - ExprResult AsmLabel(ParseSimpleAsm(&Loc)); - if (AsmLabel.isInvalid()) { - SkipUntil(tok::semi, true, true); - return 0; - } + if (ParseAttributesAfterDeclarator(D)) + return 0; - D.setAsmLabel(AsmLabel.release()); - D.SetRangeEnd(Loc); - } - - MaybeParseGNUAttributes(D); + return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo); +} +Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, + const ParsedTemplateInfo &TemplateInfo) { // Inform the current actions module that we just parsed this declarator. Decl *ThisDecl = 0; switch (TemplateInfo.Kind) { diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 8ffd6e921b2..d70a745314e 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -977,6 +977,7 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { /// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement /// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')' /// [C++] statement +/// [C++0x] 'for' '(' for-range-declaration : for-range-initializer ) statement /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement /// [OBJC2] 'for' '(' expr 'in' expr ')' statement /// @@ -984,6 +985,11 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { /// [C++] expression-statement /// [C++] simple-declaration /// +/// [C++0x] for-range-declaration: +/// [C++0x] attribute-specifier-seq[opt] type-specifier-seq declarator +/// [C++0x] for-range-initializer: +/// [C++0x] expression +/// [C++0x] braced-init-list [TODO] StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { // FIXME: Use attributes? @@ -1025,11 +1031,12 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { SourceLocation LParenLoc = ConsumeParen(); ExprResult Value; - bool ForEach = false; + bool ForEach = false, ForRange = false; StmtResult FirstPart; bool SecondPartIsInvalid = false; FullExprArg SecondPart(Actions); ExprResult Collection; + ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); Decl *SecondVar = 0; @@ -1052,13 +1059,21 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); + // In C++0x, "for (T NS:a" might not be a typo for :: + bool MightBeForRangeStmt = getLang().CPlusPlus; + ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); + SourceLocation DeclStart = Tok.getLocation(), DeclEnd; StmtVector Stmts(Actions); DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, - DeclEnd, attrs, false); + DeclEnd, attrs, false, + MightBeForRangeStmt ? + &ForRangeInit : 0); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - if (Tok.is(tok::semi)) { // for (int x = 4; + if (ForRangeInit.ParsedForRangeDecl()) { + ForRange = true; + } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); } else if ((ForEach = isTokIdentifier_in())) { Actions.ActOnForEachDeclStmt(DG); @@ -1107,7 +1122,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { } } } - if (!ForEach) { + if (!ForEach && !ForRange) { assert(!SecondPart.get() && "Shouldn't have a second expression yet."); // Parse the second part of the for specifier. if (Tok.is(tok::semi)) { // for (...;; @@ -1149,6 +1164,17 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { // Match the ')'. SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + // We need to perform most of the semantic analysis for a C++0x for-range + // statememt before parsing the body, in order to be able to deduce the type + // of an auto-typed loop variable. + StmtResult ForRangeStmt; + if (ForRange) + ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, LParenLoc, + FirstPart.take(), + ForRangeInit.ColonLoc, + ForRangeInit.RangeExpr.get(), + RParenLoc); + // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1175,15 +1201,19 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { if (Body.isInvalid()) return StmtError(); - if (!ForEach) - return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart, - SecondVar, ThirdPart, RParenLoc, Body.take()); + if (ForEach) + // FIXME: It isn't clear how to communicate the late destruction of + // C++ temporaries used to create the collection. + return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, + FirstPart.take(), + Collection.take(), RParenLoc, + Body.take()); + + if (ForRange) + return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); - // FIXME: It isn't clear how to communicate the late destruction of - // C++ temporaries used to create the collection. - return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, FirstPart.take(), - Collection.take(), RParenLoc, - Body.take()); + return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart, + SecondVar, ThirdPart, RParenLoc, Body.take()); } /// ParseGotoStatement |