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