ParseStmt.cpp revision d7f02df6e949aaf26706bea3ac79ed65ca792a30
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- ParseStmt.cpp - Statement and Block Parser -----------------------===// 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// The LLVM Compiler Infrastructure 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the Statement and Block portions of the Parser 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// interface. 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/Parser.h" 16d167ca0d26e43292b8b9e8d5300d92784ae0e27dChris Lattner#include "RAIIObjectsForParser.h" 1719510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/DeclSpec.h" 18f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall#include "clang/Sema/PrettyDeclStackTrace.h" 1919510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/Scope.h" 20ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/Diagnostic.h" 21ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/PrettyStackTrace.h" 22ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/SourceManager.h" 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang; 245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// C99 6.8: Statements and Blocks. 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===// 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseStatementOrDeclaration - Read 'statement' or 'declaration'. 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// StatementOrDeclaration: 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// statement 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// declaration 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// statement: 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// labeled-statement 365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// compound-statement 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// expression-statement 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// selection-statement 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// iteration-statement 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// jump-statement 41dcdd55fb4d28de8c314d6c6c1a38aa6aba76d431Argyrios Kyrtzidis/// [C++] declaration-statement 42a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// [C++] try-block 4328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// [MS] seh-try-block 44b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC] objc-throw-statement 45b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC] objc-try-catch-statement 46c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian/// [OBC] objc-synchronized-statement 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-statement 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] openmp-construct [TODO] 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// labeled-statement: 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// identifier ':' statement 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'case' constant-expression ':' statement 535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'default' ':' statement 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// selection-statement: 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if-statement 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// switch-statement 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// iteration-statement: 605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// while-statement 615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// do-statement 625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for-statement 635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// expression-statement: 655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// expression[opt] ';' 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// jump-statement: 685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'goto' identifier ';' 695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'continue' ';' 705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'break' ';' 715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'return' expression[opt] ';' 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] 'goto' '*' expression ';' 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 74b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC] objc-throw-statement: 75b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC] '@' 'throw' expression ';' 761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// [OBC] '@' 'throw' ';' 771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// 7860d7b3a319d84d688752be3870615ac0f111fb16John McCallStmtResult 79c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz JahanianParser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { 805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *SemiError = 0; 8160d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Res; 8236d36806f1972f7ec1d2a3f59155187278c56508Argyrios Kyrtzidis 8336d36806f1972f7ec1d2a3f59155187278c56508Argyrios Kyrtzidis ParenBraceBracketBalancer BalancerRAIIObj(*this); 840e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 850b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall ParsedAttributesWithRange attrs(AttrFactory); 867f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall MaybeParseCXX0XAttributes(attrs); 87bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt 885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Cases in this switch statement should fall through if the parser expects 895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // the token to end in a semicolon (in which case SemiError should be set), 905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // or they directly 'return;' if not. 91312eadb832cab4497a069409954500d8192b8f0dDouglas GregorRetry: 92397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian tok::TokenKind Kind = Tok.getKind(); 93397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian SourceLocation AtLoc; 94397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian switch (Kind) { 95397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian case tok::at: // May be a @try or @throw statement 96397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian { 97397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian AtLoc = ConsumeToken(); // consume @ 9843bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl return ParseObjCAtStatement(AtLoc); 99397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian } 100397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian 101791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor case tok::code_completion: 102f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement); 103c8bddde82135ab25a36ff60fbd2ad50fabe42e63Douglas Gregor ConsumeCodeCompletionToken(); 104c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz Jahanian return ParseStatementOrDeclaration(Stmts, OnlyStatement); 105791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor 106312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case tok::identifier: { 107312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Token Next = NextToken(); 108312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement 109b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis // identifier ':' statement 1107f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseLabeledStatement(attrs); 111b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis } 112312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 1133b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor if (Next.isNot(tok::coloncolon)) { 114312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor CXXScopeSpec SS; 115312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor IdentifierInfo *Name = Tok.getIdentifierInfo(); 116312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor SourceLocation NameLoc = Tok.getLocation(); 117312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Sema::NameClassification Classification 118312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next); 119312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor switch (Classification.getKind()) { 120312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case Sema::NC_Keyword: 121312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // The identifier was corrected to a keyword. Update the token 122312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // to this keyword, and try again. 123312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (Name->getTokenID() != tok::identifier) { 124312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Tok.setIdentifierInfo(Name); 125312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Tok.setKind(Name->getTokenID()); 126312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor goto Retry; 127312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 128312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 129312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Fall through via the normal error path. 130312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // FIXME: This seems like it could only happen for context-sensitive 131312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // keywords. 132312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 133312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case Sema::NC_Error: 134312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Handle errors here by skipping up to the next semicolon or '}', and 135312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // eat the semicolon if that's what stopped us. 136312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); 137312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (Tok.is(tok::semi)) 138312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor ConsumeToken(); 139312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor return StmtError(); 140312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 141312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case Sema::NC_Unknown: 142312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Either we don't know anything about this identifier, or we know that 143312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // we're in a syntactic context we haven't handled yet. 144312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor break; 145312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 146d9d75e57dfa22366c0379c92beac1db82db34e9aDouglas Gregor case Sema::NC_Type: 1473b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor Tok.setKind(tok::annot_typename); 1483b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor setTypeAnnotation(Tok, Classification.getType()); 1493b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor Tok.setAnnotationEndLoc(NameLoc); 1503b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor PP.AnnotateCachedTokens(Tok); 151312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor break; 152312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 153312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case Sema::NC_Expression: 1545ecdd78408a1c6f4be506d94f776642570d27336Douglas Gregor Tok.setKind(tok::annot_primary_expr); 1555ecdd78408a1c6f4be506d94f776642570d27336Douglas Gregor setExprAnnotation(Tok, Classification.getExpression()); 1565ecdd78408a1c6f4be506d94f776642570d27336Douglas Gregor Tok.setAnnotationEndLoc(NameLoc); 1575ecdd78408a1c6f4be506d94f776642570d27336Douglas Gregor PP.AnnotateCachedTokens(Tok); 1585ecdd78408a1c6f4be506d94f776642570d27336Douglas Gregor break; 159312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 160312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case Sema::NC_TypeTemplate: 161312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case Sema::NC_FunctionTemplate: { 162312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor ConsumeToken(); // the identifier 163312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor UnqualifiedId Id; 164312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Id.setIdentifier(Name, NameLoc); 165312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (AnnotateTemplateIdToken( 166312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor TemplateTy::make(Classification.getTemplateName()), 167312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Classification.getTemplateNameKind(), 1683b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor SS, Id, SourceLocation(), 1693b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor /*AllowTypeAnnotation=*/false)) { 1703b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor // Handle errors here by skipping up to the next semicolon or '}', and 1713b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor // eat the semicolon if that's what stopped us. 1723b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); 1733b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor if (Tok.is(tok::semi)) 1743b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor ConsumeToken(); 1753b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor return StmtError(); 1763b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor } 1773b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor 1783b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor // If the next token is '::', jump right into parsing a 1793b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor // nested-name-specifier. We don't want to leave the template-id 1803b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor // hanging. 1813b887354b1b667c97d070ddc67b5354353c4c07bDouglas Gregor if (NextToken().is(tok::coloncolon) && TryAnnotateCXXScopeToken(false)){ 182312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Handle errors here by skipping up to the next semicolon or '}', and 183312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // eat the semicolon if that's what stopped us. 184312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); 185312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (Tok.is(tok::semi)) 186312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor ConsumeToken(); 187312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor return StmtError(); 188312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 189312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 190312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // We've annotated a template-id, so try again now. 191312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor goto Retry; 192312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 193312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 194312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor case Sema::NC_NestedNameSpecifier: 195312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // FIXME: Implement this! 196312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor break; 197312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 198312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 199312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 200312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Fall through 201312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 202312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 203f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner default: { 2045404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { 20597144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner SourceLocation DeclStart = Tok.getLocation(), DeclEnd; 2068113ecfa4e41e2c888b1794389dfe3bce6386493Ted Kremenek DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext, 2077f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall DeclEnd, attrs); 20897144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd); 209f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner } 210f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner 211f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner if (Tok.is(tok::r_brace)) { 2125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::err_expected_statement); 21361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return StmtError(); 2145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2165ecdd78408a1c6f4be506d94f776642570d27336Douglas Gregor return ParseExprStatement(attrs); 217f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner } 21861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_case: // C99 6.8.1: labeled-statement 2207f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseCaseStatement(attrs); 2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_default: // C99 6.8.1: labeled-statement 2227f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseDefaultStatement(attrs); 22361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::l_brace: // C99 6.8.2: compound-statement 2257f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseCompoundStatement(attrs); 22644aa1f397855f130e88e62ffc1029f7f83bb5d2eArgyrios Kyrtzidis case tok::semi: { // C99 6.8.3p3: expression[opt] ';' 227b7d98d35ea723624345f06e5895ddce2e0388ef0Argyrios Kyrtzidis SourceLocation LeadingEmptyMacroLoc; 228b7d98d35ea723624345f06e5895ddce2e0388ef0Argyrios Kyrtzidis if (Tok.hasLeadingEmptyMacro()) 229b7d98d35ea723624345f06e5895ddce2e0388ef0Argyrios Kyrtzidis LeadingEmptyMacroLoc = PP.getLastEmptyMacroInstantiationLoc(); 230b7d98d35ea723624345f06e5895ddce2e0388ef0Argyrios Kyrtzidis return Actions.ActOnNullStmt(ConsumeToken(), LeadingEmptyMacroLoc); 23144aa1f397855f130e88e62ffc1029f7f83bb5d2eArgyrios Kyrtzidis } 23261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_if: // C99 6.8.4.1: if-statement 2347f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseIfStatement(attrs); 2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_switch: // C99 6.8.4.2: switch-statement 2367f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseSwitchStatement(attrs); 23761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_while: // C99 6.8.5.1: while-statement 2397f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseWhileStatement(attrs); 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_do: // C99 6.8.5.2: do-statement 2417f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall Res = ParseDoStatement(attrs); 2426869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner SemiError = "do/while"; 2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_for: // C99 6.8.5.3: for-statement 2457f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseForStatement(attrs); 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_goto: // C99 6.8.6.1: goto-statement 2487f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall Res = ParseGotoStatement(attrs); 2496869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner SemiError = "goto"; 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_continue: // C99 6.8.6.2: continue-statement 2527f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall Res = ParseContinueStatement(attrs); 2536869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner SemiError = "continue"; 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_break: // C99 6.8.6.3: break-statement 2567f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall Res = ParseBreakStatement(attrs); 2576869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner SemiError = "break"; 2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case tok::kw_return: // C99 6.8.6.4: return-statement 2607f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall Res = ParseReturnStatement(attrs); 2616869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner SemiError = "return"; 2625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 26361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 264a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl case tok::kw_asm: { 2657f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall ProhibitAttributes(attrs); 266d62701bc5321049353017e9abf1963edd57646aaSteve Naroff bool msAsm = false; 267d62701bc5321049353017e9abf1963edd57646aaSteve Naroff Res = ParseAsmStatement(msAsm); 268bf8cafadb9d4e0d7a90fe78fc175efb80ae34d42Argyrios Kyrtzidis Res = Actions.ActOnFinishFullStmt(Res.get()); 26961364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl if (msAsm) return move(Res); 2706869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner SemiError = "asm"; 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 27361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 274a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl case tok::kw_try: // C++ 15: try-block 2757f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall return ParseCXXTryBlock(attrs); 27628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 27728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley case tok::kw___try: 27828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return ParseSEHTryBlock(attrs); 279a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl } 280a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 2815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If we reached this code, the statement must end in a semicolon. 2824e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.is(tok::semi)) { 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 2840e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl } else if (!Res.isInvalid()) { 2857b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner // If the result was valid, then we do want to diagnose this. Use 2867b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner // ExpectAndConsume to emit the diagnostic, even though we know it won't 2877b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner // succeed. 2887b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError); 289195044028b76133e2a1f245b094468fe07db7330Chris Lattner // Skip until we see a } or ;, but don't eat it. 290195044028b76133e2a1f245b094468fe07db7330Chris Lattner SkipUntil(tok::r_brace, true, true); 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return move(Res); 2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 296312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor/// \brief Parse an expression statement. 2975ecdd78408a1c6f4be506d94f776642570d27336Douglas GregorStmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { 298312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // If a case keyword is missing, this is where it should be inserted. 299312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Token OldToken = Tok; 300312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 301312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // FIXME: Use the attributes 302312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // expression[opt] ';' 3035ecdd78408a1c6f4be506d94f776642570d27336Douglas Gregor ExprResult Expr(ParseExpression()); 304312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (Expr.isInvalid()) { 305312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // If the expression is invalid, skip ahead to the next semicolon or '}'. 306312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Not doing this opens us up to the possibility of infinite loops if 307312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // ParseExpression does not consume any tokens. 308312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); 309312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (Tok.is(tok::semi)) 310312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor ConsumeToken(); 311312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor return StmtError(); 312312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 313312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 314312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() && 315312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Actions.CheckCaseExpression(Expr.get())) { 316312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // If a constant expression is followed by a colon inside a switch block, 317312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // suggest a missing case keyword. 318312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor Diag(OldToken, diag::err_expected_case_before_expression) 319312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor << FixItHint::CreateInsertion(OldToken.getLocation(), "case "); 320312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 321312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Recover parsing as a case statement. 322312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor return ParseCaseStatement(Attrs, /*MissingCase=*/true, Expr); 323312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor } 324312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 325312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor // Otherwise, eat the semicolon. 326312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); 327312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get())); 32828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley} 329312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 33028bbe4b8acc338476fe0825769b41fb32b423c72John WiegleyStmtResult Parser::ParseSEHTryBlock(ParsedAttributes & Attrs) { 33128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley assert(Tok.is(tok::kw___try) && "Expected '__try'"); 33228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley SourceLocation Loc = ConsumeToken(); 33328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return ParseSEHTryBlockCommon(Loc); 33428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley} 33528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 33628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// ParseSEHTryBlockCommon 33728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 33828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// seh-try-block: 33928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// '__try' compound-statement seh-handler 34028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 34128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// seh-handler: 34228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// seh-except-block 34328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// seh-finally-block 34428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 34528bbe4b8acc338476fe0825769b41fb32b423c72John WiegleyStmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { 34628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Tok.isNot(tok::l_brace)) 34728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return StmtError(Diag(Tok,diag::err_expected_lbrace)); 34828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 34928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley ParsedAttributesWithRange attrs(AttrFactory); 35028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley StmtResult TryBlock(ParseCompoundStatement(attrs)); 35128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(TryBlock.isInvalid()) 35228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return move(TryBlock); 35328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 35428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley StmtResult Handler; 35528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Tok.is(tok::kw___except)) { 35628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley SourceLocation Loc = ConsumeToken(); 35728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley Handler = ParseSEHExceptBlock(Loc); 35828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley } else if (Tok.is(tok::kw___finally)) { 35928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley SourceLocation Loc = ConsumeToken(); 36028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley Handler = ParseSEHFinallyBlock(Loc); 36128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley } else { 36228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return StmtError(Diag(Tok,diag::err_seh_expected_handler)); 36328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley } 36428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 36528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Handler.isInvalid()) 36628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return move(Handler); 36728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 36828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return Actions.ActOnSEHTryBlock(false /* IsCXXTry */, 36928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley TryLoc, 37028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley TryBlock.take(), 37128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley Handler.take()); 37228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley} 37328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 37428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// ParseSEHExceptBlock - Handle __except 37528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 37628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// seh-except-block: 37728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// '__except' '(' seh-filter-expression ')' compound-statement 37828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 37928bbe4b8acc338476fe0825769b41fb32b423c72John WiegleyStmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { 38028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley PoisonIdentifierRAIIObject raii(Ident__exception_code, false), 38128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley raii2(Ident___exception_code, false), 38228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley raii3(Ident_GetExceptionCode, false); 38328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 38428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen)) 38528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return StmtError(); 38628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 38728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope); 38828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 389d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet if (getLang().Borland) { 390d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet Ident__exception_info->setIsPoisoned(false); 391d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet Ident___exception_info->setIsPoisoned(false); 392d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet Ident_GetExceptionInfo->setIsPoisoned(false); 393d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet } 39428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley ExprResult FilterExpr(ParseExpression()); 395d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet 396d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet if (getLang().Borland) { 397d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet Ident__exception_info->setIsPoisoned(true); 398d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet Ident___exception_info->setIsPoisoned(true); 399d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet Ident_GetExceptionInfo->setIsPoisoned(true); 400d7f02df6e949aaf26706bea3ac79ed65ca792a30Francois Pichet } 40128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 40228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(FilterExpr.isInvalid()) 40328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return StmtError(); 40428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 40528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen)) 40628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return StmtError(); 40728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 40828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley ParsedAttributesWithRange attrs(AttrFactory); 40928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley StmtResult Block(ParseCompoundStatement(attrs)); 41028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 41128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Block.isInvalid()) 41228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return move(Block); 41328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 41428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.take(), Block.take()); 41528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley} 41628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 41728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// ParseSEHFinallyBlock - Handle __finally 41828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 41928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// seh-finally-block: 42028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// '__finally' compound-statement 42128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 42228bbe4b8acc338476fe0825769b41fb32b423c72John WiegleyStmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) { 42328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false), 42428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley raii2(Ident___abnormal_termination, false), 42528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley raii3(Ident_AbnormalTermination, false); 42628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 42728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley ParsedAttributesWithRange attrs(AttrFactory); 42828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley StmtResult Block(ParseCompoundStatement(attrs)); 42928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Block.isInvalid()) 43028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return move(Block); 43128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 43228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.take()); 433312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor} 434312eadb832cab4497a069409954500d8192b8f0dDouglas Gregor 435f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis/// ParseLabeledStatement - We have an identifier and a ':' after it. 4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 4375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// labeled-statement: 4385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// identifier ':' statement 4395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] identifier ':' attributes[opt] statement 4405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 4417f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) { 4424e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() && 4435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer "Not an identifier!"); 4445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 445d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner Token IdentTok = Tok; // Save the whole token. 4465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); // eat the identifier. 447f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis 448f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis assert(Tok.is(tok::colon) && "Not a label!"); 44961364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 4505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // identifier ':' statement 451f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis SourceLocation ColonLoc = ConsumeToken(); 4525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 453f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis // Read label attributes, if present. 4547f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall MaybeParseGNUAttributes(attrs); 4555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 45660d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult SubStmt(ParseStatement()); 4570e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 458f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis // Broken substmt shouldn't prevent the label from being added to the AST. 4590e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (SubStmt.isInvalid()) 460f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis SubStmt = Actions.ActOnNullStmt(ColonLoc); 461337e550218128e7d922c09bb354fbc71de90c568Chris Lattner 462337e550218128e7d922c09bb354fbc71de90c568Chris Lattner LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), 463337e550218128e7d922c09bb354fbc71de90c568Chris Lattner IdentTok.getLocation()); 464337e550218128e7d922c09bb354fbc71de90c568Chris Lattner if (AttributeList *Attrs = attrs.getList()) 465337e550218128e7d922c09bb354fbc71de90c568Chris Lattner Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); 466337e550218128e7d922c09bb354fbc71de90c568Chris Lattner 467337e550218128e7d922c09bb354fbc71de90c568Chris Lattner return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc, 468337e550218128e7d922c09bb354fbc71de90c568Chris Lattner SubStmt.get()); 469f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis} 4705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCaseStatement 4725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// labeled-statement: 4735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'case' constant-expression ':' statement 4745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] 'case' constant-expression '...' constant-expression ':' statement 4755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 476bb9b80c308d7d3f758886243c7145404a50c66cfRichard TrieuStmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, 477bb9b80c308d7d3f758886243c7145404a50c66cfRichard Trieu ExprResult Expr) { 47846f1110b324583622521a01d2c8f949e1f215bd2Richard Smith assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!"); 479bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 4801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 48124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // It is very very common for code to contain many case statements recursively 48224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // nested, as in (but usually without indentation): 48324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // case 1: 48424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // case 2: 48524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // case 3: 48624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // case 4: 48724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // case 5: etc. 48824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // 48924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Parsing this naively works, but is both inefficient and can cause us to run 49024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // out of stack space in our recursive descent parser. As a special case, 49126140c6399d4b14a224d44cf0102a1919d8dab04Chris Lattner // flatten this recursion into an iterative loop. This is complex and gross, 49224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // but all the grossness is constrained to ParseCaseStatement (and some 49324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // wierdness in the actions), so this is just local grossness :). 4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 49524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // TopLevelCase - This is the highest level we have parsed. 'case 1' in the 49624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // example above. 49760d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult TopLevelCase(true); 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 49924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which 50024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // gets updated each time a new case is parsed, and whose body is unset so 50124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // far. When parsing 'case 4', this is the 'case 3' node. 50224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner StmtTy *DeepestParsedCaseStmt = 0; 5031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 50424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // While we have case statements, eat and stack them. 50524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner do { 506bb9b80c308d7d3f758886243c7145404a50c66cfRichard Trieu SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() : 507bb9b80c308d7d3f758886243c7145404a50c66cfRichard Trieu ConsumeToken(); // eat the 'case'. 5081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5093e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor if (Tok.is(tok::code_completion)) { 51023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.CodeCompleteCase(getCurScope()); 511dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor ConsumeCodeCompletionToken(); 5123e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor } 5133e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor 5146fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'. 5156fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner /// Disable this form of error recovery while we're parsing the case 5166fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner /// expression. 5176fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner ColonProtectionRAIIObject ColonProtection(*this); 5186fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner 519bb9b80c308d7d3f758886243c7145404a50c66cfRichard Trieu ExprResult LHS(MissingCase ? Expr : ParseConstantExpression()); 520bb9b80c308d7d3f758886243c7145404a50c66cfRichard Trieu MissingCase = false; 52124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner if (LHS.isInvalid()) { 52224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner SkipUntil(tok::colon); 52324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner return StmtError(); 52424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner } 5255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 52624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // GNU case range extension. 52724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner SourceLocation DotDotDotLoc; 52860d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult RHS; 52924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner if (Tok.is(tok::ellipsis)) { 53024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner Diag(Tok, diag::ext_gnu_case_range); 53124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner DotDotDotLoc = ConsumeToken(); 5320e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 53324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner RHS = ParseConstantExpression(); 53424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner if (RHS.isInvalid()) { 53524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner SkipUntil(tok::colon); 53624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner return StmtError(); 53724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner } 53824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner } 5396fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner 5406fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner ColonProtection.restore(); 5410e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 542662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor SourceLocation ColonLoc; 543f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall if (Tok.is(tok::colon)) { 544f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall ColonLoc = ConsumeToken(); 545f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall 546f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall // Treat "case blah;" as a typo for "case blah:". 547f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall } else if (Tok.is(tok::semi)) { 548f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall ColonLoc = ConsumeToken(); 549f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall Diag(ColonLoc, diag::err_expected_colon_after) << "'case'" 550f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall << FixItHint::CreateReplacement(ColonLoc, ":"); 551f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall } else { 552662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation); 553662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'" 554662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor << FixItHint::CreateInsertion(ExpectedLoc, ":"); 555662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor ColonLoc = ExpectedLoc; 5565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 557662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor 55860d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Case = 5599ae2f076ca5ab1feb3ba95629099ec2319833701John McCall Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc, 5609ae2f076ca5ab1feb3ba95629099ec2319833701John McCall RHS.get(), ColonLoc); 5611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 56224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // If we had a sema error parsing this case, then just ignore it and 56324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // continue parsing the sub-stmt. 56424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner if (Case.isInvalid()) { 56524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner if (TopLevelCase.isInvalid()) // No parsed case stmts. 56624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner return ParseStatement(); 56724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Otherwise, just don't add it as a nested case. 56824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner } else { 56924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // If this is the first case statement we parsed, it becomes TopLevelCase. 57024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Otherwise we link it into the current chain. 571ca0408fb49c1370430672acf2d770b7151cf71deJohn McCall Stmt *NextDeepest = Case.get(); 57224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner if (TopLevelCase.isInvalid()) 57324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner TopLevelCase = move(Case); 57424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner else 5759ae2f076ca5ab1feb3ba95629099ec2319833701John McCall Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get()); 57624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner DeepestParsedCaseStmt = NextDeepest; 57724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner } 5781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Handle all case statements. 58024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner } while (Tok.is(tok::kw_case)); 5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!"); 5831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // If we found a non-case statement, start by parsing it. 58560d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult SubStmt; 5861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner if (Tok.isNot(tok::r_brace)) { 58824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner SubStmt = ParseStatement(); 58924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner } else { 59024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Nicely diagnose the common error "switch (X) { case 4: }", which is 59124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // not valid. 59224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // FIXME: add insertion hint. 5935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::err_label_end_of_compound_statement); 59424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner SubStmt = true; 5955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 5961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Broken sub-stmt shouldn't prevent forming the case statement properly. 5980e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (SubStmt.isInvalid()) 59924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner SubStmt = Actions.ActOnNullStmt(SourceLocation()); 6001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Install the body into the most deeply-nested case. 6029ae2f076ca5ab1feb3ba95629099ec2319833701John McCall Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); 60361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 60424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner // Return the top level parsed statement tree. 60526140c6399d4b14a224d44cf0102a1919d8dab04Chris Lattner return move(TopLevelCase); 6065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 6075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 6085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDefaultStatement 6095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// labeled-statement: 6105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'default' ':' statement 6115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note that this does not parse the 'statement' at the end. 6125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6137f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) { 614bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt //FIXME: Use attributes? 6151e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 6164e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_default) && "Not a default stmt!"); 6175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'. 6185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 619662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor SourceLocation ColonLoc; 620f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall if (Tok.is(tok::colon)) { 621f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall ColonLoc = ConsumeToken(); 622f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall 623f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall // Treat "default;" as a typo for "default:". 624f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall } else if (Tok.is(tok::semi)) { 625f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall ColonLoc = ConsumeToken(); 626f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall Diag(ColonLoc, diag::err_expected_colon_after) << "'default'" 627f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall << FixItHint::CreateReplacement(ColonLoc, ":"); 628f6a3ab0f167f23d0669eae77280c7ff660e7ad98John McCall } else { 629662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation); 630662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'" 631662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor << FixItHint::CreateInsertion(ExpectedLoc, ":"); 632662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor ColonLoc = ExpectedLoc; 6335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 634662a4822ee7c8696434b054303c5076a606ab175Douglas Gregor 6355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Diagnose the common error "switch (X) {... default: }", which is not valid. 6364e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.is(tok::r_brace)) { 6375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::err_label_end_of_compound_statement); 63861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return StmtError(); 6395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 6405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 64160d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult SubStmt(ParseStatement()); 6420e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (SubStmt.isInvalid()) 64361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return StmtError(); 64461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 645117054a99f4994e4ec8a1fc904b554e1f2dc9b29Sebastian Redl return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc, 6469ae2f076ca5ab1feb3ba95629099ec2319833701John McCall SubStmt.get(), getCurScope()); 6475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 6485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 6495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 6505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatement - Parse a "{}" block. 6515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// compound-statement: [C99 6.8.2] 6535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// { block-item-list[opt] } 6545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] { label-declarations block-item-list } [TODO] 6555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// block-item-list: 6575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// block-item 6585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// block-item-list block-item 6595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// block-item: 6615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// declaration 66245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner/// [GNU] '__extension__' declaration 6635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// statement 6645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] openmp-directive [TODO] 6655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declarations: 6675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declaration 6685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declarations label-declaration 6695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declaration: 6715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] '__label__' identifier-list ';' 6725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] openmp-directive: [TODO] 6745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] barrier-directive 6755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] flush-directive 6765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 6777f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs, 678bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt bool isStmtExpr) { 679bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt //FIXME: Use attributes? 6801e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 6814e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); 68261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 68331e057270232c1c37602579cb6461c2704175672Chris Lattner // Enter a scope to hold everything within the compound stmt. Compound 68431e057270232c1c37602579cb6461c2704175672Chris Lattner // statements can always hold declarations. 6858935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope CompoundScope(this, Scope::DeclScope); 6865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 6875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse the statements in the body. 68861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return ParseCompoundStatementBody(isStmtExpr); 6895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 6905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 6915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 6925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the 6931b273c403734d343d720acb28f04011807c8aa56Steve Naroff/// ActOnCompoundStmt action. This expects the '{' to be the current token, and 6945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// consume the '}' at the end of the block. It does not manipulate the scope 6955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// stack. 69660d7b3a319d84d688752be3870615ac0f111fb16John McCallStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { 6971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), 698ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner Tok.getLocation(), 699ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner "in compound statement ('{}')"); 7000fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor InMessageExpressionRAIIObject InMessage(*this, false); 7010fbda68b50ce17d7ad36ef7a5ed77518a5cd272eDouglas Gregor 7025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'. 7035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 704c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz Jahanian StmtVector Stmts(Actions); 705b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis 7064ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner // "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are 7074ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner // only allowed at the start of a compound stmt regardless of the language. 7084ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner while (Tok.is(tok::kw___label__)) { 7094ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner SourceLocation LabelLoc = ConsumeToken(); 7104ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner Diag(LabelLoc, diag::ext_gnu_local_label); 7114ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner 7124ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner llvm::SmallVector<Decl *, 8> DeclsInGroup; 7134ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner while (1) { 7144ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner if (Tok.isNot(tok::identifier)) { 7154ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner Diag(Tok, diag::err_expected_ident); 7164ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner break; 7174ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner } 7184ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner 7194ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner IdentifierInfo *II = Tok.getIdentifierInfo(); 7204ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner SourceLocation IdLoc = ConsumeToken(); 7216784304db526cde59046d613c4175ce2caf93e44Abramo Bagnara DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc)); 7224ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner 7234ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner if (!Tok.is(tok::comma)) 7244ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner break; 7254ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner ConsumeToken(); 7264ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner } 7274ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner 7280b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall DeclSpec DS(AttrFactory); 7294ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner DeclGroupPtrTy Res = Actions.FinalizeDeclaratorGroup(getCurScope(), DS, 7304ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner DeclsInGroup.data(), DeclsInGroup.size()); 7314ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation()); 7324ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner 7334ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); 7344ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner if (R.isUsable()) 7354ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner Stmts.push_back(R.release()); 7364ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner } 7374ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner 7384ae493cccbfbf122ec6ebac0e330232c22fa8489Chris Lattner while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { 739b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis if (Tok.is(tok::annot_pragma_unused)) { 740b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis HandlePragmaUnused(); 741b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis continue; 742b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis } 743b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis 74460d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult R; 7454e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::kw___extension__)) { 746c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz Jahanian R = ParseStatementOrDeclaration(Stmts, false); 74745a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner } else { 74845a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner // __extension__ can start declarations and it can also be a unary 74945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner // operator for expressions. Consume multiple __extension__ markers here 75045a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner // until we can determine which is which. 751adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman // FIXME: This loses extension expressions in the AST! 75245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner SourceLocation ExtLoc = ConsumeToken(); 7534e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner while (Tok.is(tok::kw___extension__)) 75445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner ConsumeToken(); 75539146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner 7560b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall ParsedAttributesWithRange attrs(AttrFactory); 7577f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall MaybeParseCXX0XAttributes(attrs); 758bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt 75945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner // If this is the start of a declaration, parse it as such. 7605404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis if (isDeclarationStatement()) { 761bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman // __extension__ silences extension warnings in the subdeclaration. 76297144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner // FIXME: Save the __extension__ on the decl as a node somehow? 763bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman ExtensionRAIIObject O(Diags); 764bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman 76597144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner SourceLocation DeclStart = Tok.getLocation(), DeclEnd; 766c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz Jahanian DeclGroupPtrTy Res = ParseDeclaration(Stmts, 767c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz Jahanian Declarator::BlockContext, DeclEnd, 7687f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall attrs); 76997144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd); 77045a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner } else { 771adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman // Otherwise this was a unary __extension__ marker. 77260d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc)); 773043a0b50a2a7a29c78a1ffb774f6fca8baf464a0Chris Lattner 7740e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (Res.isInvalid()) { 77545a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner SkipUntil(tok::semi); 77645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner continue; 77745a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner } 778f512e82f56671b695a32d019103e62a302838b7eSebastian Redl 779bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 78039146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner // Eat the semicolon at the end of stmt and convert the expr into a 78139146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner // statement. 7829ba23b4ceacd77cd264501690a7a9e94184ef71bDouglas Gregor ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); 7839ae2f076ca5ab1feb3ba95629099ec2319833701John McCall R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res.get())); 78445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner } 78545a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner } 78661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 7870e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (R.isUsable()) 788effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl Stmts.push_back(R.release()); 7895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 79061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 7915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // We broke out of the while loop because we found a '}' or EOF. 7924e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::r_brace)) { 7935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::err_expected_rbrace); 794f65086b479778d7090622bfb6cd9646c541a097eChris Lattner Diag(LBraceLoc, diag::note_matching) << "{"; 79561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return StmtError(); 7965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 79761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 7985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation RBraceLoc = ConsumeBrace(); 799f512e82f56671b695a32d019103e62a302838b7eSebastian Redl return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts), 800a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl isStmtExpr); 8015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 8025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 80315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// ParseParenExprOrCondition: 80415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// [C ] '(' expression ')' 805ff871fb8f9c5906a4dee78afd81f60c3837e16cbChris Lattner/// [C++] '(' condition ')' [not allowed if OnlyAllowCondition=true] 80615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// 80715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// This function parses and performs error recovery on the specified condition 80815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// or expression (depending on whether we're in C++ or C mode). This function 80915ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// goes out of its way to recover well. It returns true if there was a parser 81015ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// error (the right paren couldn't be found), which indicates that the caller 81115ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// should try to recover harder. It returns false if the condition is 81215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// successfully parsed. Note that a successful parse can still have semantic 81315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// errors in the condition. 81460d7b3a319d84d688752be3870615ac0f111fb16John McCallbool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, 815d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *&DeclResult, 816586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor SourceLocation Loc, 81744aa1f397855f130e88e62ffc1029f7f83bb5d2eArgyrios Kyrtzidis bool ConvertToBoolean) { 81815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner SourceLocation LParenLoc = ConsumeParen(); 81999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor if (getLang().CPlusPlus) 820dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); 82199e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor else { 82299e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor ExprResult = ParseExpression(); 823d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall DeclResult = 0; 824586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor 825586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor // If required, convert to a boolean value. 826586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor if (!ExprResult.isInvalid() && ConvertToBoolean) 827586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor ExprResult 8289ae2f076ca5ab1feb3ba95629099ec2319833701John McCall = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get()); 82999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor } 8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 83115ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner // If the parser was confused by the condition and we don't have a ')', try to 83215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner // recover by skipping ahead to a semi and bailing out. If condexp is 83315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner // semantically invalid but we have well formed code, keep going. 834d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall if (ExprResult.isInvalid() && !DeclResult && Tok.isNot(tok::r_paren)) { 83515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner SkipUntil(tok::semi); 83615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner // Skipping may have stopped if it found the containing ')'. If so, we can 83715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner // continue parsing the if statement. 83815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner if (Tok.isNot(tok::r_paren)) 83915ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner return true; 84015ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner } 8411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 84215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner // Otherwise the condition is valid or the rparen is present. 84399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor MatchRHSPunctuation(tok::r_paren, LParenLoc); 84415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner return false; 84515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner} 84615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner 84715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner 8485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseIfStatement 8495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// if-statement: [C99 6.8.4.1] 8505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'if' '(' expression ')' statement 8515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'if' '(' expression ')' statement 'else' statement 85271b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] 'if' '(' condition ')' statement 85371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] 'if' '(' condition ')' statement 'else' statement 8545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 8557f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { 856bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 8571e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 8584e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_if) && "Not an if stmt!"); 8595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation IfLoc = ConsumeToken(); // eat the 'if'. 8605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 8614e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::l_paren)) { 8621ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Tok, diag::err_expected_lparen_after) << "if"; 8635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::semi); 86461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return StmtError(); 8655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 86671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis 867488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis bool C99orCXX = getLang().C99 || getLang().CPlusPlus; 868488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis 8692215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // C99 6.8.4p3 - In C99, the if statement is a block. This is not 8702215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // the case for C90. 871488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 872488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.4p3: 873488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // A name introduced by a declaration in a condition is in scope from its 874488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // point of declaration until the end of the substatements controlled by the 875488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // condition. 87614d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // C++ 3.3.2p4: 87714d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // Names declared in the for-init-statement, and in the condition of if, 87814d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // while, for, and switch statements are local to the if, while, for, or 87914d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // switch statement (including the controlled statement). 880488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 8818935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); 8822215325a5696fb3b23551239b900559bb3018ee9Chris Lattner 8835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse the condition. 88460d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult CondExp; 885d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *CondVar = 0; 88644aa1f397855f130e88e62ffc1029f7f83bb5d2eArgyrios Kyrtzidis if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) 88715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner return StmtError(); 88818914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner 8899ae2f076ca5ab1feb3ba95629099ec2319833701John McCall FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get())); 8901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8910ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if 89238484403c8356fb41540ace6c74f28867f28febaChris Lattner // there is no compound stmt. C90 does not have this clause. We only do this 89338484403c8356fb41540ace6c74f28867f28febaChris Lattner // if the body isn't a compound statement to avoid push/pop in common cases. 894488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 895488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.4p1: 896488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // The substatement in a selection-statement (each substatement, in the else 897488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // form of the if statement) implicitly defines a local scope. 898488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 899488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // For C++ we create a scope for the condition and a new scope for 900488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // substatements because: 901488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // -When the 'then' scope exits, we want the condition declaration to still be 902488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // active for the 'else' scope too. 903488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // -Sema will detect name clashes by considering declarations of a 904488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 'ControlScope' as part of its direct subscope. 905488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // -If we wanted the condition and substatement to be in the same scope, we 906488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // would have to notify ParseStatement not to create a new scope. It's 907488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // simpler to let it create a new scope. 908488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 9091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParseScope InnerScope(this, Scope::DeclScope, 9108935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor C99orCXX && Tok.isNot(tok::l_brace)); 91171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis 912b96728d90abc35a520798066d2a75ca36400a617Chris Lattner // Read the 'then' stmt. 913b96728d90abc35a520798066d2a75ca36400a617Chris Lattner SourceLocation ThenStmtLoc = Tok.getLocation(); 91460d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult ThenStmt(ParseStatement()); 9155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 916a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner // Pop the 'if' scope if needed. 9178935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor InnerScope.Exit(); 91861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 9195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If it has an else, parse it. 9205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation ElseLoc; 921b96728d90abc35a520798066d2a75ca36400a617Chris Lattner SourceLocation ElseStmtLoc; 92260d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult ElseStmt; 9230e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 9244e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.is(tok::kw_else)) { 9255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ElseLoc = ConsumeToken(); 926966c78b79004061c1f64feff96818b9f1d68ea58Chris Lattner ElseStmtLoc = Tok.getLocation(); 92761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 9280ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if 92938484403c8356fb41540ace6c74f28867f28febaChris Lattner // there is no compound stmt. C90 does not have this clause. We only do 93038484403c8356fb41540ace6c74f28867f28febaChris Lattner // this if the body isn't a compound statement to avoid push/pop in common 93138484403c8356fb41540ace6c74f28867f28febaChris Lattner // cases. 932488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 933488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.4p1: 934488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // The substatement in a selection-statement (each substatement, in the else 935488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // form of the if statement) implicitly defines a local scope. 936488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 93761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl ParseScope InnerScope(this, Scope::DeclScope, 9388935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor C99orCXX && Tok.isNot(tok::l_brace)); 9390e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 9405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ElseStmt = ParseStatement(); 941966c78b79004061c1f64feff96818b9f1d68ea58Chris Lattner 942a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner // Pop the 'else' scope if needed. 9438935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor InnerScope.Exit(); 9445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 94561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 9468935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor IfScope.Exit(); 9471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 94818914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner // If the condition was invalid, discard the if statement. We could recover 94918914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner // better by replacing it with a valid expr, but don't do that yet. 950d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall if (CondExp.isInvalid() && !CondVar) 95118914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner return StmtError(); 9522215325a5696fb3b23551239b900559bb3018ee9Chris Lattner 953b96728d90abc35a520798066d2a75ca36400a617Chris Lattner // If the then or else stmt is invalid and the other is valid (and present), 9541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // make turn the invalid one into a null stmt to avoid dropping the other 955b96728d90abc35a520798066d2a75ca36400a617Chris Lattner // part. If both are invalid, return error. 9560e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) || 9570e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl (ThenStmt.isInvalid() && ElseStmt.get() == 0) || 9580e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl (ThenStmt.get() == 0 && ElseStmt.isInvalid())) { 959a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl // Both invalid, or one is invalid and other is non-present: return error. 96061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl return StmtError(); 961b96728d90abc35a520798066d2a75ca36400a617Chris Lattner } 9620e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 963b96728d90abc35a520798066d2a75ca36400a617Chris Lattner // Now if either are invalid, replace with a ';'. 9640e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (ThenStmt.isInvalid()) 965b96728d90abc35a520798066d2a75ca36400a617Chris Lattner ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc); 9660e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (ElseStmt.isInvalid()) 967b96728d90abc35a520798066d2a75ca36400a617Chris Lattner ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc); 9680e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 9699ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(), 97044aa1f397855f130e88e62ffc1029f7f83bb5d2eArgyrios Kyrtzidis ElseLoc, ElseStmt.get()); 9715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 9725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 9735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseSwitchStatement 9745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// switch-statement: 9755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'switch' '(' expression ')' statement 97671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] 'switch' '(' condition ')' statement 9777f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { 978bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 9791e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 9804e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_switch) && "Not a switch stmt!"); 9815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'. 9825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 9834e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::l_paren)) { 9841ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Tok, diag::err_expected_lparen_after) << "switch"; 9855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::semi); 9869a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 9875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 9882215325a5696fb3b23551239b900559bb3018ee9Chris Lattner 989488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis bool C99orCXX = getLang().C99 || getLang().CPlusPlus; 990488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis 9912215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // C99 6.8.4p3 - In C99, the switch statement is a block. This is 9922215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // not the case for C90. Start the switch scope. 993488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 994488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.4p3: 995488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // A name introduced by a declaration in a condition is in scope from its 996488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // point of declaration until the end of the substatements controlled by the 997488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // condition. 99814d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // C++ 3.3.2p4: 99914d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // Names declared in the for-init-statement, and in the condition of if, 100014d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // while, for, and switch statements are local to the if, while, for, or 100114d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // switch statement (including the controlled statement). 1002488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1003bb9b80c308d7d3f758886243c7145404a50c66cfRichard Trieu unsigned ScopeFlags = Scope::BreakScope | Scope::SwitchScope; 100415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner if (C99orCXX) 100515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner ScopeFlags |= Scope::DeclScope | Scope::ControlScope; 10068935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope SwitchScope(this, ScopeFlags); 10075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 10085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse the condition. 100960d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Cond; 1010d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *CondVar = 0; 1011586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false)) 10129a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 10132342ef75797a2ad6c9d7a784cfff220fd1a66008Eli Friedman 101460d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Switch 10159ae2f076ca5ab1feb3ba95629099ec2319833701John McCall = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar); 1016586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor 1017586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor if (Switch.isInvalid()) { 1018586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor // Skip the switch body. 1019586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor // FIXME: This is not optimal recovery, but parsing the body is more 1020586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor // dangerous due to the presence of case and default statements, which 1021586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor // will have no place to connect back with the switch. 10224186ff4fc4102f63b7485c2bf89155d3b0899d32Douglas Gregor if (Tok.is(tok::l_brace)) { 10234186ff4fc4102f63b7485c2bf89155d3b0899d32Douglas Gregor ConsumeBrace(); 10244186ff4fc4102f63b7485c2bf89155d3b0899d32Douglas Gregor SkipUntil(tok::r_brace, false, false); 10254186ff4fc4102f63b7485c2bf89155d3b0899d32Douglas Gregor } else 1026586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor SkipUntil(tok::semi); 1027586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor return move(Switch); 1028586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor } 102999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor 10300ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if 103138484403c8356fb41540ace6c74f28867f28febaChris Lattner // there is no compound stmt. C90 does not have this clause. We only do this 103238484403c8356fb41540ace6c74f28867f28febaChris Lattner // if the body isn't a compound statement to avoid push/pop in common cases. 1033488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1034488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.4p1: 1035488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // The substatement in a selection-statement (each substatement, in the else 1036488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // form of the if statement) implicitly defines a local scope. 1037488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1038488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // See comments in ParseIfStatement for why we create a scope for the 1039488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // condition and a new scope for substatement in C++. 1040488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 10411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParseScope InnerScope(this, Scope::DeclScope, 10428935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor C99orCXX && Tok.isNot(tok::l_brace)); 104361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 10445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Read the body statement. 104560d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Body(ParseStatement()); 10465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 10477e52de4b45286d057b367bb1f9283a1e32d79252Chris Lattner // Pop the scopes. 10488935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor InnerScope.Exit(); 10498935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor SwitchScope.Exit(); 105061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 10517e52de4b45286d057b367bb1f9283a1e32d79252Chris Lattner if (Body.isInvalid()) 10527e52de4b45286d057b367bb1f9283a1e32d79252Chris Lattner // FIXME: Remove the case statement list from the Switch statement. 10537e52de4b45286d057b367bb1f9283a1e32d79252Chris Lattner Body = Actions.ActOnNullStmt(Tok.getLocation()); 10547e52de4b45286d057b367bb1f9283a1e32d79252Chris Lattner 10559ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get()); 10565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 10575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 10585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseWhileStatement 10595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// while-statement: [C99 6.8.5.1] 10605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'while' '(' expression ')' statement 106171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] 'while' '(' condition ')' statement 10627f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs) { 1063bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 10641e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 10654e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_while) && "Not a while stmt!"); 10665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation WhileLoc = Tok.getLocation(); 10675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); // eat the 'while'. 10689a920342707e384473b464528d2fd286e8c70353Sebastian Redl 10694e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::l_paren)) { 10701ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Tok, diag::err_expected_lparen_after) << "while"; 10715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::semi); 10729a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 10735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 10749a920342707e384473b464528d2fd286e8c70353Sebastian Redl 1075488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis bool C99orCXX = getLang().C99 || getLang().CPlusPlus; 1076488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis 10772215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // C99 6.8.5p5 - In C99, the while statement is a block. This is not 10782215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // the case for C90. Start the loop scope. 1079488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1080488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.4p3: 1081488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // A name introduced by a declaration in a condition is in scope from its 1082488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // point of declaration until the end of the substatements controlled by the 1083488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // condition. 108414d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // C++ 3.3.2p4: 108514d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // Names declared in the for-init-statement, and in the condition of if, 108614d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // while, for, and switch statements are local to the if, while, for, or 108714d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // switch statement (including the controlled statement). 1088488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 10898935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor unsigned ScopeFlags; 1090488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis if (C99orCXX) 10918935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ScopeFlags = Scope::BreakScope | Scope::ContinueScope | 10928935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor Scope::DeclScope | Scope::ControlScope; 10932215325a5696fb3b23551239b900559bb3018ee9Chris Lattner else 10948935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ScopeFlags = Scope::BreakScope | Scope::ContinueScope; 10958935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope WhileScope(this, ScopeFlags); 10965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 10975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse the condition. 109860d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Cond; 1099d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *CondVar = 0; 1100586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) 110115ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner return StmtError(); 11020e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 11039ae2f076ca5ab1feb3ba95629099ec2319833701John McCall FullExprArg FullCond(Actions.MakeFullExpr(Cond.get())); 11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11050ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if 110638484403c8356fb41540ace6c74f28867f28febaChris Lattner // there is no compound stmt. C90 does not have this clause. We only do this 110738484403c8356fb41540ace6c74f28867f28febaChris Lattner // if the body isn't a compound statement to avoid push/pop in common cases. 1108488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1109488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.5p2: 1110488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // The substatement in an iteration-statement implicitly defines a local scope 1111488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // which is entered and exited each time through the loop. 1112488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1113488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // See comments in ParseIfStatement for why we create a scope for the 1114488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // condition and a new scope for substatement in C++. 1115488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 11161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParseScope InnerScope(this, Scope::DeclScope, 11178935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor C99orCXX && Tok.isNot(tok::l_brace)); 11189a920342707e384473b464528d2fd286e8c70353Sebastian Redl 11195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Read the body statement. 112060d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Body(ParseStatement()); 11215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 11220ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // Pop the body scope if needed. 11238935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor InnerScope.Exit(); 11248935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor WhileScope.Exit(); 11259a920342707e384473b464528d2fd286e8c70353Sebastian Redl 1126d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall if ((Cond.isInvalid() && !CondVar) || Body.isInvalid()) 11279a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 11289a920342707e384473b464528d2fd286e8c70353Sebastian Redl 11299ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get()); 11305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 11315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 11325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDoStatement 11335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// do-statement: [C99 6.8.5.2] 11345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'do' statement 'while' '(' expression ')' ';' 11355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'. 11367f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { 1137bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 11381e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 11394e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_do) && "Not a do stmt!"); 11405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation DoLoc = ConsumeToken(); // eat the 'do'. 11419a920342707e384473b464528d2fd286e8c70353Sebastian Redl 11422215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // C99 6.8.5p5 - In C99, the do statement is a block. This is not 11432215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // the case for C90. Start the loop scope. 11448935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor unsigned ScopeFlags; 11452215325a5696fb3b23551239b900559bb3018ee9Chris Lattner if (getLang().C99) 11468935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope; 11472215325a5696fb3b23551239b900559bb3018ee9Chris Lattner else 11488935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ScopeFlags = Scope::BreakScope | Scope::ContinueScope; 11499a920342707e384473b464528d2fd286e8c70353Sebastian Redl 11508935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope DoScope(this, ScopeFlags); 11515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 11520ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if 115338484403c8356fb41540ace6c74f28867f28febaChris Lattner // there is no compound stmt. C90 does not have this clause. We only do this 115438484403c8356fb41540ace6c74f28867f28febaChris Lattner // if the body isn't a compound statement to avoid push/pop in common cases. 1155143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis // 1156143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis // C++ 6.5p2: 1157143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis // The substatement in an iteration-statement implicitly defines a local scope 1158143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis // which is entered and exited each time through the loop. 1159143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis // 11608935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope InnerScope(this, Scope::DeclScope, 11611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump (getLang().C99 || getLang().CPlusPlus) && 11628935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor Tok.isNot(tok::l_brace)); 11639a920342707e384473b464528d2fd286e8c70353Sebastian Redl 11645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Read the body statement. 116560d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Body(ParseStatement()); 11665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 11670ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // Pop the body scope if needed. 11688935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor InnerScope.Exit(); 11690ecea03077117c7ea54c88091a44c73cef67923cChris Lattner 11704e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::kw_while)) { 11710e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (!Body.isInvalid()) { 1172195044028b76133e2a1f245b094468fe07db7330Chris Lattner Diag(Tok, diag::err_expected_while); 117328eb7e992b9a266abb300da25b6d3c1557cec361Chris Lattner Diag(DoLoc, diag::note_matching) << "do"; 1174195044028b76133e2a1f245b094468fe07db7330Chris Lattner SkipUntil(tok::semi, false, true); 1175195044028b76133e2a1f245b094468fe07db7330Chris Lattner } 11769a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 11775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 11785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation WhileLoc = ConsumeToken(); 11799a920342707e384473b464528d2fd286e8c70353Sebastian Redl 11804e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::l_paren)) { 11811ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Tok, diag::err_expected_lparen_after) << "do/while"; 1182195044028b76133e2a1f245b094468fe07db7330Chris Lattner SkipUntil(tok::semi, false, true); 11839a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 11845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 11859a920342707e384473b464528d2fd286e8c70353Sebastian Redl 1186ff871fb8f9c5906a4dee78afd81f60c3837e16cbChris Lattner // Parse the parenthesized condition. 118704895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor SourceLocation LPLoc = ConsumeParen(); 118860d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Cond = ParseExpression(); 118904895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc); 11908935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor DoScope.Exit(); 11910e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 11929a920342707e384473b464528d2fd286e8c70353Sebastian Redl if (Cond.isInvalid() || Body.isInvalid()) 11939a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 11940e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 11959ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, LPLoc, 11969ae2f076ca5ab1feb3ba95629099ec2319833701John McCall Cond.get(), RPLoc); 11975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 11985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 11995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseForStatement 12005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for-statement: [C99 6.8.5.3] 12015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement 12025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement 120371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')' 120471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] statement 1205ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith/// [C++0x] 'for' '(' for-range-declaration : for-range-initializer ) statement 12063ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement 12073ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' expr 'in' expr ')' statement 120871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// 120971b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] for-init-statement: 121071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] expression-statement 121171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] simple-declaration 121271b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// 1213ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith/// [C++0x] for-range-declaration: 1214ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith/// [C++0x] attribute-specifier-seq[opt] type-specifier-seq declarator 1215ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith/// [C++0x] for-range-initializer: 1216ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith/// [C++0x] expression 1217ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith/// [C++0x] braced-init-list [TODO] 12187f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { 1219bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 12201e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 12214e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_for) && "Not a for stmt!"); 12225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation ForLoc = ConsumeToken(); // eat the 'for'. 12239a920342707e384473b464528d2fd286e8c70353Sebastian Redl 12244e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::l_paren)) { 12251ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Tok, diag::err_expected_lparen_after) << "for"; 12265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::semi); 12279a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 12285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 12299a920342707e384473b464528d2fd286e8c70353Sebastian Redl 12304d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1; 1231488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis 12322215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // C99 6.8.5p5 - In C99, the for statement is a block. This is not 12332215325a5696fb3b23551239b900559bb3018ee9Chris Lattner // the case for C90. Start the loop scope. 1234488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1235488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.4p3: 1236488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // A name introduced by a declaration in a condition is in scope from its 1237488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // point of declaration until the end of the substatements controlled by the 1238488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // condition. 123914d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // C++ 3.3.2p4: 124014d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // Names declared in the for-init-statement, and in the condition of if, 124114d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // while, for, and switch statements are local to the if, while, for, or 124214d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis // switch statement (including the controlled statement). 1243488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.5.3p1: 1244488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // Names declared in the for-init-statement are in the same declarative-region 1245488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // as those declared in the condition. 1246488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 12478935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor unsigned ScopeFlags; 12484d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner if (C99orCXXorObjC) 12498935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ScopeFlags = Scope::BreakScope | Scope::ContinueScope | 12508935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor Scope::DeclScope | Scope::ControlScope; 12512215325a5696fb3b23551239b900559bb3018ee9Chris Lattner else 12528935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ScopeFlags = Scope::BreakScope | Scope::ContinueScope; 12538935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor 12548935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope ForScope(this, ScopeFlags); 12555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 12565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation LParenLoc = ConsumeParen(); 125760d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Value; 12580e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 1259ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith bool ForEach = false, ForRange = false; 126060d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult FirstPart; 1261eecf38f821fe8e113722096b77da7d68b26d28d1Douglas Gregor bool SecondPartIsInvalid = false; 1262586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor FullExprArg SecondPart(Actions); 126360d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Collection; 1264ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ForRangeInit ForRangeInit; 1265586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor FullExprArg ThirdPart(Actions); 1266d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *SecondVar = 0; 126799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor 1268791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor if (Tok.is(tok::code_completion)) { 126923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.CodeCompleteOrdinaryName(getCurScope(), 1270f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall C99orCXXorObjC? Sema::PCC_ForInit 1271f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall : Sema::PCC_Expression); 1272dc8453422bec3bbf70c03920e01498d75783d122Douglas Gregor ConsumeCodeCompletionToken(); 1273791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor } 1274791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor 12755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse the first part of the for specifier. 12764e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.is(tok::semi)) { // for (; 12775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // no first part, eat the ';'. 12785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 1279bbc70c019f7b7f9a256ee29dab5287ecc82c6553Argyrios Kyrtzidis } else if (isSimpleDeclaration()) { // for (int X = 4; 12805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Parse declaration, which eats the ';'. 12814d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? 12825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); 12839a920342707e384473b464528d2fd286e8c70353Sebastian Redl 12840b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall ParsedAttributesWithRange attrs(AttrFactory); 12857f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall MaybeParseCXX0XAttributes(attrs); 1286bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt 1287ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // In C++0x, "for (T NS:a" might not be a typo for :: 1288ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith bool MightBeForRangeStmt = getLang().CPlusPlus; 1289ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); 1290ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 129197144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner SourceLocation DeclStart = Tok.getLocation(), DeclEnd; 1292c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz Jahanian StmtVector Stmts(Actions); 1293c5be7b0fc804d8e6f87298ec03c94d8cccd74f29Fariborz Jahanian DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, 1294ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith DeclEnd, attrs, false, 1295ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith MightBeForRangeStmt ? 1296ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith &ForRangeInit : 0); 1297cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); 12981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1299ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (ForRangeInit.ParsedForRangeDecl()) { 1300ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ForRange = true; 1301ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } else if (Tok.is(tok::semi)) { // for (int x = 4; 1302cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner ConsumeToken(); 1303cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner } else if ((ForEach = isTokIdentifier_in())) { 1304a7cf23a72b0846fc5aacf3f38bb8c8f9e76784cfFariborz Jahanian Actions.ActOnForEachDeclStmt(DG); 13051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // ObjC: for (id x in expr) 13063ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian ConsumeToken(); // consume 'in' 1307fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor 1308fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor if (Tok.is(tok::code_completion)) { 1309fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor Actions.CodeCompleteObjCForCollection(getCurScope(), DG); 1310fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor ConsumeCodeCompletionToken(); 1311fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor } 1312586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor Collection = ParseExpression(); 1313cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner } else { 1314cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner Diag(Tok, diag::err_expected_semi_for); 13153ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian } 13165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } else { 13175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Value = ParseExpression(); 13185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1319f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall ForEach = isTokIdentifier_in(); 1320f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall 13215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Turn the expression into a stmt. 1322f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall if (!Value.isInvalid()) { 1323f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall if (ForEach) 1324f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); 1325f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall else 1326f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value.get())); 1327f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall } 1328effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 13294e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.is(tok::semi)) { 13305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 1331f6a1648197562e0b133440d612d9af297d0a86ccJohn McCall } else if (ForEach) { 13323ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian ConsumeToken(); // consume 'in' 1333fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor 1334fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor if (Tok.is(tok::code_completion)) { 1335fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor Actions.CodeCompleteObjCForCollection(getCurScope(), DeclGroupPtrTy()); 1336fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor ConsumeCodeCompletionToken(); 1337fb6294123b9de1605adae69d85cb4fddf81a9bc5Douglas Gregor } 1338586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor Collection = ParseExpression(); 1339682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner } else { 1340b72c77855473379c4c47e701005f7818946f659bDouglas Gregor if (!Value.isInvalid()) { 1341b72c77855473379c4c47e701005f7818946f659bDouglas Gregor Diag(Tok, diag::err_expected_semi_for); 1342b72c77855473379c4c47e701005f7818946f659bDouglas Gregor } else { 1343b72c77855473379c4c47e701005f7818946f659bDouglas Gregor // Skip until semicolon or rparen, don't consume it. 1344b72c77855473379c4c47e701005f7818946f659bDouglas Gregor SkipUntil(tok::r_paren, true, true); 1345b72c77855473379c4c47e701005f7818946f659bDouglas Gregor if (Tok.is(tok::semi)) 1346b72c77855473379c4c47e701005f7818946f659bDouglas Gregor ConsumeToken(); 1347b72c77855473379c4c47e701005f7818946f659bDouglas Gregor } 13485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 13495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1350ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (!ForEach && !ForRange) { 13519ae2f076ca5ab1feb3ba95629099ec2319833701John McCall assert(!SecondPart.get() && "Shouldn't have a second expression yet."); 13523ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian // Parse the second part of the for specifier. 13533ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian if (Tok.is(tok::semi)) { // for (...;; 13543ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian // no second part. 1355b72c77855473379c4c47e701005f7818946f659bDouglas Gregor } else if (Tok.is(tok::r_paren)) { 1356b72c77855473379c4c47e701005f7818946f659bDouglas Gregor // missing both semicolons. 13573ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian } else { 135860d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Second; 135999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor if (getLang().CPlusPlus) 1360586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor ParseCXXCondition(Second, SecondVar, ForLoc, true); 1361586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor else { 1362586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor Second = ParseExpression(); 1363586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor if (!Second.isInvalid()) 136423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, 13659ae2f076ca5ab1feb3ba95629099ec2319833701John McCall Second.get()); 1366586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor } 1367eecf38f821fe8e113722096b77da7d68b26d28d1Douglas Gregor SecondPartIsInvalid = Second.isInvalid(); 13689ae2f076ca5ab1feb3ba95629099ec2319833701John McCall SecondPart = Actions.MakeFullExpr(Second.get()); 13693ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian } 13700e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 1371b72c77855473379c4c47e701005f7818946f659bDouglas Gregor if (Tok.isNot(tok::semi)) { 1372b72c77855473379c4c47e701005f7818946f659bDouglas Gregor if (!SecondPartIsInvalid || SecondVar) 1373b72c77855473379c4c47e701005f7818946f659bDouglas Gregor Diag(Tok, diag::err_expected_semi_for); 1374b72c77855473379c4c47e701005f7818946f659bDouglas Gregor else 1375b72c77855473379c4c47e701005f7818946f659bDouglas Gregor // Skip until semicolon or rparen, don't consume it. 1376b72c77855473379c4c47e701005f7818946f659bDouglas Gregor SkipUntil(tok::r_paren, true, true); 1377b72c77855473379c4c47e701005f7818946f659bDouglas Gregor } 1378b72c77855473379c4c47e701005f7818946f659bDouglas Gregor 13793ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian if (Tok.is(tok::semi)) { 13803ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian ConsumeToken(); 13813ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian } 13829a920342707e384473b464528d2fd286e8c70353Sebastian Redl 13833ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian // Parse the third part of the for specifier. 1384586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor if (Tok.isNot(tok::r_paren)) { // for (...;...;) 138560d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Third = ParseExpression(); 13869ae2f076ca5ab1feb3ba95629099ec2319833701John McCall ThirdPart = Actions.MakeFullExpr(Third.take()); 1387586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor } 13885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 13895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Match the ')'. 13905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 13910e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 1392ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // We need to perform most of the semantic analysis for a C++0x for-range 1393ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // statememt before parsing the body, in order to be able to deduce the type 1394ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // of an auto-typed loop variable. 1395ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith StmtResult ForRangeStmt; 1396ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (ForRange) 1397ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, LParenLoc, 1398ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith FirstPart.take(), 1399ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ForRangeInit.ColonLoc, 1400ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ForRangeInit.RangeExpr.get(), 1401ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith RParenLoc); 1402ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 14030ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if 140438484403c8356fb41540ace6c74f28867f28febaChris Lattner // there is no compound stmt. C90 does not have this clause. We only do this 140538484403c8356fb41540ace6c74f28867f28febaChris Lattner // if the body isn't a compound statement to avoid push/pop in common cases. 1406488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1407488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // C++ 6.5p2: 1408488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // The substatement in an iteration-statement implicitly defines a local scope 1409488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // which is entered and exited each time through the loop. 1410488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 1411488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // See comments in ParseIfStatement for why we create a scope for 1412488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // for-init-statement/condition and a new scope for substatement in C++. 1413488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis // 14141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParseScope InnerScope(this, Scope::DeclScope, 14154d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner C99orCXXorObjC && Tok.isNot(tok::l_brace)); 14160e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 14175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Read the body statement. 141860d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Body(ParseStatement()); 14190e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 14200ecea03077117c7ea54c88091a44c73cef67923cChris Lattner // Pop the body scope if needed. 14218935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor InnerScope.Exit(); 14220ecea03077117c7ea54c88091a44c73cef67923cChris Lattner 14235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Leave the for-scope. 14248935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ForScope.Exit(); 14250e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 14260e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (Body.isInvalid()) 14279a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 1428effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 1429ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (ForEach) 1430ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // FIXME: It isn't clear how to communicate the late destruction of 1431ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // C++ temporaries used to create the collection. 1432ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, 1433ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith FirstPart.take(), 1434ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Collection.take(), RParenLoc, 1435ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Body.take()); 1436ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 1437ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (ForRange) 1438ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); 1439586596fd7f7a336a2847b300c80614dcf39ab6d5Douglas Gregor 1440ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart, 1441ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SecondVar, ThirdPart, RParenLoc, Body.take()); 14425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 14435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 14445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseGotoStatement 14455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// jump-statement: 14465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'goto' identifier ';' 14475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] 'goto' '*' expression ';' 14485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 14495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'. 14505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 14517f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) { 1452bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 14531e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 14544e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_goto) && "Not a goto stmt!"); 14555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'. 14569a920342707e384473b464528d2fd286e8c70353Sebastian Redl 145760d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult Res; 14584e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.is(tok::identifier)) { 1459337e550218128e7d922c09bb354fbc71de90c568Chris Lattner LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(), 1460337e550218128e7d922c09bb354fbc71de90c568Chris Lattner Tok.getLocation()); 1461337e550218128e7d922c09bb354fbc71de90c568Chris Lattner Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD); 14625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 1463f01fdff97b245caac98100d232c760b4d0531411Eli Friedman } else if (Tok.is(tok::star)) { 14645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // GNU indirect goto extension. 14655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::ext_gnu_indirect_goto); 14665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation StarLoc = ConsumeToken(); 146760d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult R(ParseExpression()); 14680e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (R.isInvalid()) { // Skip to the semicolon, but don't consume it. 14695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::semi, false, true); 14709a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 14715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 14729ae2f076ca5ab1feb3ba95629099ec2319833701John McCall Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take()); 147395cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner } else { 147495cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner Diag(Tok, diag::err_expected_ident); 14759a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 14765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 14770e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 14789a920342707e384473b464528d2fd286e8c70353Sebastian Redl return move(Res); 14795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 14805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 14815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseContinueStatement 14825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// jump-statement: 14835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'continue' ';' 14845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 14855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'. 14865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 14877f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) { 1488bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 14891e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 14905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'. 149123c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor return Actions.ActOnContinueStmt(ContinueLoc, getCurScope()); 14925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 14935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 14945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseBreakStatement 14955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// jump-statement: 14965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'break' ';' 14975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 14985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'. 14995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 15007f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) { 1501bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 15021e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 15035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'. 150423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor return Actions.ActOnBreakStmt(BreakLoc, getCurScope()); 15055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 15065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 15075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseReturnStatement 15085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// jump-statement: 15095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'return' expression[opt] ';' 15107f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) { 1511bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Use attributes? 15121e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 15134e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_return) && "Not a return stmt!"); 15145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'. 15159a920342707e384473b464528d2fd286e8c70353Sebastian Redl 151660d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult R; 15174e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::semi)) { 15185ac3bdb2cb0113b640c54f01468d21985c08b252Douglas Gregor if (Tok.is(tok::code_completion)) { 151923c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.CodeCompleteReturn(getCurScope()); 15205ac3bdb2cb0113b640c54f01468d21985c08b252Douglas Gregor ConsumeCodeCompletionToken(); 15215ac3bdb2cb0113b640c54f01468d21985c08b252Douglas Gregor SkipUntil(tok::semi, false, true); 15225ac3bdb2cb0113b640c54f01468d21985c08b252Douglas Gregor return StmtError(); 15235ac3bdb2cb0113b640c54f01468d21985c08b252Douglas Gregor } 15245ac3bdb2cb0113b640c54f01468d21985c08b252Douglas Gregor 15256f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor // FIXME: This is a hack to allow something like C++0x's generalized 15266f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor // initializer lists, but only enough of this feature to allow Clang to 15276f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor // parse libstdc++ 4.5's headers. 15286f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor if (Tok.is(tok::l_brace) && getLang().CPlusPlus) { 15296f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor R = ParseInitializer(); 15306f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor if (R.isUsable() && !getLang().CPlusPlus0x) 15316f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor Diag(R.get()->getLocStart(), diag::ext_generalized_initializer_lists) 15326f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor << R.get()->getSourceRange(); 15336f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor } else 15346f4596cfb70ec706dd2da38db1be3663c214ff7aDouglas Gregor R = ParseExpression(); 15350e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (R.isInvalid()) { // Skip to the semicolon, but don't consume it. 15365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::semi, false, true); 15379a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 15385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 15395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 15409ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnReturnStmt(ReturnLoc, R.take()); 15415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 15425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 15435f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this 15445f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// routine is called to skip/ignore tokens that comprise the MS asm statement. 1545a44724d0d6d03568ec9acadc0781d612163008e1Abramo BagnaraStmtResult Parser::FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc) { 1546a44724d0d6d03568ec9acadc0781d612163008e1Abramo Bagnara SourceLocation EndLoc; 1547b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff if (Tok.is(tok::l_brace)) { 1548b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff unsigned short savedBraceCount = BraceCount; 1549b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff do { 1550a44724d0d6d03568ec9acadc0781d612163008e1Abramo Bagnara EndLoc = Tok.getLocation(); 1551b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff ConsumeAnyToken(); 1552b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof)); 15531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else { 1554b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff // From the MS website: If used without braces, the __asm keyword means 1555b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff // that the rest of the line is an assembly-language statement. 1556b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff SourceManager &SrcMgr = PP.getSourceManager(); 155703d6bc6734eb79dc27628d9ea1126c299c80b4b6Steve Naroff SourceLocation TokLoc = Tok.getLocation(); 1558f7cf85b330bedd2877e1371fb0a83e99751ae162Chris Lattner unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc); 1559362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff do { 1560a44724d0d6d03568ec9acadc0781d612163008e1Abramo Bagnara EndLoc = TokLoc; 1561362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff ConsumeAnyToken(); 1562362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff TokLoc = Tok.getLocation(); 15631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) && 15641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) && 1565362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff Tok.isNot(tok::eof)); 1566b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff } 156795059b50136e8aa9bb02017fb9210d3708b06577Mike Stump Token t; 156895059b50136e8aa9bb02017fb9210d3708b06577Mike Stump t.setKind(tok::string_literal); 1569e78968547e4976834090efdac4522c7b94daa89aChris Lattner t.setLiteralData("\"/*FIXME: not done*/\""); 157095059b50136e8aa9bb02017fb9210d3708b06577Mike Stump t.clearFlag(Token::NeedsCleaning); 1571e78968547e4976834090efdac4522c7b94daa89aChris Lattner t.setLength(21); 15726cf750298d3621d8a10a6dd07fcee8e274b9d94dSean Hunt ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1)); 157395059b50136e8aa9bb02017fb9210d3708b06577Mike Stump ExprVector Constraints(Actions); 157495059b50136e8aa9bb02017fb9210d3708b06577Mike Stump ExprVector Exprs(Actions); 157595059b50136e8aa9bb02017fb9210d3708b06577Mike Stump ExprVector Clobbers(Actions); 1576a44724d0d6d03568ec9acadc0781d612163008e1Abramo Bagnara return Actions.ActOnAsmStmt(AsmLoc, true, true, 0, 0, 0, 157795059b50136e8aa9bb02017fb9210d3708b06577Mike Stump move_arg(Constraints), move_arg(Exprs), 15789ae2f076ca5ab1feb3ba95629099ec2319833701John McCall AsmString.take(), move_arg(Clobbers), 1579a44724d0d6d03568ec9acadc0781d612163008e1Abramo Bagnara EndLoc, true); 1580d62701bc5321049353017e9abf1963edd57646aaSteve Naroff} 1581d62701bc5321049353017e9abf1963edd57646aaSteve Naroff 15825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmStatement - Parse a GNU extended asm statement. 15835f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// asm-statement: 15845f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// gnu-asm-statement 15855f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// ms-asm-statement 15865f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// 15875f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [GNU] gnu-asm-statement: 15885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';' 15895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 15905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-argument: 15915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-string-literal 15925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-string-literal ':' asm-operands[opt] 15935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] 15945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] 15955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ':' asm-clobbers 15965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 15975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-clobbers: 15985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-string-literal 15995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-clobbers ',' asm-string-literal 16005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 16015f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS] ms-asm-statement: 16025f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// '__asm' assembly-instruction ';'[opt] 16035f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// '__asm' '{' assembly-instruction-list '}' ';'[opt] 16045f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// 16055f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS] assembly-instruction-list: 16065f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// assembly-instruction ';'[opt] 16075f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// assembly-instruction-list ';' assembly-instruction ';'[opt] 16085f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// 160960d7b3a319d84d688752be3870615ac0f111fb16John McCallStmtResult Parser::ParseAsmStatement(bool &msAsm) { 16104e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); 1611fe795956194141c91ae555985c9b930595bff43fChris Lattner SourceLocation AsmLoc = ConsumeToken(); 16129a920342707e384473b464528d2fd286e8c70353Sebastian Redl 16135f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { 1614d62701bc5321049353017e9abf1963edd57646aaSteve Naroff msAsm = true; 1615a44724d0d6d03568ec9acadc0781d612163008e1Abramo Bagnara return FuzzyParseMicrosoftAsmStatement(AsmLoc); 1616d62701bc5321049353017e9abf1963edd57646aaSteve Naroff } 16170b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall DeclSpec DS(AttrFactory); 16185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation Loc = Tok.getLocation(); 1619bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt ParseTypeQualifierListOpt(DS, true, false); 16209a920342707e384473b464528d2fd286e8c70353Sebastian Redl 16215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // GNU asms accept, but warn, about type-qualifiers other than volatile. 16225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (DS.getTypeQualifiers() & DeclSpec::TQ_const) 16231ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Loc, diag::w_asm_qualifier_ignored) << "const"; 16245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) 16251ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict"; 16269a920342707e384473b464528d2fd286e8c70353Sebastian Redl 16275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Remember if this was a volatile asm. 162839c47b56f45437bbc49c9568b7308a400234a730Anders Carlsson bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; 16294e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::l_paren)) { 16301ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Tok, diag::err_expected_lparen_after) << "asm"; 16315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::r_paren); 16329a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 16335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 16345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Loc = ConsumeParen(); 16359a920342707e384473b464528d2fd286e8c70353Sebastian Redl 163660d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult AsmString(ParseAsmStringLiteral()); 16370e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (AsmString.isInvalid()) 16389a920342707e384473b464528d2fd286e8c70353Sebastian Redl return StmtError(); 16390e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 1640ff93dbd887e40588ed55d135037bb9287488b285Anders Carlsson llvm::SmallVector<IdentifierInfo *, 4> Names; 1641a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl ExprVector Constraints(Actions); 1642a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl ExprVector Exprs(Actions); 1643a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl ExprVector Clobbers(Actions); 1644dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson 1645dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson if (Tok.is(tok::r_paren)) { 164664cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner // We have a simple asm expression like 'asm("foo")'. 164764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner SourceLocation RParenLoc = ConsumeParen(); 164864cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, 164964cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, 165064cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner move_arg(Constraints), move_arg(Exprs), 16519ae2f076ca5ab1feb3ba95629099ec2319833701John McCall AsmString.take(), move_arg(Clobbers), 165264cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner RParenLoc); 165364cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner } 16549a920342707e384473b464528d2fd286e8c70353Sebastian Redl 165564cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner // Parse Outputs, if present. 16566405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner bool AteExtraColon = false; 16576405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { 16586405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner // In C++ mode, parse "::" like ": :". 16596405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner AteExtraColon = Tok.is(tok::coloncolon); 166064cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner ConsumeToken(); 166164cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner 16626405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner if (!AteExtraColon && 16636405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner ParseAsmOperandsOpt(Names, Constraints, Exprs)) 166464cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner return StmtError(); 166564cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner } 16666405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner 166764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner unsigned NumOutputs = Names.size(); 16689a920342707e384473b464528d2fd286e8c70353Sebastian Redl 166964cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner // Parse Inputs, if present. 16706405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner if (AteExtraColon || 16716405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { 16726405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner // In C++ mode, parse "::" like ": :". 16736405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner if (AteExtraColon) 16746405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner AteExtraColon = false; 16756405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner else { 16766405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner AteExtraColon = Tok.is(tok::coloncolon); 16776405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner ConsumeToken(); 16786405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner } 16796405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner 16806405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner if (!AteExtraColon && 16816405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner ParseAsmOperandsOpt(Names, Constraints, Exprs)) 168264cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner return StmtError(); 168364cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner } 1684effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 168564cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner assert(Names.size() == Constraints.size() && 168664cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner Constraints.size() == Exprs.size() && 168764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner "Input operand size mismatch!"); 1688b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson 168964cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner unsigned NumInputs = Names.size() - NumOutputs; 1690effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 169164cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner // Parse the clobbers, if present. 16926405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner if (AteExtraColon || Tok.is(tok::colon)) { 16936405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner if (!AteExtraColon) 16946405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner ConsumeToken(); 1695effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 1696102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth // Parse the asm-string list for clobbers if present. 1697102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth if (Tok.isNot(tok::r_paren)) { 1698102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth while (1) { 169960d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Clobber(ParseAsmStringLiteral()); 17005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1701102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth if (Clobber.isInvalid()) 1702102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth break; 1703effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 1704102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth Clobbers.push_back(Clobber.release()); 1705effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 1706102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth if (Tok.isNot(tok::comma)) break; 1707102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth ConsumeToken(); 1708102e1b6a4753b0bd3662ad1bd119f6efa04b8763Chandler Carruth } 17095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1710dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson } 1711effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 171264cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc); 171364cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile, 1714beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad NumOutputs, NumInputs, Names.data(), 1715f512e82f56671b695a32d019103e62a302838b7eSebastian Redl move_arg(Constraints), move_arg(Exprs), 17169ae2f076ca5ab1feb3ba95629099ec2319833701John McCall AsmString.take(), move_arg(Clobbers), 17173037ed0a27dba62e522304183718efc149e8b6d9Sebastian Redl RParenLoc); 17185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 17195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 17205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmOperands - Parse the asm-operands production as used by 172164cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner/// asm-statement, assuming the leading ':' token was eaten. 17225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 17235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operands: 17245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-operand 17255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-operands ',' asm-operand 17265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 17275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operand: 17285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-string-literal '(' expression ')' 17295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// '[' identifier ']' asm-string-literal '(' expression ')' 17305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 17315ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar// 17325ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar// FIXME: Avoid unnecessary std::string trashing. 1733ff93dbd887e40588ed55d135037bb9287488b285Anders Carlssonbool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, 1734ff93dbd887e40588ed55d135037bb9287488b285Anders Carlsson llvm::SmallVectorImpl<ExprTy *> &Constraints, 1735ff93dbd887e40588ed55d135037bb9287488b285Anders Carlsson llvm::SmallVectorImpl<ExprTy *> &Exprs) { 17365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // 'asm-operands' isn't present? 17374e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (!isTokenStringLiteral() && Tok.isNot(tok::l_square)) 17388bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson return false; 17391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump while (1) { 17415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Read the [id] if present. 17424e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.is(tok::l_square)) { 17435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation Loc = ConsumeBracket(); 17441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17454e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::identifier)) { 17465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Diag(Tok, diag::err_expected_ident); 17475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::r_paren); 17488bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson return true; 17495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 17501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1751b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson IdentifierInfo *II = Tok.getIdentifierInfo(); 175269efba74cf5488060accf34c011b33ce6c15ece0Chris Lattner ConsumeToken(); 1753b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson 1754ff93dbd887e40588ed55d135037bb9287488b285Anders Carlsson Names.push_back(II); 17555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer MatchRHSPunctuation(tok::r_square, Loc); 1756b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson } else 1757ff93dbd887e40588ed55d135037bb9287488b285Anders Carlsson Names.push_back(0); 17580e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl 175960d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Constraint(ParseAsmStringLiteral()); 17600e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (Constraint.isInvalid()) { 1761b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson SkipUntil(tok::r_paren); 17628bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson return true; 1763b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson } 1764effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl Constraints.push_back(Constraint.release()); 17655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 17664e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner if (Tok.isNot(tok::l_paren)) { 17671ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner Diag(Tok, diag::err_expected_lparen_after) << "asm operand"; 17685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::r_paren); 17698bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson return true; 17705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1771effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl 17725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Read the parenthesized expression. 177372056a237c536ee63285ab0850cb50f299281767Eli Friedman SourceLocation OpenLoc = ConsumeParen(); 177460d7b3a319d84d688752be3870615ac0f111fb16John McCall ExprResult Res(ParseExpression()); 177572056a237c536ee63285ab0850cb50f299281767Eli Friedman MatchRHSPunctuation(tok::r_paren, OpenLoc); 17760e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (Res.isInvalid()) { 17775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SkipUntil(tok::r_paren); 17788bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson return true; 17795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1780effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl Exprs.push_back(Res.release()); 17815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Eat the comma and continue parsing if it exists. 17828bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson if (Tok.isNot(tok::comma)) return false; 17835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ConsumeToken(); 17845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 17858bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson 17868bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson return true; 17875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1788f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian 1789c9977d09a2de7f7d2245973413d4caf86c736640Douglas GregorDecl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { 179040e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner assert(Tok.is(tok::l_brace)); 179140e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner SourceLocation LBraceLoc = Tok.getLocation(); 1792d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 1793c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor if (PP.isCodeCompletionEnabled()) { 1794c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor if (trySkippingFunctionBodyForCodeCompletion()) { 1795c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor BodyScope.Exit(); 1796b162054ba8f5b64fe87fbc4837933ab23eebd52bArgyrios Kyrtzidis return Actions.ActOnFinishFunctionBody(Decl, 0); 1797c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor } 1798c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor } 1799c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor 1800f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, 1801f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall "parsing function body"); 18021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1803f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian // Do not enter a scope for the brace, as the arguments are in the same scope 1804f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian // (the function body) as the body itself. Instead, just read the statement 1805f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian // list and put it into a CompoundStmt for safe keeping. 180660d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult FnBody(ParseCompoundStatementBody()); 180761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 1808f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian // If the function body could not be parsed, make a bogus compoundstmt. 18090e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl if (FnBody.isInvalid()) 18101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, 181140e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner MultiStmtArg(Actions), false); 181261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl 1813c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor BodyScope.Exit(); 18149ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); 1815cd5af4b5863c63b62cde96ad6d52fb1eec0e26bbSeo Sanghyeon} 1816a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1817d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// ParseFunctionTryBlock - Parse a C++ function-try-block. 1818d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 1819d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// function-try-block: 1820d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 'try' ctor-initializer[opt] compound-statement handler-seq 1821d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 1822c9977d09a2de7f7d2245973413d4caf86c736640Douglas GregorDecl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { 1823d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl assert(Tok.is(tok::kw_try) && "Expected 'try'"); 1824d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl SourceLocation TryLoc = ConsumeToken(); 1825d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 1826f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, TryLoc, 1827f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall "parsing function try block"); 1828d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 1829d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // Constructor initializer list? 1830d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl if (Tok.is(tok::colon)) 1831d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl ParseConstructorInitializer(Decl); 1832d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 1833c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor if (PP.isCodeCompletionEnabled()) { 1834c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor if (trySkippingFunctionBodyForCodeCompletion()) { 1835c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor BodyScope.Exit(); 1836b162054ba8f5b64fe87fbc4837933ab23eebd52bArgyrios Kyrtzidis return Actions.ActOnFinishFunctionBody(Decl, 0); 1837c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor } 1838c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor } 18390fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis 1840de1b60a9868f80f0872ed05d78df3b40a10ba5caSebastian Redl SourceLocation LBraceLoc = Tok.getLocation(); 184160d7b3a319d84d688752be3870615ac0f111fb16John McCall StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc)); 1842d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // If we failed to parse the try-catch, we just give the function an empty 1843d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // compound statement as the body. 1844d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl if (FnBody.isInvalid()) 1845de1b60a9868f80f0872ed05d78df3b40a10ba5caSebastian Redl FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, 1846d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl MultiStmtArg(Actions), false); 1847d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 1848c9977d09a2de7f7d2245973413d4caf86c736640Douglas Gregor BodyScope.Exit(); 18499ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); 1850d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl} 1851d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 1852b162054ba8f5b64fe87fbc4837933ab23eebd52bArgyrios Kyrtzidisbool Parser::trySkippingFunctionBodyForCodeCompletion() { 18530fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis assert(Tok.is(tok::l_brace)); 1854b162054ba8f5b64fe87fbc4837933ab23eebd52bArgyrios Kyrtzidis assert(PP.isCodeCompletionEnabled() && 1855b162054ba8f5b64fe87fbc4837933ab23eebd52bArgyrios Kyrtzidis "Should only be called when in code-completion mode"); 18560fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis 18570fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis // We're in code-completion mode. Skip parsing for all function bodies unless 18580fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis // the body contains the code-completion point. 18590fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis TentativeParsingAction PA(*this); 18600fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis ConsumeBrace(); 18610fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false, 18620fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis /*StopAtCodeCompletion=*/true)) { 18630fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis PA.Commit(); 18640fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis return true; 18650fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis } 18660fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis 18670fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis PA.Revert(); 18680fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis return false; 18690fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis} 18700fe5397b26695926a835fa99eceb7fc879b307afArgyrios Kyrtzidis 1871a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// ParseCXXTryBlock - Parse a C++ try-block. 1872a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// 1873a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// try-block: 1874a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// 'try' compound-statement handler-seq 1875a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// 18767f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCallStmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) { 1877bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Add attributes? 18781e37765c9257ef1d051f54a674eaa964bdba9693Ted Kremenek 1879a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl assert(Tok.is(tok::kw_try) && "Expected 'try'"); 1880a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1881a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl SourceLocation TryLoc = ConsumeToken(); 1882d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl return ParseCXXTryBlockCommon(TryLoc); 1883d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl} 1884d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 1885d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// ParseCXXTryBlockCommon - Parse the common part of try-block and 1886d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// function-try-block. 1887d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 1888d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// try-block: 1889d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 'try' compound-statement handler-seq 1890d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 1891d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// function-try-block: 1892d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 'try' ctor-initializer[opt] compound-statement handler-seq 1893d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 1894d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// handler-seq: 1895d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// handler handler-seq[opt] 1896d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// 189728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// [Borland] try-block: 189828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 'try' compound-statement seh-except-block 189928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 'try' compound-statment seh-finally-block 190028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley/// 190160d7b3a319d84d688752be3870615ac0f111fb16John McCallStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { 1902a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl if (Tok.isNot(tok::l_brace)) 1903a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl return StmtError(Diag(Tok, diag::err_expected_lbrace)); 1904bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Possible draft standard bug: attribute-specifier should be allowed? 19050b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall ParsedAttributesWithRange attrs(AttrFactory); 19067f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall StmtResult TryBlock(ParseCompoundStatement(attrs)); 1907a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl if (TryBlock.isInvalid()) 1908a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl return move(TryBlock); 1909a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 191028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley // Borland allows SEH-handlers with 'try' 191128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Tok.is(tok::kw___except) || Tok.is(tok::kw___finally)) { 191228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley // TODO: Factor into common return ParseSEHHandlerCommon(...) 191328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley StmtResult Handler; 191428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Tok.is(tok::kw___except)) { 191528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley SourceLocation Loc = ConsumeToken(); 191628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley Handler = ParseSEHExceptBlock(Loc); 191728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley } 191828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley else { 191928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley SourceLocation Loc = ConsumeToken(); 192028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley Handler = ParseSEHFinallyBlock(Loc); 192128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley } 192228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if(Handler.isInvalid()) 192328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return move(Handler); 192428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 192528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return Actions.ActOnSEHTryBlock(true /* IsCXXTry */, 192628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley TryLoc, 192728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley TryBlock.take(), 192828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley Handler.take()); 1929a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl } 193028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley else { 193128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley StmtVector Handlers(Actions); 193228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley MaybeParseCXX0XAttributes(attrs); 193328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley ProhibitAttributes(attrs); 193428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley 193528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if (Tok.isNot(tok::kw_catch)) 193628bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return StmtError(Diag(Tok, diag::err_expected_catch)); 193728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley while (Tok.is(tok::kw_catch)) { 193828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley StmtResult Handler(ParseCXXCatchBlock()); 193928bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if (!Handler.isInvalid()) 194028bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley Handlers.push_back(Handler.release()); 194128bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley } 194228bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley // Don't bother creating the full statement if we don't have any usable 194328bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley // handlers. 194428bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley if (Handlers.empty()) 194528bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return StmtError(); 1946a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 194728bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers)); 194828bbe4b8acc338476fe0825769b41fb32b423c72John Wiegley } 1949a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl} 1950a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1951a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard 1952a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// 1953a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// handler: 1954a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// 'catch' '(' exception-declaration ')' compound-statement 1955a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// 1956a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// exception-declaration: 1957a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// type-specifier-seq declarator 1958a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// type-specifier-seq abstract-declarator 1959a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// type-specifier-seq 1960a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// '...' 1961a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// 196260d7b3a319d84d688752be3870615ac0f111fb16John McCallStmtResult Parser::ParseCXXCatchBlock() { 1963a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl assert(Tok.is(tok::kw_catch) && "Expected 'catch'"); 1964a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1965a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl SourceLocation CatchLoc = ConsumeToken(); 1966a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1967a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl SourceLocation LParenLoc = Tok.getLocation(); 1968a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) 1969a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl return StmtError(); 1970a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1971a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl // C++ 3.3.2p3: 1972a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl // The name in a catch exception-declaration is local to the handler and 1973a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl // shall not be redeclared in the outermost block of the handler. 1974a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope); 1975a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1976a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl // exception-declaration is equivalent to '...' or a parameter-declaration 1977a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl // without default arguments. 1978d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *ExceptionDecl = 0; 1979a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl if (Tok.isNot(tok::ellipsis)) { 19800b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall DeclSpec DS(AttrFactory); 19814b07b2968f87f3cd5a3d8c76145f1cbfd718d42dSebastian Redl if (ParseCXXTypeSpecifierSeq(DS)) 19824b07b2968f87f3cd5a3d8c76145f1cbfd718d42dSebastian Redl return StmtError(); 1983a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl Declarator ExDecl(DS, Declarator::CXXCatchContext); 1984a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl ParseDeclarator(ExDecl); 198523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl); 1986a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl } else 1987a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl ConsumeToken(); 1988a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1989a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid()) 1990a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl return StmtError(); 1991a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1992a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl if (Tok.isNot(tok::l_brace)) 1993a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl return StmtError(Diag(Tok, diag::err_expected_lbrace)); 1994a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 1995bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt // FIXME: Possible draft standard bug: attribute-specifier should be allowed? 19960b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall ParsedAttributes attrs(AttrFactory); 19977f040a9d817cd1c72b565e92abff473510bf9e1dJohn McCall StmtResult Block(ParseCompoundStatement(attrs)); 1998a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl if (Block.isInvalid()) 1999a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl return move(Block); 2000a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl 20019ae2f076ca5ab1feb3ba95629099ec2319833701John McCall return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take()); 2002a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl} 2003