diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp | 140 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp | 810 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | 418 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp | 184 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp | 577 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp | 25 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp | 631 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp | 19 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 395 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp | 115 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp | 26 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 187 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h | 4 |
14 files changed, 2390 insertions, 1147 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp index 56584c9..fdd7d0f 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp @@ -37,11 +37,11 @@ using namespace clang; /// void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, ASTContext &Ctx, bool PrintStats, - bool CompleteTranslationUnit, + TranslationUnitKind TUKind, CodeCompleteConsumer *CompletionConsumer) { llvm::OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, - CompleteTranslationUnit, + TUKind, CompletionConsumer)); // Recover resources if we crash before exiting this method. @@ -93,7 +93,7 @@ void clang::ParseAST(Sema &S, bool PrintStats) { Consumer->HandleTopLevelDecl(ADecl.get()); // Process any TopLevelDecls generated by #pragma weak. - for (llvm::SmallVector<Decl*,2>::iterator + for (SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(), E = S.WeakTopLevelDecls().end(); I != E; ++I) Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index f5c6998..b387e9e 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -21,7 +21,9 @@ using namespace clang; /// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. -Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, +Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, + AttributeList *AccessAttrs, + ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, ExprResult& Init) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); @@ -34,16 +36,25 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); Decl *FnD; + D.setFunctionDefinition(true); if (D.getDeclSpec().isFriendSpecified()) - // FIXME: Friend templates - FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true, + FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, move(TemplateParams)); - else { // FIXME: pass template information through + else { FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, move(TemplateParams), 0, - VS, Init.release(), - /*HasInit=*/false, - /*IsDefinition*/true); + VS, /*HasInit=*/false); + if (FnD) { + Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs, + false, true); + bool TypeSpecContainsAuto + = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; + if (Init.get()) + Actions.AddInitializerToDecl(FnD, Init.get(), false, + TypeSpecContainsAuto); + else + Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto); + } } HandleMemberFunctionDefaultArgs(D, FnD); @@ -123,30 +134,24 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, CachedTokens &Toks = LM->Toks; tok::TokenKind kind = Tok.getKind(); - // We may have a constructor initializer or function-try-block here. - if (kind == tok::colon || kind == tok::kw_try) { - // Consume everything up to (and including) the left brace. - if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) { - // We didn't find the left-brace we expected after the - // constructor initializer. - if (Tok.is(tok::semi)) { - // We found a semicolon; complain, consume the semicolon, and - // don't try to parse this method later. - Diag(Tok.getLocation(), diag::err_expected_lbrace); - ConsumeAnyToken(); - delete getCurrentClass().LateParsedDeclarations.back(); - getCurrentClass().LateParsedDeclarations.pop_back(); - return FnD; - } + // Consume everything up to (and including) the left brace of the + // function body. + if (ConsumeAndStoreFunctionPrologue(Toks)) { + // We didn't find the left-brace we expected after the + // constructor initializer. + if (Tok.is(tok::semi)) { + // We found a semicolon; complain, consume the semicolon, and + // don't try to parse this method later. + Diag(Tok.getLocation(), diag::err_expected_lbrace); + ConsumeAnyToken(); + delete getCurrentClass().LateParsedDeclarations.back(); + getCurrentClass().LateParsedDeclarations.pop_back(); + return FnD; } - } else { - // Begin by storing the '{' token. - Toks.push_back(Tok); - ConsumeBrace(); + // Consume everything up to (and including) the matching right brace. + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); } - // Consume everything up to (and including) the matching right brace. - ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); // If we're in a function-try-block, we need to store all the catch blocks. if (kind == tok::kw_try) { @@ -398,6 +403,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { if (!Tok.is(tok::l_brace)) { FnScope.Exit(); Actions.ActOnFinishFunctionBody(LM.D, 0); + while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + ConsumeAnyToken(); return; } } else @@ -450,7 +457,7 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) { } void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { - if (MI.Field->isInvalidDecl()) + if (!MI.Field || MI.Field->isInvalidDecl()) return; // Append the current token at the end of the new token stream so that it @@ -551,8 +558,16 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, ConsumeBrace(); break; + case tok::code_completion: + Toks.push_back(Tok); + ConsumeCodeCompletionToken(); + break; + case tok::string_literal: case tok::wide_string_literal: + case tok::utf8_string_literal: + case tok::utf16_string_literal: + case tok::utf32_string_literal: Toks.push_back(Tok); ConsumeStringToken(); break; @@ -569,3 +584,70 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, isFirstTokenConsumed = false; } } + +/// \brief Consume tokens and store them in the passed token container until +/// we've passed the try keyword and constructor initializers and have consumed +/// the opening brace of the function body. The opening brace will be consumed +/// if and only if there was no error. +/// +/// \return True on error. +bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { + if (Tok.is(tok::kw_try)) { + Toks.push_back(Tok); + ConsumeToken(); + } + if (Tok.is(tok::colon)) { + // Initializers can contain braces too. + Toks.push_back(Tok); + ConsumeToken(); + + while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) { + if (Tok.is(tok::eof) || Tok.is(tok::semi)) + return true; + + // Grab the identifier. + if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks, + /*StopAtSemi=*/true, + /*ConsumeFinalToken=*/false)) + return true; + + tok::TokenKind kind = Tok.getKind(); + Toks.push_back(Tok); + if (kind == tok::l_paren) + ConsumeParen(); + else { + assert(kind == tok::l_brace && "Must be left paren or brace here."); + ConsumeBrace(); + // In C++03, this has to be the start of the function body, which + // means the initializer is malformed. + if (!getLang().CPlusPlus0x) + return false; + } + + // Grab the initializer + if (!ConsumeAndStoreUntil(kind == tok::l_paren ? tok::r_paren : + tok::r_brace, + Toks, /*StopAtSemi=*/true)) + return true; + + // Grab the separating comma, if any. + if (Tok.is(tok::comma)) { + Toks.push_back(Tok); + ConsumeToken(); + } + } + } + + // Grab any remaining garbage to be diagnosed later. We stop when we reach a + // brace: an opening one is the function body, while a closing one probably + // means we've reached the end of the class. + if (!ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks, + /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false)) + return true; + if(Tok.isNot(tok::l_brace)) + return true; + + Toks.push_back(Tok); + ConsumeBrace(); + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 0e17295..2aa178f 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -19,6 +19,7 @@ #include "clang/Sema/PrettyDeclStackTrace.h" #include "RAIIObjectsForParser.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -32,12 +33,10 @@ using namespace clang; /// Called type-id in C++. TypeResult Parser::ParseTypeName(SourceRange *Range, Declarator::TheContext Context, - ObjCDeclSpec *objcQuals, AccessSpecifier AS, Decl **OwnedType) { // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); - DS.setObjCQualifiers(objcQuals); ParseSpecifierQualifierList(DS, AS); if (OwnedType) *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0; @@ -54,6 +53,16 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } + +/// isAttributeLateParsed - Return true if the attribute has arguments that +/// require late parsing. +static bool isAttributeLateParsed(const IdentifierInfo &II) { + return llvm::StringSwitch<bool>(II.getName()) +#include "clang/Parse/AttrLateParsed.inc" + .Default(false); +} + + /// ParseGNUAttributes - Parse a non-empty attributes list. /// /// [GNU] attributes: @@ -91,7 +100,8 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, /// a pressing need to implement the 2 token lookahead. void Parser::ParseGNUAttributes(ParsedAttributes &attrs, - SourceLocation *endLoc) { + SourceLocation *endLoc, + LateParsedAttrList *LateAttrs) { assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); while (Tok.is(tok::kw___attribute)) { @@ -108,7 +118,6 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") )) while (Tok.is(tok::identifier) || isDeclarationSpecifier() || Tok.is(tok::comma)) { - if (Tok.is(tok::comma)) { // allows for empty/non-empty attributes. ((__vector_size__(16),,,,)) ConsumeToken(); @@ -118,112 +127,26 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - // Availability attributes have their own grammar. - if (AttrName->isStr("availability")) - ParseAvailabilityAttribute(*AttrName, AttrNameLoc, attrs, endLoc); - // check if we have a "parameterized" attribute - else if (Tok.is(tok::l_paren)) { - ConsumeParen(); // ignore the left paren loc for now - - if (Tok.is(tok::identifier)) { - IdentifierInfo *ParmName = Tok.getIdentifierInfo(); - SourceLocation ParmLoc = ConsumeToken(); - - if (Tok.is(tok::r_paren)) { - // __attribute__(( mode(byte) )) - ConsumeParen(); // ignore the right paren loc for now - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, - ParmName, ParmLoc, 0, 0); - } else if (Tok.is(tok::comma)) { - ConsumeToken(); - // __attribute__(( format(printf, 1, 2) )) - ExprVector ArgExprs(Actions); - bool ArgExprsOk = true; - - // now parse the non-empty comma separated list of expressions - while (1) { - ExprResult ArgExpr(ParseAssignmentExpression()); - if (ArgExpr.isInvalid()) { - ArgExprsOk = false; - SkipUntil(tok::r_paren); - break; - } else { - ArgExprs.push_back(ArgExpr.release()); - } - if (Tok.isNot(tok::comma)) - break; - ConsumeToken(); // Eat the comma, move to the next argument - } - if (ArgExprsOk && Tok.is(tok::r_paren)) { - ConsumeParen(); // ignore the right paren loc for now - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, - ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size()); - } - } - } else { // not an identifier - switch (Tok.getKind()) { - case tok::r_paren: - // parse a possibly empty comma separated list of expressions - // __attribute__(( nonnull() )) - ConsumeParen(); // ignore the right paren loc for now - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0); - break; - case tok::kw_char: - case tok::kw_wchar_t: - case tok::kw_char16_t: - case tok::kw_char32_t: - case tok::kw_bool: - case tok::kw_short: - case tok::kw_int: - case tok::kw_long: - case tok::kw___int64: - case tok::kw_signed: - case tok::kw_unsigned: - case tok::kw_float: - case tok::kw_double: - case tok::kw_void: - case tok::kw_typeof: { - AttributeList *attr - = attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0); - if (attr->getKind() == AttributeList::AT_IBOutletCollection) - Diag(Tok, diag::err_iboutletcollection_builtintype); - // If it's a builtin type name, eat it and expect a rparen - // __attribute__(( vec_type_hint(char) )) - ConsumeToken(); - if (Tok.is(tok::r_paren)) - ConsumeParen(); - break; - } - default: - // __attribute__(( aligned(16) )) - ExprVector ArgExprs(Actions); - bool ArgExprsOk = true; - - // now parse the list of expressions - while (1) { - ExprResult ArgExpr(ParseAssignmentExpression()); - if (ArgExpr.isInvalid()) { - ArgExprsOk = false; - SkipUntil(tok::r_paren); - break; - } else { - ArgExprs.push_back(ArgExpr.release()); - } - if (Tok.isNot(tok::comma)) - break; - ConsumeToken(); // Eat the comma, move to the next argument - } - // Match the ')'. - if (ArgExprsOk && Tok.is(tok::r_paren)) { - ConsumeParen(); // ignore the right paren loc for now - attrs.addNew(AttrName, AttrNameLoc, 0, - AttrNameLoc, 0, SourceLocation(), - ArgExprs.take(), ArgExprs.size()); - } - break; - } + if (Tok.is(tok::l_paren)) { + // handle "parameterized" attributes + if (LateAttrs && !ClassStack.empty() && + isAttributeLateParsed(*AttrName)) { + // Delayed parsing is only available for attributes that occur + // in certain locations within a class scope. + LateParsedAttribute *LA = + new LateParsedAttribute(this, *AttrName, AttrNameLoc); + LateAttrs->push_back(LA); + getCurrentClass().LateParsedDeclarations.push_back(LA); + + // consume everything up to and including the matching right parens + ConsumeAndStoreUntil(tok::r_paren, LA->Toks, true, false); + + Token Eof; + Eof.startToken(); + Eof.setLocation(Tok.getLocation()); + LA->Toks.push_back(Eof); + } else { + ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc); } } else { attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, @@ -241,6 +164,133 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } } + +/// Parse the arguments to a parameterized GNU attribute +void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + SourceLocation *EndLoc) { + + assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); + + // Availability attributes have their own grammar. + if (AttrName->isStr("availability")) { + ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc); + return; + } + // Thread safety attributes fit into the FIXME case above, so we + // just parse the arguments as a list of expressions + if (IsThreadSafetyAttribute(AttrName->getName())) { + ParseThreadSafetyAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc); + return; + } + + ConsumeParen(); // ignore the left paren loc for now + + if (Tok.is(tok::identifier)) { + IdentifierInfo *ParmName = Tok.getIdentifierInfo(); + SourceLocation ParmLoc = ConsumeToken(); + + if (Tok.is(tok::r_paren)) { + // __attribute__(( mode(byte) )) + SourceLocation RParen = ConsumeParen(); + Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc, + ParmName, ParmLoc, 0, 0); + } else if (Tok.is(tok::comma)) { + ConsumeToken(); + // __attribute__(( format(printf, 1, 2) )) + ExprVector ArgExprs(Actions); + bool ArgExprsOk = true; + + // now parse the non-empty comma separated list of expressions + while (1) { + ExprResult ArgExpr(ParseAssignmentExpression()); + if (ArgExpr.isInvalid()) { + ArgExprsOk = false; + SkipUntil(tok::r_paren); + break; + } else { + ArgExprs.push_back(ArgExpr.release()); + } + if (Tok.isNot(tok::comma)) + break; + ConsumeToken(); // Eat the comma, move to the next argument + } + if (ArgExprsOk && Tok.is(tok::r_paren)) { + SourceLocation RParen = ConsumeParen(); + Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc, + ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size()); + } + } + } else { // not an identifier + switch (Tok.getKind()) { + case tok::r_paren: { + // parse a possibly empty comma separated list of expressions + // __attribute__(( nonnull() )) + SourceLocation RParen = ConsumeParen(); + Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc, + 0, SourceLocation(), 0, 0); + break; + } + case tok::kw_char: + case tok::kw_wchar_t: + case tok::kw_char16_t: + case tok::kw_char32_t: + case tok::kw_bool: + case tok::kw_short: + case tok::kw_int: + case tok::kw_long: + case tok::kw___int64: + case tok::kw_signed: + case tok::kw_unsigned: + case tok::kw_float: + case tok::kw_double: + case tok::kw_void: + case tok::kw_typeof: { + // If it's a builtin type name, eat it and expect a rparen + // __attribute__(( vec_type_hint(char) )) + SourceLocation EndLoc = ConsumeToken(); + if (Tok.is(tok::r_paren)) + EndLoc = ConsumeParen(); + AttributeList *attr + = Attrs.addNew(AttrName, SourceRange(AttrNameLoc, EndLoc), 0, + AttrNameLoc, 0, SourceLocation(), 0, 0); + if (attr->getKind() == AttributeList::AT_IBOutletCollection) + Diag(Tok, diag::err_iboutletcollection_builtintype); + break; + } + default: + // __attribute__(( aligned(16) )) + ExprVector ArgExprs(Actions); + bool ArgExprsOk = true; + + // now parse the list of expressions + while (1) { + ExprResult ArgExpr(ParseAssignmentExpression()); + if (ArgExpr.isInvalid()) { + ArgExprsOk = false; + SkipUntil(tok::r_paren); + break; + } else { + ArgExprs.push_back(ArgExpr.release()); + } + if (Tok.isNot(tok::comma)) + break; + ConsumeToken(); // Eat the comma, move to the next argument + } + // Match the ')'. + if (ArgExprsOk && Tok.is(tok::r_paren)) { + SourceLocation RParen = ConsumeParen(); + Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, + AttrNameLoc, 0, SourceLocation(), + ArgExprs.take(), ArgExprs.size()); + } + break; + } + } +} + + /// ParseMicrosoftDeclSpec - Parse an __declspec construct /// /// [MS] decl-specifier: @@ -297,10 +347,13 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { // FIXME: Allow Sema to distinguish between these and real attributes! while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) || Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) || - Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) { + Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) || + Tok.is(tok::kw___ptr32) || + Tok.is(tok::kw___unaligned)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) + if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) || + Tok.is(tok::kw___ptr32)) // FIXME: Support these properly! continue; attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, @@ -511,12 +564,11 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, AvailabilityChange Changes[Unknown]; // Opening '('. - SourceLocation LParenLoc; - if (!Tok.is(tok::l_paren)) { + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { Diag(Tok, diag::err_expected_lparen); return; } - LParenLoc = ConsumeParen(); // Parse the platform name, if (Tok.isNot(tok::identifier)) { @@ -614,12 +666,11 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, } while (true); // Closing ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - if (RParenLoc.isInvalid()) + if (T.consumeClose()) return; if (endLoc) - *endLoc = RParenLoc; + *endLoc = T.getCloseLocation(); // The 'unavailable' availability cannot be combined with any other // availability changes. Make sure that hasn't happened. @@ -641,7 +692,8 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, } // Record this attribute - attrs.addNew(&Availability, AvailabilityLoc, + attrs.addNew(&Availability, + SourceRange(AvailabilityLoc, T.getCloseLocation()), 0, SourceLocation(), Platform, PlatformLoc, Changes[Introduced], @@ -650,6 +702,172 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, UnavailableLoc, false, false); } + +// Late Parsed Attributes: +// See other examples of late parsing in lib/Parse/ParseCXXInlineMethods + +void Parser::LateParsedDeclaration::ParseLexedAttributes() {} + +void Parser::LateParsedClass::ParseLexedAttributes() { + Self->ParseLexedAttributes(*Class); +} + +void Parser::LateParsedAttribute::ParseLexedAttributes() { + Self->ParseLexedAttribute(*this); +} + +/// Wrapper class which calls ParseLexedAttribute, after setting up the +/// scope appropriately. +void Parser::ParseLexedAttributes(ParsingClass &Class) { + // Deal with templates + // FIXME: Test cases to make sure this does the right thing for templates. + bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; + ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, + HasTemplateScope); + if (HasTemplateScope) + Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); + + // Set or update the scope flags to include Scope::ThisScope. + bool AlreadyHasClassScope = Class.TopLevelClass; + unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope|Scope::ThisScope; + ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope); + ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope); + + for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i) { + Class.LateParsedDeclarations[i]->ParseLexedAttributes(); + } +} + +/// \brief Finish parsing an attribute for which parsing was delayed. +/// This will be called at the end of parsing a class declaration +/// for each LateParsedAttribute. We consume the saved tokens and +/// create an attribute with the arguments filled in. We add this +/// to the Attribute list for the decl. +void Parser::ParseLexedAttribute(LateParsedAttribute &LA) { + // Save the current token position. + SourceLocation OrigLoc = Tok.getLocation(); + + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + LA.Toks.push_back(Tok); + PP.EnterTokenStream(LA.Toks.data(), LA.Toks.size(), true, false); + // Consume the previously pushed token. + ConsumeAnyToken(); + + ParsedAttributes Attrs(AttrFactory); + SourceLocation endLoc; + + // If the Decl is templatized, add template parameters to scope. + bool HasTemplateScope = LA.D && LA.D->isTemplateDecl(); + ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope); + if (HasTemplateScope) + Actions.ActOnReenterTemplateScope(Actions.CurScope, LA.D); + + // If the Decl is on a function, add function parameters to the scope. + bool HasFunctionScope = LA.D && LA.D->isFunctionOrFunctionTemplate(); + ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunctionScope); + if (HasFunctionScope) + Actions.ActOnReenterFunctionContext(Actions.CurScope, LA.D); + + ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc); + + if (HasFunctionScope) { + Actions.ActOnExitFunctionContext(); + FnScope.Exit(); // Pop scope, and remove Decls from IdResolver + } + if (HasTemplateScope) { + TempScope.Exit(); + } + + // Late parsed attributes must be attached to Decls by hand. If the + // LA.D is not set, then this was not done properly. + assert(LA.D && "No decl attached to late parsed attribute"); + Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.D, Attrs); + + if (Tok.getLocation() != OrigLoc) { + // Due to a parsing error, we either went over the cached tokens or + // there are still cached tokens left, so we skip the leftover tokens. + // Since this is an uncommon situation that should be avoided, use the + // expensive isBeforeInTranslationUnit call. + if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), + OrigLoc)) + while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) + ConsumeAnyToken(); + } +} + +/// \brief Wrapper around a case statement checking if AttrName is +/// one of the thread safety attributes +bool Parser::IsThreadSafetyAttribute(llvm::StringRef AttrName){ + return llvm::StringSwitch<bool>(AttrName) + .Case("guarded_by", true) + .Case("guarded_var", true) + .Case("pt_guarded_by", true) + .Case("pt_guarded_var", true) + .Case("lockable", true) + .Case("scoped_lockable", true) + .Case("no_thread_safety_analysis", true) + .Case("acquired_after", true) + .Case("acquired_before", true) + .Case("exclusive_lock_function", true) + .Case("shared_lock_function", true) + .Case("exclusive_trylock_function", true) + .Case("shared_trylock_function", true) + .Case("unlock_function", true) + .Case("lock_returned", true) + .Case("locks_excluded", true) + .Case("exclusive_locks_required", true) + .Case("shared_locks_required", true) + .Default(false); +} + +/// \brief Parse the contents of thread safety attributes. These +/// should always be parsed as an expression list. +/// +/// We need to special case the parsing due to the fact that if the first token +/// of the first argument is an identifier, the main parse loop will store +/// that token as a "parameter" and the rest of +/// the arguments will be added to a list of "arguments". However, +/// subsequent tokens in the first argument are lost. We instead parse each +/// argument as an expression and add all arguments to the list of "arguments". +/// In future, we will take advantage of this special case to also +/// deal with some argument scoping issues here (for example, referring to a +/// function parameter in the attribute on that function). +void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + SourceLocation *EndLoc) { + assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); + + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + + ExprVector ArgExprs(Actions); + bool ArgExprsOk = true; + + // now parse the list of expressions + while (1) { + ExprResult ArgExpr(ParseAssignmentExpression()); + if (ArgExpr.isInvalid()) { + ArgExprsOk = false; + T.consumeClose(); + break; + } else { + ArgExprs.push_back(ArgExpr.release()); + } + if (Tok.isNot(tok::comma)) + break; + ConsumeToken(); // Eat the comma, move to the next argument + } + // Match the ')'. + if (ArgExprsOk && !T.consumeClose()) { + Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(), + ArgExprs.take(), ArgExprs.size()); + } + if (EndLoc) + *EndLoc = T.getCloseLocation(); +} + void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range; @@ -676,6 +894,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs) { ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Must temporarily exit the objective-c container scope for + // parsing c none objective-c decls. + ObjCDeclContextSwitch ObjCDC(*this); Decl *SingleDecl = 0; Decl *OwnedType = 0; @@ -832,7 +1053,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, &ThisDecl, 1); } - llvm::SmallVector<Decl *, 8> DeclsInGroup; + SmallVector<Decl *, 8> DeclsInGroup; Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D); D.complete(FirstDecl); if (FirstDecl) @@ -998,9 +1219,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteInitializer(getCurScope(), ThisDecl); - ConsumeCodeCompletionToken(); - SkipUntil(tok::comma, true, true); - return ThisDecl; + cutOffParsing(); + return 0; } ExprResult Init(ParseInitializer()); @@ -1019,7 +1239,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, } } else if (Tok.is(tok::l_paren)) { // Parse C++ direct initializer: '(' expression-list ')' - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + ExprVector Exprs(Actions); CommaLocsTy CommaLocs; @@ -1037,7 +1259,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, } } else { // Match the ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() && "Unexpected number of commas!"); @@ -1047,9 +1269,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, ExitScope(); } - Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc, + Actions.AddCXXDirectInitializerToDecl(ThisDecl, T.getOpenLocation(), move_arg(Exprs), - RParenLoc, + T.getCloseLocation(), TypeContainsAuto); } } else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { @@ -1090,6 +1312,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS) { /// specifier-qualifier-list is a subset of declaration-specifiers. Just /// parse declaration-specifiers and complain about extra stuff. + /// TODO: diagnose attribute-specifiers and alignment-specifiers. ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS); // Validate declspec for type-name. @@ -1273,12 +1496,70 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { return DSC_normal; } +/// ParseAlignArgument - Parse the argument to an alignment-specifier. +/// +/// FIXME: Simply returns an alignof() expression if the argument is a +/// type. Ideally, the type should be propagated directly into Sema. +/// +/// [C1X/C++0x] type-id +/// [C1X] constant-expression +/// [C++0x] assignment-expression +ExprResult Parser::ParseAlignArgument(SourceLocation Start) { + if (isTypeIdInParens()) { + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + SourceLocation TypeLoc = Tok.getLocation(); + ParsedType Ty = ParseTypeName().get(); + SourceRange TypeRange(Start, Tok.getLocation()); + return Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true, + Ty.getAsOpaquePtr(), TypeRange); + } else + return ParseConstantExpression(); +} + +/// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the +/// attribute to Attrs. +/// +/// alignment-specifier: +/// [C1X] '_Alignas' '(' type-id ')' +/// [C1X] '_Alignas' '(' constant-expression ')' +/// [C++0x] 'alignas' '(' type-id ')' +/// [C++0x] 'alignas' '(' assignment-expression ')' +void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, + SourceLocation *endLoc) { + assert((Tok.is(tok::kw_alignas) || Tok.is(tok::kw__Alignas)) && + "Not an alignment-specifier!"); + + SourceLocation KWLoc = Tok.getLocation(); + ConsumeToken(); + + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) + return; + + ExprResult ArgExpr = ParseAlignArgument(T.getOpenLocation()); + if (ArgExpr.isInvalid()) { + SkipUntil(tok::r_paren); + return; + } + + T.consumeClose(); + if (endLoc) + *endLoc = T.getCloseLocation(); + + ExprVector ArgExprs(Actions); + ArgExprs.push_back(ArgExpr.release()); + Attrs.addNew(PP.getIdentifierInfo("aligned"), KWLoc, 0, KWLoc, + 0, T.getOpenLocation(), ArgExprs.take(), 1, false, true); +} + /// ParseDeclarationSpecifiers /// declaration-specifiers: [C99 6.7] /// storage-class-specifier declaration-specifiers[opt] /// type-specifier declaration-specifiers[opt] /// [C99] function-specifier declaration-specifiers[opt] +/// [C1X] alignment-specifier declaration-specifiers[opt] /// [GNU] attributes declaration-specifiers[opt] +/// [Clang] '__module_private__' declaration-specifiers[opt] /// /// storage-class-specifier: [C99 6.7.1] /// 'typedef' @@ -1316,6 +1597,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, switch (Tok.getKind()) { default: DoneWithDeclSpec: + // [C++0x] decl-specifier-seq: decl-specifier attribute-specifier-seq[opt] + MaybeParseCXX0XAttributes(DS.getAttributes()); + // If this is not a declaration specifier token, we're done reading decl // specifiers. First verify that DeclSpec's are consistent. DS.Finish(Diags, PP); @@ -1337,8 +1621,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, Actions.CodeCompleteDeclSpec(getCurScope(), DS, AllowNonIdentifiers, AllowNestedNameSpecifiers); - ConsumeCodeCompletionToken(); - return; + return cutOffParsing(); } if (getCurScope()->getFnParent() || getCurScope()->getBlockParent()) @@ -1352,8 +1635,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, CCC = Sema::PCC_ObjCImplementation; Actions.CodeCompleteOrdinaryName(getCurScope(), CCC); - ConsumeCodeCompletionToken(); - return; + return cutOffParsing(); } case tok::coloncolon: // ::foo::bar @@ -1641,11 +1923,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; case tok::kw___ptr64: + case tok::kw___ptr32: case tok::kw___w64: case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___unaligned: ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; @@ -1661,49 +1945,47 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // storage-class-specifier case tok::kw_typedef: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc, + PrevSpec, DiagID); break; case tok::kw_extern: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "extern"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc, + PrevSpec, DiagID); break; case tok::kw___private_extern__: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc, - PrevSpec, DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern, + Loc, PrevSpec, DiagID); break; case tok::kw_static: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "static"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc, + PrevSpec, DiagID); break; case tok::kw_auto: if (getLang().CPlusPlus0x) { if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, + PrevSpec, DiagID); if (!isInvalid) - Diag(Tok, diag::auto_storage_class) + Diag(Tok, diag::ext_auto_storage_class) << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); - } - else + } else isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID); - } - else - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, - DiagID, getLang()); + } else + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, + PrevSpec, DiagID); break; case tok::kw_register: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc, + PrevSpec, DiagID); break; case tok::kw_mutable: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec, - DiagID, getLang()); + isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc, + PrevSpec, DiagID); break; case tok::kw___thread: isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID); @@ -1720,6 +2002,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID); break; + // alignment-specifier + case tok::kw__Alignas: + if (!getLang().C1X) + Diag(Tok, diag::ext_c1x_alignas); + ParseAlignmentSpecifier(DS.getAttributes()); + continue; + // friend case tok::kw_friend: if (DSContext == DSC_class) @@ -1731,6 +2020,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } break; + // Modules + case tok::kw___module_private__: + isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID); + break; + // constexpr case tok::kw_constexpr: isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID); @@ -1781,6 +2075,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); break; + case tok::kw_half: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, + DiagID); + break; case tok::kw_float: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); @@ -1890,6 +2188,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___underlying_type: ParseUnderlyingTypeSpecifier(DS); + continue; + + case tok::kw__Atomic: + ParseAtomicSpecifier(DS); + continue; // OpenCL qualifiers: case tok::kw_private: @@ -2004,7 +2307,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, case tok::kw_typename: // typename foo::bar // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. - if (TryAnnotateTypeOrScopeToken()) + if (TryAnnotateTypeOrScopeToken(/*EnteringContext=*/false, + /*NeedType=*/true)) return true; if (Tok.is(tok::identifier)) return false; @@ -2017,7 +2321,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. - if (TryAnnotateTypeOrScopeToken()) + if (TryAnnotateTypeOrScopeToken(/*EnteringContext=*/false, + /*NeedType=*/true)) return true; return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, TemplateInfo, SuppressDeclarations); @@ -2082,6 +2387,9 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, case tok::kw_int: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); break; + case tok::kw_half: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID); + break; case tok::kw_float: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); break; @@ -2166,6 +2474,10 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, ParseUnderlyingTypeSpecifier(DS); return true; + case tok::kw__Atomic: + ParseAtomicSpecifier(DS); + return true; + // OpenCL qualifiers: case tok::kw_private: if (!getLang().OpenCL) @@ -2182,18 +2494,24 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, // C++0x auto support. case tok::kw_auto: - if (!getLang().CPlusPlus0x) + // This is only called in situations where a storage-class specifier is + // illegal, so we can assume an auto type specifier was intended even in + // C++98. In C++98 mode, DeclSpec::Finish will produce an appropriate + // extension diagnostic. + if (!getLang().CPlusPlus) return false; isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID); break; case tok::kw___ptr64: + case tok::kw___ptr32: case tok::kw___w64: case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___unaligned: ParseMicrosoftTypeAttributes(DS.getAttributes()); return true; @@ -2236,6 +2554,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, /// void Parser:: ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { + if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. @@ -2314,7 +2633,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc, "parsing struct/union body"); - SourceLocation LBraceLoc = ConsumeBrace(); + BalancedDelimiterTracker T(*this, tok::l_brace); + if (T.consumeOpen()) + return; ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); @@ -2325,7 +2646,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, Diag(Tok, diag::ext_empty_struct_union) << (TagType == TST_union); - llvm::SmallVector<Decl *, 32> FieldDecls; + SmallVector<Decl *, 32> FieldDecls; // While we still have something to read, read the declarations in the struct. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { @@ -2347,10 +2668,10 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, struct CFieldCallback : FieldCallback { Parser &P; Decl *TagDecl; - llvm::SmallVectorImpl<Decl *> &FieldDecls; + SmallVectorImpl<Decl *> &FieldDecls; CFieldCallback(Parser &P, Decl *TagDecl, - llvm::SmallVectorImpl<Decl *> &FieldDecls) : + SmallVectorImpl<Decl *> &FieldDecls) : P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {} virtual Decl *invoke(FieldDeclarator &FD) { @@ -2378,7 +2699,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, SkipUntil(tok::semi, true); continue; } - llvm::SmallVector<Decl *, 16> Fields; + SmallVector<Decl *, 16> Fields; Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(), Tok.getIdentifierInfo(), Fields); FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end()); @@ -2400,18 +2721,19 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, } } - SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); + T.consumeClose(); ParsedAttributes attrs(AttrFactory); // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs); Actions.ActOnFields(getCurScope(), - RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(), - LBraceLoc, RBraceLoc, + RecordLoc, TagDecl, FieldDecls, + T.getOpenLocation(), T.getCloseLocation(), attrs.getList()); StructScope.Exit(); - Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc); + Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, + T.getCloseLocation()); } /// ParseEnumSpecifier @@ -2448,7 +2770,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (Tok.is(tok::code_completion)) { // Code completion for an enum name. Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } bool IsScopedEnum = false; @@ -2465,7 +2787,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - bool AllowFixedUnderlyingType = getLang().CPlusPlus0x || getLang().Microsoft; + bool AllowFixedUnderlyingType + = getLang().CPlusPlus0x || getLang().MicrosoftExt || getLang().ObjC2; CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLang().CPlusPlus) { @@ -2568,7 +2891,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SourceRange Range; BaseType = ParseTypeName(&Range); - if (!getLang().CPlusPlus0x) + if (!getLang().CPlusPlus0x && !getLang().ObjC2) Diag(StartLoc, diag::ext_ms_enum_fixed_underlying_type) << Range; } @@ -2615,7 +2938,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, unsigned DiagID; Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, attrs.getList(), - AS, + AS, DS.getModulePrivateSpecLoc(), MultiTemplateParamsArg(Actions), Owned, IsDependent, IsScopedEnum, IsScopedUsingClassTag, BaseType); @@ -2681,13 +3004,14 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { ParseScope EnumScope(this, Scope::DeclScope); Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl); - SourceLocation LBraceLoc = ConsumeBrace(); + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); // C does not allow an empty enumerator-list, C++ does [dcl.enum]. if (Tok.is(tok::r_brace) && !getLang().CPlusPlus) Diag(Tok, diag::error_empty_enum); - llvm::SmallVector<Decl *, 32> EnumConstantDecls; + SmallVector<Decl *, 32> EnumConstantDecls; Decl *LastEnumConstDecl = 0; @@ -2738,18 +3062,20 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { } // Eat the }. - SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); + T.consumeClose(); // If attributes exist after the identifier list, parse them. ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl, - EnumConstantDecls.data(), EnumConstantDecls.size(), - getCurScope(), attrs.getList()); + Actions.ActOnEnumBody(StartLoc, T.getOpenLocation(), T.getCloseLocation(), + EnumDecl, EnumConstantDecls.data(), + EnumConstantDecls.size(), getCurScope(), + attrs.getList()); EnumScope.Exit(); - Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, RBraceLoc); + Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, + T.getCloseLocation()); } /// isTypeSpecifierQualifier - Return true if the current token could be the @@ -2797,6 +3123,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_int: + case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw_bool: @@ -2866,6 +3193,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_int: + case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw_bool: @@ -2901,7 +3229,9 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: + case tok::kw___ptr32: case tok::kw___pascal: + case tok::kw___unaligned: case tok::kw___private: case tok::kw___local: @@ -2915,6 +3245,10 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_private: return getLang().OpenCL; + + // C1x _Atomic() + case tok::kw__Atomic: + return true; } } @@ -2976,6 +3310,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_register: case tok::kw___thread: + // Modules + case tok::kw___module_private__: + // type-specifiers case tok::kw_short: case tok::kw_long: @@ -2991,6 +3328,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_char32_t: case tok::kw_int: + case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw_bool: @@ -3031,6 +3369,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_decltype: return true; + // C1x _Atomic() + case tok::kw__Atomic: + return true; + // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'. case tok::less: return getLang().ObjC1; @@ -3047,8 +3389,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: + case tok::kw___ptr32: case tok::kw___forceinline: case tok::kw___pascal: + case tok::kw___unaligned: case tok::kw___private: case tok::kw___local: @@ -3148,8 +3492,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, switch (Tok.getKind()) { case tok::code_completion: Actions.CodeCompleteTypeQualifiers(DS); - ConsumeCodeCompletionToken(); - break; + return cutOffParsing(); case tok::kw_const: isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID, @@ -3180,10 +3523,12 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___w64: case tok::kw___ptr64: + case tok::kw___ptr32: case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___unaligned: if (VendorAttributesAllowed) { ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; @@ -3548,7 +3893,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) { break; } ParsedAttributes attrs(AttrFactory); - ParseFunctionDeclarator(ConsumeParen(), D, attrs); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + ParseFunctionDeclarator(D, attrs, T); } else if (Tok.is(tok::l_square)) { ParseBracketDeclarator(D); } else { @@ -3571,7 +3918,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) { /// parameter-type-list[opt] ')' /// void Parser::ParseParenDeclarator(Declarator &D) { - SourceLocation StartLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + assert(!D.isPastIdentifier() && "Should be called before passing identifier"); // Eat any attributes before we look at whether this is a grouping or function @@ -3596,7 +3945,8 @@ void Parser::ParseParenDeclarator(Declarator &D) { // Eat any Microsoft extensions. if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) || Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) || - Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) { + Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64) || + Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned)) { ParseMicrosoftTypeAttributes(attrs); } // Eat any Borland extensions. @@ -3633,9 +3983,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. - SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc); - D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), - attrs, EndLoc); + T.consumeClose(); + D.AddTypeInfo(DeclaratorChunk::getParen(T.getOpenLocation(), + T.getCloseLocation()), + attrs, T.getCloseLocation()); D.setGroupingParens(hadGroupingParens); return; @@ -3647,7 +3998,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // ParseFunctionDeclarator to handle of argument list. D.SetIdentifier(0, Tok.getLocation()); - ParseFunctionDeclarator(StartLoc, D, attrs, RequiresArg); + ParseFunctionDeclarator(D, attrs, T, RequiresArg); } /// ParseFunctionDeclarator - We are after the identifier and have parsed the @@ -3668,8 +4019,9 @@ void Parser::ParseParenDeclarator(Declarator &D) { /// dynamic-exception-specification /// noexcept-specification /// -void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, +void Parser::ParseFunctionDeclarator(Declarator &D, ParsedAttributes &attrs, + BalancedDelimiterTracker &Tracker, bool RequiresArg) { // lparen is already consumed! assert(D.isPastIdentifier() && "Should not call before identifier!"); @@ -3678,7 +4030,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Otherwise, it is treated as a K&R-style function. bool HasProto = false; // Build up an array of information about the parsed arguments. - llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; + SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; // Remember where we see an ellipsis, if any. SourceLocation EllipsisLoc; @@ -3687,20 +4039,20 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, SourceLocation RefQualifierLoc; ExceptionSpecificationType ESpecType = EST_None; SourceRange ESpecRange; - llvm::SmallVector<ParsedType, 2> DynamicExceptions; - llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; + SmallVector<ParsedType, 2> DynamicExceptions; + SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; ParsedType TrailingReturnType; SourceLocation EndLoc; - if (isFunctionDeclaratorIdentifierList()) { if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); ParseFunctionDeclaratorIdentifierList(D, ParamInfo); - EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + Tracker.consumeClose(); + EndLoc = Tracker.getCloseLocation(); } else { // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. @@ -3715,7 +4067,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, HasProto = ParamInfo.size() || getLang().CPlusPlus; // If we have the closing ')', eat it. - EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + Tracker.consumeClose(); + EndLoc = Tracker.getCloseLocation(); if (getLang().CPlusPlus) { MaybeParseCXX0XAttributes(attrs); @@ -3745,7 +4098,10 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Parse trailing-return-type[opt]. if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { - TrailingReturnType = ParseTrailingReturnType().get(); + SourceRange Range; + TrailingReturnType = ParseTrailingReturnType(Range).get(); + if (Range.getEnd().isValid()) + EndLoc = Range.getEnd(); } } @@ -3768,7 +4124,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, - LParenLoc, EndLoc, D, + Tracker.getOpenLocation(), + EndLoc, D, TrailingReturnType), attrs, EndLoc); } @@ -3811,7 +4168,7 @@ bool Parser::isFunctionDeclaratorIdentifierList() { /// void Parser::ParseFunctionDeclaratorIdentifierList( Declarator &D, - llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo) { + SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo) { // If there was no identifier specified for the declarator, either we are in // an abstract-declarator, or we are in a parameter declarator which was found // to be abstract. In abstract-declarators, identifier lists are not valid: @@ -3890,7 +4247,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList( void Parser::ParseParameterDeclarationClause( Declarator &D, ParsedAttributes &attrs, - llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo, + SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo, SourceLocation &EllipsisLoc) { while (1) { @@ -3902,9 +4259,9 @@ void Parser::ParseParameterDeclarationClause( // Parse the declaration-specifiers. // Just use the ParsingDeclaration "scope" of the declarator. DeclSpec DS(AttrFactory); - + // Skip any Microsoft attributes before a param. - if (getLang().Microsoft && Tok.is(tok::l_square)) + if (getLang().MicrosoftExt && Tok.is(tok::l_square)) ParseMicrosoftAttributes(DS.getAttributes()); SourceLocation DSStart = Tok.getLocation(); @@ -4036,20 +4393,22 @@ void Parser::ParseParameterDeclarationClause( /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']' /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']' void Parser::ParseBracketDeclarator(Declarator &D) { - SourceLocation StartLoc = ConsumeBracket(); + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); // C array syntax has many features, but by-far the most common is [] and [4]. // This code does a fast path to handle some of the most obvious cases. if (Tok.getKind() == tok::r_square) { - SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); + T.consumeClose(); ParsedAttributes attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); // Remember that we parsed the empty array type. ExprResult NumElements; D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, - StartLoc, EndLoc), - attrs, EndLoc); + T.getOpenLocation(), + T.getCloseLocation()), + attrs, T.getCloseLocation()); return; } else if (Tok.getKind() == tok::numeric_constant && GetLookAheadToken(1).is(tok::r_square)) { @@ -4057,15 +4416,16 @@ void Parser::ParseBracketDeclarator(Declarator &D) { ExprResult ExprRes(Actions.ActOnNumericConstant(Tok)); ConsumeToken(); - SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); + T.consumeClose(); ParsedAttributes attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(), - StartLoc, EndLoc), - attrs, EndLoc); + T.getOpenLocation(), + T.getCloseLocation()), + attrs, T.getCloseLocation()); return; } @@ -4122,7 +4482,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { return; } - SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); + T.consumeClose(); ParsedAttributes attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); @@ -4131,8 +4491,9 @@ void Parser::ParseBracketDeclarator(Declarator &D) { D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), isStar, NumElements.release(), - StartLoc, EndLoc), - attrs, EndLoc); + T.getOpenLocation(), + T.getCloseLocation()), + attrs, T.getCloseLocation()); } /// [GNU] typeof-specifier: @@ -4190,6 +4551,41 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { Diag(StartLoc, DiagID) << PrevSpec; } +/// [C1X] atomic-specifier: +/// _Atomic ( type-name ) +/// +void Parser::ParseAtomicSpecifier(DeclSpec &DS) { + assert(Tok.is(tok::kw__Atomic) && "Not an atomic specifier"); + + SourceLocation StartLoc = ConsumeToken(); + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen_after, "_Atomic")) { + SkipUntil(tok::r_paren); + return; + } + + TypeResult Result = ParseTypeName(); + if (Result.isInvalid()) { + SkipUntil(tok::r_paren); + return; + } + + // Match the ')' + T.consumeClose(); + + if (T.getCloseLocation().isInvalid()) + return; + + DS.setTypeofParensRange(T.getRange()); + DS.SetRangeEnd(T.getCloseLocation()); + + const char *PrevSpec = 0; + unsigned DiagID; + if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec, + DiagID, Result.release())) + Diag(StartLoc, DiagID) << PrevSpec; +} + /// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called /// from TryAltiVecVectorToken. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 172049c..4339047 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -52,10 +52,12 @@ Decl *Parser::ParseNamespace(unsigned Context, SourceLocation InlineLoc) { assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. - + ObjCDeclContextSwitch ObjCDC(*this); + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceDecl(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } SourceLocation IdentLoc; @@ -89,12 +91,12 @@ Decl *Parser::ParseNamespace(unsigned Context, if (InlineLoc.isValid()) Diag(InlineLoc, diag::err_inline_namespace_alias) << FixItHint::CreateRemoval(InlineLoc); - return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); } - if (Tok.isNot(tok::l_brace)) { + BalancedDelimiterTracker T(*this, tok::l_brace); + if (T.consumeOpen()) { if (!ExtraIdent.empty()) { Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); @@ -104,8 +106,6 @@ Decl *Parser::ParseNamespace(unsigned Context, return 0; } - SourceLocation LBrace = ConsumeBrace(); - if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() || getCurScope()->getFnParent()) { @@ -113,7 +113,7 @@ Decl *Parser::ParseNamespace(unsigned Context, Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); } - Diag(LBrace, diag::err_namespace_nonnamespace_scope); + Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace, false); return 0; } @@ -156,23 +156,23 @@ Decl *Parser::ParseNamespace(unsigned Context, Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc, - IdentLoc, Ident, LBrace, attrs.getList()); + IdentLoc, Ident, T.getOpenLocation(), + attrs.getList()); PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc, "parsing namespace"); - SourceLocation RBraceLoc; // Parse the contents of the namespace. This includes parsing recovery on // any improperly nested namespaces. ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0, - InlineLoc, LBrace, attrs, RBraceLoc); + InlineLoc, attrs, T); // Leave the namespace scope. NamespaceScope.Exit(); - Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); + DeclEnd = T.getCloseLocation(); + Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd); - DeclEnd = RBraceLoc; return NamespcDecl; } @@ -181,9 +181,8 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, std::vector<IdentifierInfo*>& Ident, std::vector<SourceLocation>& NamespaceLoc, unsigned int index, SourceLocation& InlineLoc, - SourceLocation& LBrace, ParsedAttributes& attrs, - SourceLocation& RBraceLoc) { + BalancedDelimiterTracker &Tracker) { if (index == Ident.size()) { while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); @@ -191,7 +190,10 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, MaybeParseMicrosoftAttributes(attrs); ParseExternalDeclaration(attrs); } - RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace); + + // The caller is what called check -- we are simply calling + // the close for it. + Tracker.consumeClose(); return; } @@ -201,14 +203,15 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index], - Ident[index], LBrace, attrs.getList()); + Ident[index], Tracker.getOpenLocation(), + attrs.getList()); ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc, - LBrace, attrs, RBraceLoc); + attrs, Tracker); NamespaceScope.Exit(); - Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); + Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation()); } /// ParseNamespaceAlias - Parse the part after the '=' in a namespace @@ -224,7 +227,8 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceAliasDecl(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } CXXScopeSpec SS; @@ -262,7 +266,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { assert(Tok.is(tok::string_literal) && "Not a string literal!"); llvm::SmallString<8> LangBuffer; bool Invalid = false; - llvm::StringRef Lang = PP.getSpelling(Tok, LangBuffer, &Invalid); + StringRef Lang = PP.getSpelling(Tok, LangBuffer, &Invalid); if (Invalid) return 0; @@ -296,7 +300,8 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { ProhibitAttributes(attrs); - SourceLocation LBrace = ConsumeBrace(); + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX0XAttributes(attrs); @@ -304,9 +309,9 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { ParseExternalDeclaration(attrs); } - SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); + T.consumeClose(); return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec, - RBrace); + T.getCloseLocation()); } /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or @@ -317,13 +322,15 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, ParsedAttributesWithRange &attrs, Decl **OwnedType) { assert(Tok.is(tok::kw_using) && "Not using token"); - + ObjCDeclContextSwitch ObjCDC(*this); + // Eat 'using'. SourceLocation UsingLoc = ConsumeToken(); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteUsing(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } // 'using namespace' means this is a using-directive. @@ -344,7 +351,7 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, ProhibitAttributes(attrs); return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, - AS_none, OwnedType); + AS_none, OwnedType); } /// ParseUsingDirective - Parse C++ using-directive, assumes @@ -368,7 +375,8 @@ Decl *Parser::ParseUsingDirective(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteUsingDirective(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } CXXScopeSpec SS; @@ -514,7 +522,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? Declarator::AliasTemplateContext : - Declarator::AliasDeclContext, 0, AS, OwnedType); + Declarator::AliasDeclContext, AS, OwnedType); } else // Parse (optional) attributes (most likely GNU strong-using extension). MaybeParseGNUAttributes(attrs); @@ -540,6 +548,15 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } + // "typename" keyword is allowed for identifiers only, + // because it may be a type definition. + if (IsTypeName && Name.getKind() != UnqualifiedId::IK_Identifier) { + Diag(Name.getSourceRange().getBegin(), diag::err_typename_identifiers_only) + << FixItHint::CreateRemoval(SourceRange(TypenameLoc)); + // Proceed parsing, but reset the IsTypeName flag. + IsTypeName = false; + } + if (IsAliasDecl) { TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; MultiTemplateParamsArg TemplateParamsArg(Actions, @@ -571,13 +588,12 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ SourceLocation StaticAssertLoc = ConsumeToken(); - if (Tok.isNot(tok::l_paren)) { + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { Diag(Tok, diag::err_expected_lparen); return 0; } - SourceLocation LParenLoc = ConsumeParen(); - ExprResult AssertExpr(ParseConstantExpression()); if (AssertExpr.isInvalid()) { SkipUntil(tok::semi); @@ -597,7 +613,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ if (AssertMessage.isInvalid()) return 0; - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); DeclEnd = Tok.getLocation(); ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert); @@ -605,7 +621,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr.take(), AssertMessage.take(), - RParenLoc); + T.getCloseLocation()); } /// ParseDecltypeSpecifier - Parse a C++0x decltype specifier. @@ -616,11 +632,9 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) { assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier"); SourceLocation StartLoc = ConsumeToken(); - SourceLocation LParenLoc = Tok.getLocation(); - - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, - "decltype")) { - SkipUntil(tok::r_paren); + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen_after, + "decltype", tok::r_paren)) { return; } @@ -637,13 +651,8 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) { } // Match the ')' - SourceLocation RParenLoc; - if (Tok.is(tok::r_paren)) - RParenLoc = ConsumeParen(); - else - MatchRHSPunctuation(tok::r_paren, LParenLoc); - - if (RParenLoc.isInvalid()) + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return; const char *PrevSpec = 0; @@ -659,11 +668,9 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { "Not an underlying type specifier"); SourceLocation StartLoc = ConsumeToken(); - SourceLocation LParenLoc = Tok.getLocation(); - - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, - "__underlying_type")) { - SkipUntil(tok::r_paren); + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen_after, + "__underlying_type", tok::r_paren)) { return; } @@ -674,13 +681,8 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { } // Match the ')' - SourceLocation RParenLoc; - if (Tok.is(tok::r_paren)) - RParenLoc = ConsumeParen(); - else - MatchRHSPunctuation(tok::r_paren, LParenLoc); - - if (RParenLoc.isInvalid()) + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return; const char *PrevSpec = 0; @@ -851,7 +853,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (Tok.is(tok::code_completion)) { // Code completion for a struct, class, or union name. Actions.CodeCompleteTag(getCurScope(), TagType); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } // C++03 [temp.explicit] 14.7.2/8: @@ -901,7 +903,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Tok.is(tok::kw___is_signed) || Tok.is(tok::kw___is_unsigned) || Tok.is(tok::kw___is_void))) { - // GNU libstdc++ 4.2 and libc++ uaw certain intrinsic names as the + // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the // name of struct templates, but some are keywords in GCC >= 4.3 // and Clang. Therefore, when we see the token sequence "struct // X", make X into a normal identifier rather than a keyword, to @@ -1136,7 +1138,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Build the class template specialization. TagOrTempResult = Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK, - StartLoc, SS, + StartLoc, DS.getModulePrivateSpecLoc(), SS, TemplateId->Template, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, @@ -1188,6 +1190,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Declaration or definition of a class type TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs.getList(), AS, + DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, false, false, clang::TypeResult()); @@ -1264,7 +1267,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, case tok::kw_typedef: // struct foo {...} typedef x; case tok::kw_register: // struct foo {...} register x; case tok::kw_auto: // struct foo {...} auto x; - case tok::kw_mutable: // struct foo {...} mutable x; + case tok::kw_mutable: // struct foo {...} mutable x; + case tok::kw_constexpr: // struct foo {...} constexpr x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, // almost no one actually writes code like this. If we see one of these, @@ -1321,7 +1325,7 @@ void Parser::ParseBaseClause(Decl *ClassDecl) { ConsumeToken(); // Build up an array of parsed base specifiers. - llvm::SmallVector<CXXBaseSpecifier *, 8> BaseInfo; + SmallVector<CXXBaseSpecifier *, 8> BaseInfo; while (true) { // Parse a base-specifier. @@ -1565,7 +1569,6 @@ bool Parser::isCXX0XFinalKeyword() const { /// virt-specifier: /// override /// final -/// new /// /// pure-specifier: /// '= 0' @@ -1574,6 +1577,7 @@ bool Parser::isCXX0XFinalKeyword() const { /// '=' constant-expression /// void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, + AttributeList *AccessAttrs, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { if (Tok.is(tok::at)) { @@ -1640,7 +1644,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, "Nested template improperly parsed?"); SourceLocation DeclEnd; ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd, - AS); + AS, AccessAttrs); return; } @@ -1649,7 +1653,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. ConsumeToken(); - return ParseCXXClassMemberDeclaration(AS, TemplateInfo, TemplateDiags); + return ParseCXXClassMemberDeclaration(AS, AccessAttrs, + TemplateInfo, TemplateDiags); } // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it @@ -1699,7 +1704,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext); VirtSpecifiers VS; - ExprResult Init; + + // Hold late-parsed attributes so we can attach a Decl to them later. + LateParsedAttrList LateParsedAttrs; if (Tok.isNot(tok::colon)) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR. @@ -1719,11 +1726,12 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ParseOptionalCXX0XVirtSpecifierSeq(VS); // If attributes exist after the declarator, but before an '{', parse them. - MaybeParseGNUAttributes(DeclaratorInfo); + MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); // MSVC permits pure specifier on inline functions declared at class scope. // Hence check for =0 before checking for function definition. - if (getLang().Microsoft && Tok.is(tok::equal) && + ExprResult Init; + if (getLang().MicrosoftExt && Tok.is(tok::equal) && DeclaratorInfo.isFunctionDeclarator() && NextToken().is(tok::numeric_constant)) { ConsumeToken(); @@ -1776,7 +1784,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; } - ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init); + Decl *FunDecl = + ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, + VS, Init); + + for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) { + LateParsedAttrs[i]->setDecl(FunDecl); + } + LateParsedAttrs.clear(); // Consume the ';' - it's optional unless we have a delete or default if (Tok.is(tok::semi)) { @@ -1791,7 +1806,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // member-declarator // member-declarator-list ',' member-declarator - llvm::SmallVector<Decl *, 8> DeclsInGroup; + SmallVector<Decl *, 8> DeclsInGroup; ExprResult BitfieldSize; while (1) { @@ -1818,31 +1833,25 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } // If attributes exist after the declarator, parse them. - MaybeParseGNUAttributes(DeclaratorInfo); + MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); // FIXME: When g++ adds support for this, we'll need to check whether it // goes before or after the GNU attributes and __asm__. ParseOptionalCXX0XVirtSpecifierSeq(VS); + bool HasInitializer = false; bool HasDeferredInitializer = false; if (Tok.is(tok::equal) || Tok.is(tok::l_brace)) { if (BitfieldSize.get()) { Diag(Tok, diag::err_bitfield_member_init); SkipUntil(tok::comma, true, true); } else { + HasInitializer = true; HasDeferredInitializer = !DeclaratorInfo.isDeclarationOfFunction() && DeclaratorInfo.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static && DeclaratorInfo.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef; - - if (!HasDeferredInitializer) { - SourceLocation EqualLoc; - Init = ParseCXXMemberInitializer( - DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); - if (Init.isInvalid()) - SkipUntil(tok::comma, true, true); - } } } @@ -1854,32 +1863,30 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (DS.isFriendSpecified()) { // TODO: handle initializers, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, - /*IsDefinition*/ false, move(TemplateParams)); } else { ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, DeclaratorInfo, move(TemplateParams), BitfieldSize.release(), - VS, Init.release(), - HasDeferredInitializer, - /*IsDefinition*/ false); + VS, HasDeferredInitializer); + if (AccessAttrs) + Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs, + false, true); } - if (ThisDecl) - DeclsInGroup.push_back(ThisDecl); - - if (DeclaratorInfo.isFunctionDeclarator() && - DeclaratorInfo.getDeclSpec().getStorageClassSpec() - != DeclSpec::SCS_typedef) { - HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl); + + // Set the Decl for any late parsed attributes + for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) { + LateParsedAttrs[i]->setDecl(ThisDecl); } + LateParsedAttrs.clear(); - DeclaratorInfo.complete(ThisDecl); - + // Handle the initializer. if (HasDeferredInitializer) { + // The initializer was deferred; parse it and cache the tokens. if (!getLang().CPlusPlus0x) Diag(Tok, diag::warn_nonstatic_member_init_accepted_as_extension); - + if (DeclaratorInfo.isArrayOfUnknownBound()) { // C++0x [dcl.array]p3: An array bound may also be omitted when the // declarator is followed by an initializer. @@ -1892,8 +1899,36 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ThisDecl->setInvalidDecl(); } else ParseCXXNonStaticMemberInitializer(ThisDecl); + } else if (HasInitializer) { + // Normal initializer. + SourceLocation EqualLoc; + ExprResult Init + = ParseCXXMemberInitializer(DeclaratorInfo.isDeclarationOfFunction(), + EqualLoc); + if (Init.isInvalid()) + SkipUntil(tok::comma, true, true); + else if (ThisDecl) + Actions.AddInitializerToDecl(ThisDecl, Init.get(), false, + DS.getTypeSpecType() == DeclSpec::TST_auto); + } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) { + // No initializer. + Actions.ActOnUninitializedDecl(ThisDecl, + DS.getTypeSpecType() == DeclSpec::TST_auto); + } + + if (ThisDecl) { + Actions.FinalizeDeclaration(ThisDecl); + DeclsInGroup.push_back(ThisDecl); + } + + if (DeclaratorInfo.isFunctionDeclarator() && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() + != DeclSpec::SCS_typedef) { + HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl); } + DeclaratorInfo.complete(ThisDecl); + // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. if (Tok.isNot(tok::comma)) @@ -1905,8 +1940,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Parse the next declarator. DeclaratorInfo.clear(); VS.clear(); - BitfieldSize = 0; - Init = 0; + BitfieldSize = true; // Attributes are only allowed on the second declarator. MaybeParseGNUAttributes(DeclaratorInfo); @@ -1973,7 +2007,6 @@ ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction, return ExprResult(); } } else if (Tok.is(tok::kw_default)) { - Diag(ConsumeToken(), diag::err_default_special_members); if (IsFunction) Diag(Tok, diag::err_default_delete_in_multiple_declaration) << 0 /* default */; @@ -2067,12 +2100,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } assert(Tok.is(tok::l_brace)); - - SourceLocation LBraceLoc = ConsumeBrace(); + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); if (TagDecl) Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc, - LBraceLoc); + T.getOpenLocation()); // C++ 11p3: Members of a class defined with the keyword class are private // by default. Members of a class defined with the keywords struct or union @@ -2082,14 +2115,14 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, CurAS = AS_private; else CurAS = AS_public; + ParsedAttributes AccessAttrs(AttrFactory); - SourceLocation RBraceLoc; if (TagDecl) { // While we still have something to read, read the member-declarations. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // Each iteration of this loop reads one member-declaration. - if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) || + if (getLang().MicrosoftExt && (Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); continue; @@ -2109,22 +2142,41 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // Current token is a C++ access specifier. CurAS = AS; SourceLocation ASLoc = Tok.getLocation(); + unsigned TokLength = Tok.getLength(); ConsumeToken(); - if (Tok.is(tok::colon)) - Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); - else - Diag(Tok, diag::err_expected_colon); - ConsumeToken(); + AccessAttrs.clear(); + MaybeParseGNUAttributes(AccessAttrs); + + SourceLocation EndLoc; + if (Tok.is(tok::colon)) { + EndLoc = Tok.getLocation(); + if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc, + AccessAttrs.getList())) { + // found another attribute than only annotations + AccessAttrs.clear(); + } + ConsumeToken(); + } else if (Tok.is(tok::semi)) { + EndLoc = Tok.getLocation(); + ConsumeToken(); + Diag(EndLoc, diag::err_expected_colon) + << FixItHint::CreateReplacement(EndLoc, ":"); + } else { + EndLoc = ASLoc.getLocWithOffset(TokLength); + Diag(EndLoc, diag::err_expected_colon) + << FixItHint::CreateInsertion(EndLoc, ":"); + } + Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc); continue; } // FIXME: Make sure we don't have a template here. // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS); + ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList()); } - RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); + T.consumeClose(); } else { SkipUntil(tok::r_brace, false, false); } @@ -2135,7 +2187,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl) Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl, - LBraceLoc, RBraceLoc, + T.getOpenLocation(), + T.getCloseLocation(), attrs.getList()); // C++0x [class.mem]p2: Within the class member-specification, the class is @@ -2148,8 +2201,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl && NonNestedClass) { // We are not inside a nested class. This class and its nested classes // are complete and we can parse the delayed portions of method - // declarations and the lexed inline method definitions. + // declarations and the lexed inline method definitions, along with any + // delayed attributes. SourceLocation SavedPrevTokLocation = PrevTokLocation; + ParseLexedAttributes(getCurrentClass()); ParseLexedMethodDeclarations(getCurrentClass()); ParseLexedMemberInitializers(getCurrentClass()); ParseLexedMethodDefs(getCurrentClass()); @@ -2157,7 +2212,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } if (TagDecl) - Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc); + Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, + T.getCloseLocation()); // Leave the class scope. ParsingDef.Pop(); @@ -2192,7 +2248,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); SourceLocation ColonLoc = ConsumeToken(); - llvm::SmallVector<CXXCtorInitializer*, 4> MemInitializers; + SmallVector<CXXCtorInitializer*, 4> MemInitializers; bool AnyErrors = false; do { @@ -2200,7 +2256,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { Actions.CodeCompleteConstructorInitializer(ConstructorDecl, MemInitializers.data(), MemInitializers.size()); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } else { MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); if (!MemInit.isInvalid()) @@ -2270,11 +2326,20 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // Parse the '('. if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { - // FIXME: Do something with the braced-init-list. - ParseBraceInitializer(); - return true; + ExprResult InitList = ParseBraceInitializer(); + if (InitList.isInvalid()) + return true; + + SourceLocation EllipsisLoc; + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); + + return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, + TemplateTypeTy, IdLoc, InitList.take(), + EllipsisLoc); } else if(Tok.is(tok::l_paren)) { - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); // Parse the optional expression-list. ExprVector ArgExprs(Actions); @@ -2284,7 +2349,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { return true; } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); SourceLocation EllipsisLoc; if (Tok.is(tok::ellipsis)) @@ -2292,8 +2357,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy, IdLoc, - LParenLoc, ArgExprs.take(), - ArgExprs.size(), RParenLoc, + T.getOpenLocation(), ArgExprs.take(), + ArgExprs.size(), T.getCloseLocation(), EllipsisLoc); } @@ -2313,8 +2378,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { /// 'noexcept' '(' constant-expression ')' ExceptionSpecificationType Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, - llvm::SmallVectorImpl<ParsedType> &DynamicExceptions, - llvm::SmallVectorImpl<SourceRange> &DynamicExceptionRanges, + SmallVectorImpl<ParsedType> &DynamicExceptions, + SmallVectorImpl<SourceRange> &DynamicExceptionRanges, ExprResult &NoexceptExpr) { ExceptionSpecificationType Result = EST_None; @@ -2339,7 +2404,8 @@ Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, SourceLocation KeywordLoc = ConsumeToken(); if (Tok.is(tok::l_paren)) { // There is an argument. - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); NoexceptType = EST_ComputedNoexcept; NoexceptExpr = ParseConstantExpression(); // The argument must be contextually convertible to bool. We use @@ -2347,8 +2413,8 @@ Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, if (!NoexceptExpr.isInvalid()) NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc, NoexceptExpr.get()); - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - NoexceptRange = SourceRange(KeywordLoc, RParenLoc); + T.consumeClose(); + NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); } else { // There is no argument. NoexceptType = EST_BasicNoexcept; @@ -2386,27 +2452,26 @@ Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, /// ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( SourceRange &SpecificationRange, - llvm::SmallVectorImpl<ParsedType> &Exceptions, - llvm::SmallVectorImpl<SourceRange> &Ranges) { + SmallVectorImpl<ParsedType> &Exceptions, + SmallVectorImpl<SourceRange> &Ranges) { assert(Tok.is(tok::kw_throw) && "expected throw"); SpecificationRange.setBegin(ConsumeToken()); - - if (!Tok.is(tok::l_paren)) { + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { Diag(Tok, diag::err_expected_lparen_after) << "throw"; SpecificationRange.setEnd(SpecificationRange.getBegin()); return EST_DynamicNone; } - SourceLocation LParenLoc = ConsumeParen(); // Parse throw(...), a Microsoft extension that means "this function // can throw anything". if (Tok.is(tok::ellipsis)) { SourceLocation EllipsisLoc = ConsumeToken(); - if (!getLang().Microsoft) + if (!getLang().MicrosoftExt) Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec); - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - SpecificationRange.setEnd(RParenLoc); + T.consumeClose(); + SpecificationRange.setEnd(T.getCloseLocation()); return EST_MSAny; } @@ -2436,13 +2501,14 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( break; } - SpecificationRange.setEnd(MatchRHSPunctuation(tok::r_paren, LParenLoc)); + T.consumeClose(); + SpecificationRange.setEnd(T.getCloseLocation()); return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic; } /// ParseTrailingReturnType - Parse a trailing return type on a new-style /// function declaration. -TypeResult Parser::ParseTrailingReturnType() { +TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) { assert(Tok.is(tok::arrow) && "expected arrow"); ConsumeToken(); @@ -2454,8 +2520,6 @@ TypeResult Parser::ParseTrailingReturnType() { // // struct X is parsed as class definition because of the trailing // brace. - - SourceRange Range; return ParseTypeName(&Range); } @@ -2519,11 +2583,12 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope(); } -/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier. Currently only -/// parses standard attributes. +/// ParseCXX0XAttributeSpecifier - Parse a C++0x attribute-specifier. Currently +/// only parses standard attributes. /// /// [C++0x] attribute-specifier: /// '[' '[' attribute-list ']' ']' +/// alignment-specifier /// /// [C++0x] attribute-list: /// attribute[opt] @@ -2554,12 +2619,18 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { /// '[' balanced-token-seq ']' /// '{' balanced-token-seq '}' /// any token but '(', ')', '[', ']', '{', or '}' -void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, - SourceLocation *endLoc) { +void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, + SourceLocation *endLoc) { + if (Tok.is(tok::kw_alignas)) { + Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas); + ParseAlignmentSpecifier(attrs, endLoc); + return; + } + assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) && "Not a C++0x attribute list"); - SourceLocation StartLoc = Tok.getLocation(), Loc; + Diag(Tok.getLocation(), diag::warn_cxx98_compat_attribute); ConsumeBracket(); ConsumeBracket(); @@ -2617,29 +2688,6 @@ void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, break; } - // One argument; must be a type-id or assignment-expression - case AttributeList::AT_aligned: { - if (Tok.isNot(tok::l_paren)) { - Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments) - << AttrName->getName(); - break; - } - SourceLocation ParamLoc = ConsumeParen(); - - ExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc); - - MatchRHSPunctuation(tok::r_paren, ParamLoc); - - ExprVector ArgExprs(Actions); - ArgExprs.push_back(ArgExpr.release()); - attrs.addNew(AttrName, AttrLoc, 0, AttrLoc, - 0, ParamLoc, ArgExprs.take(), 1, - false, true); - - AttrParsed = true; - break; - } - // Silence warnings default: break; } @@ -2655,31 +2703,27 @@ void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare)) SkipUntil(tok::r_square, false); - Loc = Tok.getLocation(); + if (endLoc) + *endLoc = Tok.getLocation(); if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare)) SkipUntil(tok::r_square, false); - - attrs.Range = SourceRange(StartLoc, Loc); } -/// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]] -/// attribute. -/// -/// FIXME: Simply returns an alignof() expression if the argument is a -/// type. Ideally, the type should be propagated directly into Sema. -/// -/// [C++0x] 'align' '(' type-id ')' -/// [C++0x] 'align' '(' assignment-expression ')' -ExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) { - if (isTypeIdInParens()) { - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); - SourceLocation TypeLoc = Tok.getLocation(); - ParsedType Ty = ParseTypeName().get(); - SourceRange TypeRange(Start, Tok.getLocation()); - return Actions.ActOnUnaryExprOrTypeTraitExpr(TypeLoc, UETT_AlignOf, true, - Ty.getAsOpaquePtr(), TypeRange); - } else - return ParseConstantExpression(); +/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier-seq. +/// +/// attribute-specifier-seq: +/// attribute-specifier-seq[opt] attribute-specifier +void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, + SourceLocation *endLoc) { + SourceLocation StartLoc = Tok.getLocation(), Loc; + if (!endLoc) + endLoc = &Loc; + + do { + ParseCXX0XAttributeSpecifier(attrs, endLoc); + } while (isCXX0XAttributeSpecifier()); + + attrs.Range = SourceRange(StartLoc, *endLoc); } /// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr] @@ -2753,7 +2797,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, } // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS); + ParseCXXClassMemberDeclaration(CurAS, 0); } if (Tok.isNot(tok::r_brace)) { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index fc64ae0..bc8bbf5 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -214,7 +214,8 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { ExprResult Parser::ParseAssignmentExpression() { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return ExprError(); } if (Tok.is(tok::kw_throw)) @@ -303,23 +304,23 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // Eat the colon. ColonLoc = ConsumeToken(); } else { - // Otherwise, we're missing a ':'. Assume that this was a typo that the - // user forgot. If we're not in a macro instantiation, we can suggest a - // fixit hint. If there were two spaces before the current token, + // Otherwise, we're missing a ':'. Assume that this was a typo that + // the user forgot. If we're not in a macro expansion, we can suggest + // a fixit hint. If there were two spaces before the current token, // suggest inserting the colon in between them, otherwise insert ": ". SourceLocation FILoc = Tok.getLocation(); const char *FIText = ": "; const SourceManager &SM = PP.getSourceManager(); if (FILoc.isFileID() || PP.isAtStartOfMacroExpansion(FILoc)) { - FILoc = SM.getInstantiationLoc(FILoc); + FILoc = SM.getExpansionLoc(FILoc); bool IsInvalid = false; const char *SourcePtr = - SM.getCharacterData(FILoc.getFileLocWithOffset(-1), &IsInvalid); + SM.getCharacterData(FILoc.getLocWithOffset(-1), &IsInvalid); if (!IsInvalid && *SourcePtr == ' ') { SourcePtr = - SM.getCharacterData(FILoc.getFileLocWithOffset(-2), &IsInvalid); + SM.getCharacterData(FILoc.getLocWithOffset(-2), &IsInvalid); if (!IsInvalid && *SourcePtr == ' ') { - FILoc = FILoc.getFileLocWithOffset(-1); + FILoc = FILoc.getLocWithOffset(-1); FIText = ":"; } } @@ -336,7 +337,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // goes through a special hook that takes the left-hand side into account. if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) { Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get()); - ConsumeCodeCompletionToken(); + cutOffParsing(); return ExprError(); } @@ -769,6 +770,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, break; } case tok::char_constant: // constant: character-constant + case tok::wide_char_constant: + case tok::utf16_char_constant: + case tok::utf32_char_constant: Res = Actions.ActOnCharacterConstant(Tok); ConsumeToken(); break; @@ -780,6 +784,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, break; case tok::string_literal: // primary-expression: string-literal case tok::wide_string_literal: + case tok::utf8_string_literal: + case tok::utf16_string_literal: + case tok::utf32_string_literal: Res = ParseStringLiteralExpression(); break; case tok::kw__Generic: // primary-expression: generic-selection [C1X 6.5.1] @@ -913,6 +920,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: + case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw_void: @@ -1021,18 +1029,21 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')' SourceLocation KeyLoc = ConsumeToken(); - SourceLocation LParen = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, - diag::err_expected_lparen_after, "noexcept")) + BalancedDelimiterTracker T(*this, tok::l_paren); + + if (T.expectAndConsume(diag::err_expected_lparen_after, "noexcept")) return ExprError(); // C++ [expr.unary.noexcept]p1: // The noexcept operator determines whether the evaluation of its operand, // which is an unevaluated operand, can throw an exception. EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); ExprResult Result = ParseExpression(); - SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + + T.consumeClose(); + if (!Result.isInvalid()) - Result = Actions.ActOnNoexceptExpr(KeyLoc, LParen, Result.take(), RParen); + Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), + Result.take(), T.getCloseLocation()); return move(Result); } @@ -1104,11 +1115,20 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, break; case tok::code_completion: { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); - ConsumeCodeCompletionToken(); - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); + cutOffParsing(); + return ExprError(); } case tok::l_square: + if (getLang().CPlusPlus0x) { + if (getLang().ObjC1) { + Res = TryParseLambdaExpression(); + if (Res.isInvalid()) + Res = ParseObjCMessageExpression(); + break; + } + Res = ParseLambdaExpression(); + break; + } if (getLang().ObjC1) { Res = ParseObjCMessageExpression(); break; @@ -1154,9 +1174,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { return move(LHS); Actions.CodeCompletePostfixExpression(getCurScope(), LHS); - ConsumeCodeCompletionToken(); - LHS = ExprError(); - break; + cutOffParsing(); + return ExprError(); case tok::identifier: // If we see identifier: after an expression, and we're not already in a @@ -1183,8 +1202,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (getLang().ObjC1 && Tok.isAtStartOfLine() && isSimpleObjCMessageExpression()) return move(LHS); - - Loc = ConsumeBracket(); + + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + Loc = T.getOpenLocation(); ExprResult Idx; if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) Idx = ParseBraceInitializer(); @@ -1200,7 +1221,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = ExprError(); // Match the ']'. - MatchRHSPunctuation(tok::r_square, Loc); + T.consumeClose(); break; } @@ -1212,12 +1233,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { Expr *ExecConfig = 0; + BalancedDelimiterTracker LLLT(*this, tok::lesslessless); + BalancedDelimiterTracker PT(*this, tok::l_paren); + if (OpKind == tok::lesslessless) { ExprVector ExecConfigExprs(Actions); CommaLocsTy ExecConfigCommaLocs; - SourceLocation LLLLoc, GGGLoc; - - LLLLoc = ConsumeToken(); + LLLT.consumeOpen(); if (ParseExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) { LHS = ExprError(); @@ -1225,11 +1247,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (LHS.isInvalid()) { SkipUntil(tok::greatergreatergreater); - } else if (Tok.isNot(tok::greatergreatergreater)) { - MatchRHSPunctuation(tok::greatergreatergreater, LLLLoc); + } else if (LLLT.consumeClose()) { + // There was an error closing the brackets LHS = ExprError(); - } else { - GGGLoc = ConsumeToken(); } if (!LHS.isInvalid()) { @@ -1241,14 +1261,17 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (!LHS.isInvalid()) { ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(), - LLLLoc, move_arg(ExecConfigExprs), GGGLoc); + LLLT.getOpenLocation(), + move_arg(ExecConfigExprs), + LLLT.getCloseLocation()); if (ECResult.isInvalid()) LHS = ExprError(); else ExecConfig = ECResult.get(); } } else { - Loc = ConsumeParen(); + PT.consumeOpen(); + Loc = PT.getOpenLocation(); } ExprVector ArgExprs(Actions); @@ -1256,7 +1279,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCall(getCurScope(), LHS.get(), 0, 0); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return ExprError(); } if (OpKind == tok::l_paren || !LHS.isInvalid()) { @@ -1272,7 +1296,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (LHS.isInvalid()) { SkipUntil(tok::r_paren); } else if (Tok.isNot(tok::r_paren)) { - MatchRHSPunctuation(tok::r_paren, Loc); + PT.consumeClose(); LHS = ExprError(); } else { assert((ArgExprs.size() == 0 || @@ -1281,7 +1305,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc, move_arg(ArgExprs), Tok.getLocation(), ExecConfig); - ConsumeParen(); + PT.consumeClose(); } break; @@ -1314,7 +1338,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { Actions.CodeCompleteMemberReferenceExpr(getCurScope(), LHS.get(), OpLoc, OpKind == tok::arrow); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return ExprError(); } if (MayBePseudoDestructor && !LHS.isInvalid()) { @@ -1334,7 +1359,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (ParseUnqualifiedId(SS, /*EnteringContext=*/false, /*AllowDestructorName=*/true, - /*AllowConstructorName=*/ getLang().Microsoft, + /*AllowConstructorName=*/ getLang().MicrosoftExt, ObjectType, Name)) LHS = ExprError(); @@ -1473,11 +1498,14 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { IdentifierInfo *Name = 0; SourceLocation NameLoc; if (Tok.is(tok::l_paren)) { - LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + LParenLoc = T.getOpenLocation(); if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); - RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); + RParenLoc = T.getCloseLocation(); if (RParenLoc.isInvalid()) RParenLoc = PP.getLocForEndOfToken(NameLoc); } else { @@ -1564,11 +1592,13 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { return ExprError(Diag(Tok, diag::err_expected_lparen_after_id) << BuiltinII); - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker PT(*this, tok::l_paren); + PT.consumeOpen(); + // TODO: Build AST. switch (T) { - default: assert(0 && "Not a builtin primary expression!"); + default: llvm_unreachable("Not a builtin primary expression!"); case tok::kw___builtin_va_arg: { ExprResult Expr(ParseAssignmentExpression()); @@ -1607,7 +1637,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { } // Keep track of the various subcomponents we see. - llvm::SmallVector<Sema::OffsetOfComponent, 4> Comps; + SmallVector<Sema::OffsetOfComponent, 4> Comps; Comps.push_back(Sema::OffsetOfComponent()); Comps.back().isBrackets = false; @@ -1634,7 +1664,9 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { // offsetof-member-designator: offsetof-member-design '[' expression ']' Comps.push_back(Sema::OffsetOfComponent()); Comps.back().isBrackets = true; - Comps.back().LocStart = ConsumeBracket(); + BalancedDelimiterTracker ST(*this, tok::l_square); + ST.consumeOpen(); + Comps.back().LocStart = ST.getOpenLocation(); Res = ParseExpression(); if (Res.isInvalid()) { SkipUntil(tok::r_paren); @@ -1642,18 +1674,19 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { } Comps.back().U.E = Res.release(); - Comps.back().LocEnd = - MatchRHSPunctuation(tok::r_square, Comps.back().LocStart); + ST.consumeClose(); + Comps.back().LocEnd = ST.getCloseLocation(); } else { if (Tok.isNot(tok::r_paren)) { - MatchRHSPunctuation(tok::r_paren, LParenLoc); + PT.consumeClose(); Res = ExprError(); } else if (Ty.isInvalid()) { Res = ExprError(); } else { + PT.consumeClose(); Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc, - Ty.get(), &Comps[0], - Comps.size(), ConsumeParen()); + Ty.get(), &Comps[0], Comps.size(), + PT.getCloseLocation()); } break; } @@ -1753,7 +1786,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, SourceLocation &RParenLoc) { assert(Tok.is(tok::l_paren) && "Not a paren expr!"); GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); - SourceLocation OpenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) + return ExprError(); + SourceLocation OpenLoc = T.getOpenLocation(); + ExprResult Result(true); bool isAmbiguousTypeId; CastTy = ParsedType(); @@ -1762,7 +1799,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Actions.CodeCompleteOrdinaryName(getCurScope(), ExprType >= CompoundLiteral? Sema::PCC_ParenthesizedExpression : Sema::PCC_Expression); - ConsumeCodeCompletionToken(); + cutOffParsing(); return ExprError(); } @@ -1806,7 +1843,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, } TypeResult Ty = ParseTypeName(); - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, OpenLoc); + T.consumeClose(); + RParenLoc = T.getCloseLocation(); ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false); if (Ty.isInvalid() || SubExpr.isInvalid()) @@ -1825,9 +1863,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // in which case we should treat it as type-id. // if stopIfCastExpr is false, we need to determine the context past the // parens, so we defer to ParseCXXAmbiguousParenExpression for that. - if (isAmbiguousTypeId && !stopIfCastExpr) - return ParseCXXAmbiguousParenExpression(ExprType, CastTy, - OpenLoc, RParenLoc); + if (isAmbiguousTypeId && !stopIfCastExpr) { + ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T); + RParenLoc = T.getCloseLocation(); + return res; + } // Parse the type declarator. DeclSpec DS(AttrFactory); @@ -1851,11 +1891,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Ty.get(), 0); } else { // Match the ')'. - if (Tok.is(tok::r_paren)) - RParenLoc = ConsumeParen(); - else - MatchRHSPunctuation(tok::r_paren, OpenLoc); - + T.consumeClose(); + RParenLoc = T.getCloseLocation(); if (Tok.is(tok::l_brace)) { ExprType = CompoundLiteral; TypeResult Ty; @@ -1939,11 +1976,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, return ExprError(); } - if (Tok.is(tok::r_paren)) - RParenLoc = ConsumeParen(); - else - MatchRHSPunctuation(tok::r_paren, OpenLoc); - + T.consumeClose(); + RParenLoc = T.getCloseLocation(); return move(Result); } @@ -1978,7 +2012,7 @@ ExprResult Parser::ParseStringLiteralExpression() { // String concat. Note that keywords like __func__ and __FUNCTION__ are not // considered to be strings for concatenation purposes. - llvm::SmallVector<Token, 4> StringToks; + SmallVector<Token, 4> StringToks; do { StringToks.push_back(Tok); @@ -2007,8 +2041,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { if (!getLang().C1X) Diag(KeyLoc, diag::ext_c1x_generic_selection); - SourceLocation LParenLoc = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, "")) + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) return ExprError(); ExprResult ControllingExpr; @@ -2074,11 +2108,12 @@ ExprResult Parser::ParseGenericSelectionExpression() { ConsumeToken(); } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - if (RParenLoc.isInvalid()) + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return ExprError(); - return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, + T.getCloseLocation(), ControllingExpr.release(), move_arg(Types), move_arg(Exprs)); } @@ -2104,8 +2139,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { /// [C++0x] assignment-expression /// [C++0x] braced-init-list /// -bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, - llvm::SmallVectorImpl<SourceLocation> &CommaLocs, +bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, + SmallVectorImpl<SourceLocation> &CommaLocs, void (Sema::*Completer)(Scope *S, Expr *Data, Expr **Args, @@ -2117,7 +2152,8 @@ bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, (Actions.*Completer)(getCurScope(), Data, Exprs.data(), Exprs.size()); else Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return true; } ExprResult Expr; @@ -2148,7 +2184,7 @@ bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, void Parser::ParseBlockId() { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } // Parse the specifier-qualifier-list piece. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index b32eeda..60166e8 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -15,6 +15,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" #include "llvm/Support/ErrorHandling.h" @@ -28,8 +29,7 @@ static int SelectDigraphErrorMessage(tok::TokenKind Kind) { case tok::kw_reinterpret_cast: return 3; case tok::kw_static_cast: return 4; default: - assert(0 && "Unknown type for digraph error message."); - return -1; + llvm_unreachable("Unknown type for digraph error message."); } } @@ -37,7 +37,7 @@ static int SelectDigraphErrorMessage(tok::TokenKind Kind) { static bool AreTokensAdjacent(Preprocessor &PP, Token &First, Token &Second) { SourceManager &SM = PP.getSourceManager(); SourceLocation FirstLoc = SM.getSpellingLoc(First.getLocation()); - SourceLocation FirstEnd = FirstLoc.getFileLocWithOffset(First.getLength()); + SourceLocation FirstEnd = FirstLoc.getLocWithOffset(First.getLength()); return FirstEnd == SM.getSpellingLoc(Second.getLocation()); } @@ -58,7 +58,7 @@ static void FixDigraph(Parser &P, Preprocessor &PP, Token &DigraphToken, // Update token information to reflect their change in token type. ColonToken.setKind(tok::coloncolon); - ColonToken.setLocation(ColonToken.getLocation().getFileLocWithOffset(-1)); + ColonToken.setLocation(ColonToken.getLocation().getLocWithOffset(-1)); ColonToken.setLength(2); DigraphToken.setKind(tok::less); DigraphToken.setLength(1); @@ -69,6 +69,31 @@ static void FixDigraph(Parser &P, Preprocessor &PP, Token &DigraphToken, PP.EnterToken(DigraphToken); } +// Check for '<::' which should be '< ::' instead of '[:' when following +// a template name. +void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, + bool EnteringContext, + IdentifierInfo &II, CXXScopeSpec &SS) { + if (!Next.is(tok::l_square) || Next.getLength() != 2) + return; + + Token SecondToken = GetLookAheadToken(2); + if (!SecondToken.is(tok::colon) || !AreTokensAdjacent(PP, Next, SecondToken)) + return; + + TemplateTy Template; + UnqualifiedId TemplateName; + TemplateName.setIdentifier(&II, Tok.getLocation()); + bool MemberOfUnknownSpecialization; + if (!Actions.isTemplateName(getCurScope(), SS, /*hasTemplateKeyword=*/false, + TemplateName, ObjectType, EnteringContext, + Template, MemberOfUnknownSpecialization)) + return; + + FixDigraph(*this, PP, Next, SecondToken, tok::kw_template, + /*AtDigraph*/false); +} + /// \brief Parse global scope or nested-name-specifier if present. /// /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which @@ -161,12 +186,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Code completion for a nested-name-specifier, where the code // code completion token follows the '::'. Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext); - SourceLocation ccLoc = ConsumeCodeCompletionToken(); // Include code completion token into the range of the scope otherwise // when we try to annotate the scope tokens the dangling code completion // token will cause assertion in // Preprocessor::AnnotatePreviousCachedTokens. - SS.setEndLoc(ccLoc); + SS.setEndLoc(Tok.getLocation()); + cutOffParsing(); + return true; } } @@ -339,28 +365,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, continue; } - // Check for '<::' which should be '< ::' instead of '[:' when following - // a template name. - if (Next.is(tok::l_square) && Next.getLength() == 2) { - Token SecondToken = GetLookAheadToken(2); - if (SecondToken.is(tok::colon) && - AreTokensAdjacent(PP, Next, SecondToken)) { - TemplateTy Template; - UnqualifiedId TemplateName; - TemplateName.setIdentifier(&II, Tok.getLocation()); - bool MemberOfUnknownSpecialization; - if (Actions.isTemplateName(getCurScope(), SS, - /*hasTemplateKeyword=*/false, - TemplateName, - ObjectType, - EnteringContext, - Template, - MemberOfUnknownSpecialization)) { - FixDigraph(*this, PP, Next, SecondToken, tok::kw_template, - /*AtDigraph*/false); - } - } - } + CheckForTemplateAndDigraph(Next, ObjectType, EnteringContext, II, SS); // nested-name-specifier: // type-name '<' @@ -396,7 +401,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // parse correctly as a template, so suggest the keyword 'template' // before 'getAs' and treat this as a dependent template name. unsigned DiagID = diag::err_missing_dependent_template_keyword; - if (getLang().Microsoft) + if (getLang().MicrosoftExt) DiagID = diag::warn_missing_dependent_template_keyword; Diag(Tok.getLocation(), DiagID) @@ -504,6 +509,273 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { } +/// ParseLambdaExpression - Parse a C++0x lambda expression. +/// +/// lambda-expression: +/// lambda-introducer lambda-declarator[opt] compound-statement +/// +/// lambda-introducer: +/// '[' lambda-capture[opt] ']' +/// +/// lambda-capture: +/// capture-default +/// capture-list +/// capture-default ',' capture-list +/// +/// capture-default: +/// '&' +/// '=' +/// +/// capture-list: +/// capture +/// capture-list ',' capture +/// +/// capture: +/// identifier +/// '&' identifier +/// 'this' +/// +/// lambda-declarator: +/// '(' parameter-declaration-clause ')' attribute-specifier[opt] +/// 'mutable'[opt] exception-specification[opt] +/// trailing-return-type[opt] +/// +ExprResult Parser::ParseLambdaExpression() { + // Parse lambda-introducer. + LambdaIntroducer Intro; + + llvm::Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro)); + if (DiagID) { + Diag(Tok, DiagID.getValue()); + SkipUntil(tok::r_square); + } + + return ParseLambdaExpressionAfterIntroducer(Intro); +} + +/// TryParseLambdaExpression - Use lookahead and potentially tentative +/// parsing to determine if we are looking at a C++0x lambda expression, and parse +/// it if we are. +/// +/// If we are not looking at a lambda expression, returns ExprError(). +ExprResult Parser::TryParseLambdaExpression() { + assert(getLang().CPlusPlus0x + && Tok.is(tok::l_square) + && "Not at the start of a possible lambda expression."); + + const Token Next = NextToken(), After = GetLookAheadToken(2); + + // If lookahead indicates this is a lambda... + if (Next.is(tok::r_square) || // [] + Next.is(tok::equal) || // [= + (Next.is(tok::amp) && // [&] or [&, + (After.is(tok::r_square) || + After.is(tok::comma))) || + (Next.is(tok::identifier) && // [identifier] + After.is(tok::r_square))) { + return ParseLambdaExpression(); + } + + // If lookahead indicates this is an Objective-C message... + if (Next.is(tok::identifier) && After.is(tok::identifier)) { + return ExprError(); + } + + LambdaIntroducer Intro; + if (TryParseLambdaIntroducer(Intro)) + return ExprError(); + return ParseLambdaExpressionAfterIntroducer(Intro); +} + +/// ParseLambdaExpression - Parse a lambda introducer. +/// +/// Returns a DiagnosticID if it hit something unexpected. +llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro) { + typedef llvm::Optional<unsigned> DiagResult; + + assert(Tok.is(tok::l_square) && "Lambda expressions begin with '['."); + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + + Intro.Range.setBegin(T.getOpenLocation()); + + bool first = true; + + // Parse capture-default. + if (Tok.is(tok::amp) && + (NextToken().is(tok::comma) || NextToken().is(tok::r_square))) { + Intro.Default = LCD_ByRef; + ConsumeToken(); + first = false; + } else if (Tok.is(tok::equal)) { + Intro.Default = LCD_ByCopy; + ConsumeToken(); + first = false; + } + + while (Tok.isNot(tok::r_square)) { + if (!first) { + if (Tok.isNot(tok::comma)) + return DiagResult(diag::err_expected_comma_or_rsquare); + ConsumeToken(); + } + + first = false; + + // Parse capture. + LambdaCaptureKind Kind = LCK_ByCopy; + SourceLocation Loc; + IdentifierInfo* Id = 0; + + if (Tok.is(tok::kw_this)) { + Kind = LCK_This; + Loc = ConsumeToken(); + } else { + if (Tok.is(tok::amp)) { + Kind = LCK_ByRef; + ConsumeToken(); + } + + if (Tok.is(tok::identifier)) { + Id = Tok.getIdentifierInfo(); + Loc = ConsumeToken(); + } else if (Tok.is(tok::kw_this)) { + // FIXME: If we want to suggest a fixit here, will need to return more + // than just DiagnosticID. Perhaps full DiagnosticBuilder that can be + // Clear()ed to prevent emission in case of tentative parsing? + return DiagResult(diag::err_this_captured_by_reference); + } else { + return DiagResult(diag::err_expected_capture); + } + } + + Intro.addCapture(Kind, Loc, Id); + } + + T.consumeClose(); + Intro.Range.setEnd(T.getCloseLocation()); + + return DiagResult(); +} + +/// TryParseLambdaExpression - Tentatively parse a lambda introducer. +/// +/// Returns true if it hit something unexpected. +bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) { + TentativeParsingAction PA(*this); + + llvm::Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro)); + + if (DiagID) { + PA.Revert(); + return true; + } + + PA.Commit(); + return false; +} + +/// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda +/// expression. +ExprResult Parser::ParseLambdaExpressionAfterIntroducer( + LambdaIntroducer &Intro) { + // Parse lambda-declarator[opt]. + DeclSpec DS(AttrFactory); + Declarator D(DS, Declarator::PrototypeContext); + + if (Tok.is(tok::l_paren)) { + ParseScope PrototypeScope(this, + Scope::FunctionPrototypeScope | + Scope::DeclScope); + + SourceLocation DeclLoc, DeclEndLoc; + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + DeclLoc = T.getOpenLocation(); + + // Parse parameter-declaration-clause. + ParsedAttributes Attr(AttrFactory); + llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; + SourceLocation EllipsisLoc; + + if (Tok.isNot(tok::r_paren)) + ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc); + + T.consumeClose(); + DeclEndLoc = T.getCloseLocation(); + + // Parse 'mutable'[opt]. + SourceLocation MutableLoc; + if (Tok.is(tok::kw_mutable)) { + MutableLoc = ConsumeToken(); + DeclEndLoc = MutableLoc; + } + + // Parse exception-specification[opt]. + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + llvm::SmallVector<ParsedType, 2> DynamicExceptions; + llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; + ExprResult NoexceptExpr; + ESpecType = MaybeParseExceptionSpecification(ESpecRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr); + + if (ESpecType != EST_None) + DeclEndLoc = ESpecRange.getEnd(); + + // Parse attribute-specifier[opt]. + MaybeParseCXX0XAttributes(Attr, &DeclEndLoc); + + // Parse trailing-return-type[opt]. + ParsedType TrailingReturnType; + if (Tok.is(tok::arrow)) { + SourceRange Range; + TrailingReturnType = ParseTrailingReturnType(Range).get(); + if (Range.getEnd().isValid()) + DeclEndLoc = Range.getEnd(); + } + + PrototypeScope.Exit(); + + D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, + /*isVariadic=*/EllipsisLoc.isValid(), + EllipsisLoc, + ParamInfo.data(), ParamInfo.size(), + DS.getTypeQualifiers(), + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/SourceLocation(), + MutableLoc, + ESpecType, ESpecRange.getBegin(), + DynamicExceptions.data(), + DynamicExceptionRanges.data(), + DynamicExceptions.size(), + NoexceptExpr.isUsable() ? + NoexceptExpr.get() : 0, + DeclLoc, DeclEndLoc, D, + TrailingReturnType), + Attr, DeclEndLoc); + } + + // Parse compound-statement. + if (Tok.is(tok::l_brace)) { + // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using + // it. + ParseScope BodyScope(this, Scope::BlockScope | Scope::FnScope | + Scope::BreakScope | Scope::ContinueScope | + Scope::DeclScope); + + StmtResult Stmt(ParseCompoundStatementBody()); + + BodyScope.Exit(); + } else { + Diag(Tok, diag::err_expected_lambda_body); + } + + return ExprEmpty(); +} + /// ParseCXXCasts - This handles the various ways to cast expressions to another /// type. /// @@ -518,7 +790,7 @@ ExprResult Parser::ParseCXXCasts() { const char *CastName = 0; // For error messages switch (Kind) { - default: assert(0 && "Unknown C++ cast!"); abort(); + default: llvm_unreachable("Unknown C++ cast!"); case tok::kw_const_cast: CastName = "const_cast"; break; case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break; case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; @@ -551,21 +823,23 @@ ExprResult Parser::ParseCXXCasts() { if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); - SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; + SourceLocation LParenLoc, RParenLoc; + BalancedDelimiterTracker T(*this, tok::l_paren); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName)) + if (T.expectAndConsume(diag::err_expected_lparen_after, CastName)) return ExprError(); ExprResult Result = ParseExpression(); // Match the ')'. - RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); if (!Result.isInvalid() && !DeclaratorInfo.isInvalidType()) Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, LAngleBracketLoc, DeclaratorInfo, RAngleBracketLoc, - LParenLoc, Result.take(), RParenLoc); + T.getOpenLocation(), Result.take(), + T.getCloseLocation()); return move(Result); } @@ -580,13 +854,13 @@ ExprResult Parser::ParseCXXTypeid() { assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!"); SourceLocation OpLoc = ConsumeToken(); - SourceLocation LParenLoc = Tok.getLocation(); - SourceLocation RParenLoc; + SourceLocation LParenLoc, RParenLoc; + BalancedDelimiterTracker T(*this, tok::l_paren); // typeid expressions are always parenthesized. - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, - "typeid")) + if (T.expectAndConsume(diag::err_expected_lparen_after, "typeid")) return ExprError(); + LParenLoc = T.getOpenLocation(); ExprResult Result; @@ -594,8 +868,8 @@ ExprResult Parser::ParseCXXTypeid() { TypeResult Ty = ParseTypeName(); // Match the ')'. - RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - + T.consumeClose(); + RParenLoc = T.getCloseLocation(); if (Ty.isInvalid() || RParenLoc.isInvalid()) return ExprError(); @@ -618,18 +892,11 @@ ExprResult Parser::ParseCXXTypeid() { if (Result.isInvalid()) SkipUntil(tok::r_paren); else { - RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); + RParenLoc = T.getCloseLocation(); if (RParenLoc.isInvalid()) return ExprError(); - // If we are a foo<int> that identifies a single function, resolve it now... - Expr* e = Result.get(); - if (e->getType() == Actions.Context.OverloadTy) { - ExprResult er = - Actions.ResolveAndFixSingleFunctionTemplateSpecialization(e); - if (er.isUsable()) - Result = er.release(); - } Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, Result.release(), RParenLoc); } @@ -647,12 +914,10 @@ ExprResult Parser::ParseCXXUuidof() { assert(Tok.is(tok::kw___uuidof) && "Not '__uuidof'!"); SourceLocation OpLoc = ConsumeToken(); - SourceLocation LParenLoc = Tok.getLocation(); - SourceLocation RParenLoc; + BalancedDelimiterTracker T(*this, tok::l_paren); // __uuidof expressions are always parenthesized. - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, - "__uuidof")) + if (T.expectAndConsume(diag::err_expected_lparen_after, "__uuidof")) return ExprError(); ExprResult Result; @@ -661,13 +926,14 @@ ExprResult Parser::ParseCXXUuidof() { TypeResult Ty = ParseTypeName(); // Match the ')'. - RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); if (Ty.isInvalid()) return ExprError(); - Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/true, - Ty.get().getAsOpaquePtr(), RParenLoc); + Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(), /*isType=*/true, + Ty.get().getAsOpaquePtr(), + T.getCloseLocation()); } else { EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); Result = ParseExpression(); @@ -676,10 +942,11 @@ ExprResult Parser::ParseCXXUuidof() { if (Result.isInvalid()) SkipUntil(tok::r_paren); else { - RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); - Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/false, - Result.release(), RParenLoc); + Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(), + /*isType=*/false, + Result.release(), T.getCloseLocation()); } } @@ -836,7 +1103,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { } else { GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); ExprVector Exprs(Actions); CommaLocsTy CommaLocs; @@ -849,7 +1117,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { } // Match the ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); // TypeRep could be null, if it references an invalid typedef. if (!TypeRep) @@ -857,8 +1125,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); - return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs), - RParenLoc); + return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(), + move_arg(Exprs), + T.getCloseLocation()); } } @@ -889,7 +1158,8 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, bool ConvertToBoolean) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return true; } if (!isCXXConditionDeclaration()) { @@ -969,6 +1239,7 @@ bool Parser::isCXXSimpleTypeSpecifier() const { case tok::kw_void: case tok::kw_char: case tok::kw_int: + case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw_wchar_t: @@ -1022,10 +1293,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { switch (Tok.getKind()) { case tok::identifier: // foo::bar case tok::coloncolon: // ::foo::bar - assert(0 && "Annotation token should already be formed!"); + llvm_unreachable("Annotation token should already be formed!"); default: - assert(0 && "Not a simple-type-specifier token!"); - abort(); + llvm_unreachable("Not a simple-type-specifier token!"); // type-name case tok::annot_typename: { @@ -1074,6 +1344,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw_int: DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); break; + case tok::kw_half: + DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID); + break; case tok::kw_float: DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); break; @@ -1394,16 +1667,15 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Consume the 'new' or 'delete'. SymbolLocations[SymbolIdx++] = ConsumeToken(); if (Tok.is(tok::l_square)) { - // Consume the '['. - SourceLocation LBracketLoc = ConsumeBracket(); - // Consume the ']'. - SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square, - LBracketLoc); - if (RBracketLoc.isInvalid()) + // Consume the '[' and ']'. + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return true; - SymbolLocations[SymbolIdx++] = LBracketLoc; - SymbolLocations[SymbolIdx++] = RBracketLoc; + SymbolLocations[SymbolIdx++] = T.getOpenLocation(); + SymbolLocations[SymbolIdx++] = T.getCloseLocation(); Op = isNew? OO_Array_New : OO_Array_Delete; } else { Op = isNew? OO_New : OO_Delete; @@ -1420,31 +1692,29 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, #include "clang/Basic/OperatorKinds.def" case tok::l_paren: { - // Consume the '('. - SourceLocation LParenLoc = ConsumeParen(); - // Consume the ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, - LParenLoc); - if (RParenLoc.isInvalid()) + // Consume the '(' and ')'. + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return true; - SymbolLocations[SymbolIdx++] = LParenLoc; - SymbolLocations[SymbolIdx++] = RParenLoc; + SymbolLocations[SymbolIdx++] = T.getOpenLocation(); + SymbolLocations[SymbolIdx++] = T.getCloseLocation(); Op = OO_Call; break; } case tok::l_square: { - // Consume the '['. - SourceLocation LBracketLoc = ConsumeBracket(); - // Consume the ']'. - SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square, - LBracketLoc); - if (RBracketLoc.isInvalid()) + // Consume the '[' and ']'. + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return true; - SymbolLocations[SymbolIdx++] = LBracketLoc; - SymbolLocations[SymbolIdx++] = RBracketLoc; + SymbolLocations[SymbolIdx++] = T.getOpenLocation(); + SymbolLocations[SymbolIdx++] = T.getCloseLocation(); Op = OO_Subscript; break; } @@ -1452,10 +1722,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, case tok::code_completion: { // Code completion for the operator name. Actions.CodeCompleteOperatorName(getCurScope()); - - // Consume the operator token. - ConsumeCodeCompletionToken(); - + cutOffParsing(); // Don't try to parse any further. return true; } @@ -1758,13 +2025,16 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { Declarator DeclaratorInfo(DS, Declarator::CXXNewContext); if (Tok.is(tok::l_paren)) { // If it turns out to be a placement, we change the type location. - PlacementLParen = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + PlacementLParen = T.getOpenLocation(); if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) { SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); return ExprError(); } - PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen); + T.consumeClose(); + PlacementRParen = T.getCloseLocation(); if (PlacementRParen.isInvalid()) { SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); return ExprError(); @@ -1772,18 +2042,19 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { if (PlacementArgs.empty()) { // Reset the placement locations. There was no placement. - TypeIdParens = SourceRange(PlacementLParen, PlacementRParen); + TypeIdParens = T.getRange(); PlacementLParen = PlacementRParen = SourceLocation(); } else { // We still need the type. if (Tok.is(tok::l_paren)) { - TypeIdParens.setBegin(ConsumeParen()); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); MaybeParseGNUAttributes(DeclaratorInfo); ParseSpecifierQualifierList(DS); DeclaratorInfo.SetSourceRange(DS.getSourceRange()); ParseDeclarator(DeclaratorInfo); - TypeIdParens.setEnd(MatchRHSPunctuation(tok::r_paren, - TypeIdParens.getBegin())); + T.consumeClose(); + TypeIdParens = T.getRange(); } else { MaybeParseGNUAttributes(DeclaratorInfo); if (ParseCXXTypeSpecifierSeq(DS)) @@ -1816,7 +2087,9 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SourceLocation ConstructorLParen, ConstructorRParen; if (Tok.is(tok::l_paren)) { - ConstructorLParen = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + ConstructorLParen = T.getOpenLocation(); if (Tok.isNot(tok::r_paren)) { CommaLocsTy CommaLocs; if (ParseExpressionList(ConstructorArgs, CommaLocs)) { @@ -1824,7 +2097,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return ExprError(); } } - ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen); + T.consumeClose(); + ConstructorRParen = T.getCloseLocation(); if (ConstructorRParen.isInvalid()) { SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); return ExprError(); @@ -1851,7 +2125,9 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { // Parse the array dimensions. bool first = true; while (Tok.is(tok::l_square)) { - SourceLocation LLoc = ConsumeBracket(); + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + ExprResult Size(first ? ParseExpression() : ParseConstantExpression()); if (Size.isInvalid()) { @@ -1861,15 +2137,17 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { } first = false; - SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); + T.consumeClose(); ParsedAttributes attrs(AttrFactory); D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.release(), LLoc, RLoc), - attrs, RLoc); + Size.release(), + T.getOpenLocation(), + T.getCloseLocation()), + attrs, T.getCloseLocation()); - if (RLoc.isInvalid()) + if (T.getCloseLocation().isInvalid()) return; } } @@ -1885,7 +2163,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { /// '(' expression-list ')' /// bool Parser::ParseExpressionListOrTypeId( - llvm::SmallVectorImpl<Expr*> &PlacementArgs, + SmallVectorImpl<Expr*> &PlacementArgs, Declarator &D) { // The '(' was already consumed. if (isTypeIdInParens()) { @@ -1921,9 +2199,11 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { bool ArrayDelete = false; if (Tok.is(tok::l_square)) { ArrayDelete = true; - SourceLocation LHS = ConsumeBracket(); - SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS); - if (RHS.isInvalid()) + BalancedDelimiterTracker T(*this, tok::l_square); + + T.consumeOpen(); + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return ExprError(); } @@ -1936,7 +2216,7 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { - default: assert(false && "Not a known unary type trait."); + default: llvm_unreachable("Not a known unary type trait."); case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; @@ -2004,7 +2284,7 @@ static ArrayTypeTrait ArrayTypeTraitFromTokKind(tok::TokenKind kind) { static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) { switch(kind) { - default: assert(false && "Not a known unary expression trait."); + default: llvm_unreachable("Not a known unary expression trait."); case tok::kw___is_lvalue_expr: return ET_IsLValueExpr; case tok::kw___is_rvalue_expr: return ET_IsRValueExpr; } @@ -2021,8 +2301,8 @@ ExprResult Parser::ParseUnaryTypeTrait() { UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind()); SourceLocation Loc = ConsumeToken(); - SourceLocation LParen = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) return ExprError(); // FIXME: Error reporting absolutely sucks! If the this fails to parse a type @@ -2030,12 +2310,12 @@ ExprResult Parser::ParseUnaryTypeTrait() { // specifiers. TypeResult Ty = ParseTypeName(); - SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + T.consumeClose(); if (Ty.isInvalid()) return ExprError(); - return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen); + return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), T.getCloseLocation()); } /// ParseBinaryTypeTrait - Parse the built-in binary type-trait @@ -2049,8 +2329,8 @@ ExprResult Parser::ParseBinaryTypeTrait() { BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind()); SourceLocation Loc = ConsumeToken(); - SourceLocation LParen = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) return ExprError(); TypeResult LhsTy = ParseTypeName(); @@ -2070,9 +2350,10 @@ ExprResult Parser::ParseBinaryTypeTrait() { return ExprError(); } - SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + T.consumeClose(); - return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen); + return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), + T.getCloseLocation()); } /// ParseArrayTypeTrait - Parse the built-in array type-trait @@ -2086,8 +2367,8 @@ ExprResult Parser::ParseArrayTypeTrait() { ArrayTypeTrait ATT = ArrayTypeTraitFromTokKind(Tok.getKind()); SourceLocation Loc = ConsumeToken(); - SourceLocation LParen = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) return ExprError(); TypeResult Ty = ParseTypeName(); @@ -2099,8 +2380,9 @@ ExprResult Parser::ParseArrayTypeTrait() { switch (ATT) { case ATT_ArrayRank: { - SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); - return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL, RParen); + T.consumeClose(); + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL, + T.getCloseLocation()); } case ATT_ArrayExtent: { if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { @@ -2109,9 +2391,10 @@ ExprResult Parser::ParseArrayTypeTrait() { } ExprResult DimExpr = ParseExpression(); - SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + T.consumeClose(); - return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(), RParen); + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), DimExpr.get(), + T.getCloseLocation()); } default: break; @@ -2129,15 +2412,16 @@ ExprResult Parser::ParseExpressionTrait() { ExpressionTrait ET = ExpressionTraitFromTokKind(Tok.getKind()); SourceLocation Loc = ConsumeToken(); - SourceLocation LParen = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) return ExprError(); ExprResult Expr = ParseExpression(); - SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + T.consumeClose(); - return Actions.ActOnExpressionTrait(ET, Loc, Expr.get(), RParen); + return Actions.ActOnExpressionTrait(ET, Loc, Expr.get(), + T.getCloseLocation()); } @@ -2147,8 +2431,7 @@ ExprResult Parser::ParseExpressionTrait() { ExprResult Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ParsedType &CastTy, - SourceLocation LParenLoc, - SourceLocation &RParenLoc) { + BalancedDelimiterTracker &Tracker) { assert(getLang().CPlusPlus && "Should only be called for C++!"); assert(ExprType == CastExpr && "Compound literals are not ambiguous!"); assert(isTypeIdInParens() && "Not a type-id!"); @@ -2182,7 +2465,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, // the context that follows them. if (!ConsumeAndStoreUntil(tok::r_paren, Toks)) { // We didn't find the ')' we expected. - MatchRHSPunctuation(tok::r_paren, LParenLoc); + Tracker.consumeClose(); return ExprError(); } @@ -2227,15 +2510,14 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ParseDeclarator(DeclaratorInfo); // Match the ')'. - if (Tok.is(tok::r_paren)) - RParenLoc = ConsumeParen(); - else - MatchRHSPunctuation(tok::r_paren, LParenLoc); + Tracker.consumeClose(); if (ParseAs == CompoundLiteral) { ExprType = CompoundLiteral; TypeResult Ty = ParseTypeName(); - return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc); + return ParseCompoundLiteralExpression(Ty.get(), + Tracker.getOpenLocation(), + Tracker.getCloseLocation()); } // We parsed '(' type-id ')' and the thing after it wasn't a '{'. @@ -2246,9 +2528,9 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, // Result is what ParseCastExpression returned earlier. if (!Result.isInvalid()) - Result = Actions.ActOnCastExpr(getCurScope(), LParenLoc, - DeclaratorInfo, CastTy, - RParenLoc, Result.take()); + Result = Actions.ActOnCastExpr(getCurScope(), Tracker.getOpenLocation(), + DeclaratorInfo, CastTy, + Tracker.getCloseLocation(), Result.take()); return move(Result); } @@ -2258,7 +2540,8 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ExprType = SimpleExpr; Result = ParseExpression(); if (!Result.isInvalid() && Tok.is(tok::r_paren)) - Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), Result.take()); + Result = Actions.ActOnParenExpr(Tracker.getOpenLocation(), + Tok.getLocation(), Result.take()); // Match the ')'. if (Result.isInvalid()) { @@ -2266,10 +2549,6 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, return ExprError(); } - if (Tok.is(tok::r_paren)) - RParenLoc = ConsumeParen(); - else - MatchRHSPunctuation(tok::r_paren, LParenLoc); - + Tracker.consumeClose(); return move(Result); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp index 2c9278a..33abc93 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp @@ -90,7 +90,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!"); SourceLocation ColonLoc = ConsumeToken(); - Diag(Tok, diag::ext_gnu_old_style_field_designator) + Diag(NameLoc, diag::ext_gnu_old_style_field_designator) << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc), NewSyntax.str()); @@ -139,7 +139,10 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { // InMessageExpressionRAIIObject InMessage(*this, true); - SourceLocation StartLoc = ConsumeBracket(); + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + SourceLocation StartLoc = T.getOpenLocation(); + ExprResult Idx; // If Objective-C is enabled and this is a typename (class message @@ -266,8 +269,9 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { StartLoc, EllipsisLoc)); } - SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); - Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc(EndLoc); + T.consumeClose(); + Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc( + T.getCloseLocation()); } // Okay, we're done with the designator sequence. We know that there must be @@ -316,7 +320,9 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { ExprResult Parser::ParseBraceInitializer() { InMessageExpressionRAIIObject InMessage(*this, false); - SourceLocation LBraceLoc = ConsumeBrace(); + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); + SourceLocation LBraceLoc = T.getOpenLocation(); /// InitExprs - This is the actual list of expressions contained in the /// initializer. @@ -376,12 +382,13 @@ ExprResult Parser::ParseBraceInitializer() { // Handle trailing comma. if (Tok.is(tok::r_brace)) break; } - if (InitExprsOk && Tok.is(tok::r_brace)) + + bool closed = !T.consumeClose(); + + if (InitExprsOk && closed) return Actions.ActOnInitList(LBraceLoc, move_arg(InitExprs), - ConsumeBrace()); + T.getCloseLocation()); - // Match the '}'. - MatchRHSPunctuation(tok::r_brace, LBraceLoc); return ExprError(); // an error occurred. } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp index 7641565..88044d1 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -29,57 +29,70 @@ using namespace clang; /// [OBJC] objc-protocol-definition /// [OBJC] objc-method-definition /// [OBJC] '@' 'end' -Decl *Parser::ParseObjCAtDirectives() { +Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, false); - ConsumeCodeCompletionToken(); + Actions.CodeCompleteObjCAtDirective(getCurScope()); + cutOffParsing(); + return DeclGroupPtrTy(); } - + + Decl *SingleDecl = 0; switch (Tok.getObjCKeywordID()) { case tok::objc_class: return ParseObjCAtClassDeclaration(AtLoc); + break; case tok::objc_interface: { ParsedAttributes attrs(AttrFactory); - return ParseObjCAtInterfaceDeclaration(AtLoc, attrs); + SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs); + break; } case tok::objc_protocol: { ParsedAttributes attrs(AttrFactory); - return ParseObjCAtProtocolDeclaration(AtLoc, attrs); + SingleDecl = ParseObjCAtProtocolDeclaration(AtLoc, attrs); + break; } case tok::objc_implementation: - return ParseObjCAtImplementationDeclaration(AtLoc); + SingleDecl = ParseObjCAtImplementationDeclaration(AtLoc); + break; case tok::objc_end: return ParseObjCAtEndDeclaration(AtLoc); + break; case tok::objc_compatibility_alias: - return ParseObjCAtAliasDeclaration(AtLoc); + SingleDecl = ParseObjCAtAliasDeclaration(AtLoc); + break; case tok::objc_synthesize: - return ParseObjCPropertySynthesize(AtLoc); + SingleDecl = ParseObjCPropertySynthesize(AtLoc); + break; case tok::objc_dynamic: - return ParseObjCPropertyDynamic(AtLoc); + SingleDecl = ParseObjCPropertyDynamic(AtLoc); + break; default: Diag(AtLoc, diag::err_unexpected_at); SkipUntil(tok::semi); - return 0; + SingleDecl = 0; + break; } + return Actions.ConvertDeclToDeclGroup(SingleDecl); } /// /// objc-class-declaration: /// '@' 'class' identifier-list ';' /// -Decl *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { +Parser::DeclGroupPtrTy +Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { ConsumeToken(); // the identifier "class" - llvm::SmallVector<IdentifierInfo *, 8> ClassNames; - llvm::SmallVector<SourceLocation, 8> ClassLocs; + SmallVector<IdentifierInfo *, 8> ClassNames; + SmallVector<SourceLocation, 8> ClassLocs; while (1) { if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); SkipUntil(tok::semi); - return 0; + return Actions.ConvertDeclToDeclGroup(0); } ClassNames.push_back(Tok.getIdentifierInfo()); ClassLocs.push_back(Tok.getLocation()); @@ -93,7 +106,7 @@ Decl *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { // Consume the ';'. if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class")) - return 0; + return Actions.ConvertDeclToDeclGroup(0); return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(), ClassLocs.data(), @@ -137,7 +150,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, // Code completion after '@interface'. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceDecl(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -150,14 +164,16 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, SourceLocation nameLoc = ConsumeToken(); if (Tok.is(tok::l_paren) && !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category. - // TODO(dgregor): Use the return value from the next line to provide better - // recovery. - ConsumeParen(); - SourceLocation categoryLoc, rparenLoc; + + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + + SourceLocation categoryLoc; IdentifierInfo *categoryId = 0; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } // For ObjC2, the category name is optional (not an error). @@ -169,24 +185,25 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, Diag(Tok, diag::err_expected_ident); // missing category name. return 0; } - if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_rparen); - SkipUntil(tok::r_paren, false); // don't stop at ';' + + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return 0; + + if (!attrs.empty()) { // categories don't support attributes. + Diag(nameLoc, diag::err_objc_no_attributes_on_category); + attrs.clear(); } - rparenLoc = ConsumeParen(); + // Next, we need to check for any protocol references. SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<Decl *, 8> ProtocolRefs; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + SmallVector<Decl *, 8> ProtocolRefs; + SmallVector<SourceLocation, 8> ProtocolLocs; if (Tok.is(tok::less) && ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, LAngleLoc, EndProtoLoc)) return 0; - if (!attrs.empty()) // categories don't support attributes. - Diag(Tok, diag::err_objc_no_attributes_on_category); - Decl *CategoryType = Actions.ActOnStartCategoryInterface(atLoc, nameId, nameLoc, @@ -195,11 +212,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc); - if (Tok.is(tok::l_brace)) - ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, - atLoc); - ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword); + if (Tok.is(tok::l_brace)) + ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, atLoc); + + ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType); return CategoryType; } // Parse a class interface. @@ -212,7 +229,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, // Code completion of superclass names. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -223,8 +241,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, superClassLoc = ConsumeToken(); } // Next, we need to check for any protocol references. - llvm::SmallVector<Decl *, 8> ProtocolRefs; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + SmallVector<Decl *, 8> ProtocolRefs; + SmallVector<SourceLocation, 8> ProtocolLocs; SourceLocation LAngleLoc, EndProtoLoc; if (Tok.is(tok::less) && ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, @@ -241,7 +259,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc); - ParseObjCInterfaceDeclList(ClsType, tok::objc_interface); + ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); return ClsType; } @@ -249,17 +267,16 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, /// it's used, but instead it's been lifted to here to support VS2005. struct Parser::ObjCPropertyCallback : FieldCallback { Parser &P; - Decl *IDecl; - llvm::SmallVectorImpl<Decl *> &Props; + SmallVectorImpl<Decl *> &Props; ObjCDeclSpec &OCDS; SourceLocation AtLoc; tok::ObjCKeywordKind MethodImplKind; - ObjCPropertyCallback(Parser &P, Decl *IDecl, - llvm::SmallVectorImpl<Decl *> &Props, + ObjCPropertyCallback(Parser &P, + SmallVectorImpl<Decl *> &Props, ObjCDeclSpec &OCDS, SourceLocation AtLoc, tok::ObjCKeywordKind MethodImplKind) : - P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc), + P(P), Props(Props), OCDS(OCDS), AtLoc(AtLoc), MethodImplKind(MethodImplKind) { } @@ -292,7 +309,7 @@ struct Parser::ObjCPropertyCallback : FieldCallback { bool isOverridingProperty = false; Decl *Property = P.Actions.ActOnProperty(P.getCurScope(), AtLoc, FD, OCDS, - GetterSel, SetterSel, IDecl, + GetterSel, SetterSel, &isOverridingProperty, MethodImplKind); if (!isOverridingProperty) @@ -314,20 +331,20 @@ struct Parser::ObjCPropertyCallback : FieldCallback { /// @required /// @optional /// -void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, - tok::ObjCKeywordKind contextKey) { - llvm::SmallVector<Decl *, 32> allMethods; - llvm::SmallVector<Decl *, 16> allProperties; - llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables; +void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, + Decl *CDecl) { + SmallVector<Decl *, 32> allMethods; + SmallVector<Decl *, 16> allProperties; + SmallVector<DeclGroupPtrTy, 8> allTUVariables; tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; SourceRange AtEnd; - + while (1) { // If this is a method prototype, parse it. if (Tok.is(tok::minus) || Tok.is(tok::plus)) { Decl *methodPrototype = - ParseObjCMethodPrototype(interfaceDecl, MethodImplKind, false); + ParseObjCMethodPrototype(MethodImplKind, false); allMethods.push_back(methodPrototype); // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for // method definitions. @@ -339,7 +356,6 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, Diag(Tok, diag::err_expected_minus_or_plus); ParseObjCMethodDecl(Tok.getLocation(), tok::minus, - interfaceDecl, MethodImplKind, false); continue; } @@ -358,7 +374,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, Actions.CodeCompleteOrdinaryName(getCurScope(), ObjCImpDecl? Sema::PCC_ObjCImplementation : Sema::PCC_ObjCInterface); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } // If we don't have an @ directive, parse it as a function definition. @@ -368,9 +384,6 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // erroneous r_brace would cause an infinite loop if not handled here. if (Tok.is(tok::r_brace)) break; - - // FIXME: as the name implies, this rule allows function definitions. - // We could pass a flag or check for functions during semantic analysis. ParsedAttributes attrs(AttrFactory); allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); continue; @@ -379,8 +392,8 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // Otherwise, we have an @ directive, eat the @. SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true); - ConsumeCodeCompletionToken(); + Actions.CodeCompleteObjCAtDirective(getCurScope()); + return cutOffParsing(); break; } @@ -433,9 +446,9 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, ObjCDeclSpec OCDS; // Parse property attribute list, if any. if (Tok.is(tok::l_paren)) - ParseObjCPropertyAttribute(OCDS, interfaceDecl); + ParseObjCPropertyAttribute(OCDS); - ObjCPropertyCallback Callback(*this, interfaceDecl, allProperties, + ObjCPropertyCallback Callback(*this, allProperties, OCDS, AtLoc, MethodImplKind); // Parse all the comma separated declarators. @@ -450,8 +463,8 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // We break out of the big loop in two cases: when we see @end or when we see // EOF. In the former case, eat the @end. In the later case, emit an error. if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCAtDirective(getCurScope(), ObjCImpDecl, true); - ConsumeCodeCompletionToken(); + Actions.CodeCompleteObjCAtDirective(getCurScope()); + return cutOffParsing(); } else if (Tok.isObjCAtKeyword(tok::objc_end)) ConsumeToken(); // the "end" identifier else @@ -459,7 +472,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // Insert collected methods declarations into the @interface object. // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. - Actions.ActOnAtEnd(getCurScope(), AtEnd, interfaceDecl, + Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods.data(), allMethods.size(), allProperties.data(), allProperties.size(), allTUVariables.data(), allTUVariables.size()); @@ -485,20 +498,21 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, /// weak /// unsafe_unretained /// -void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { +void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { assert(Tok.getKind() == tok::l_paren); - SourceLocation LHSLoc = ConsumeParen(); // consume '(' + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); while (1) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } const IdentifierInfo *II = Tok.getIdentifierInfo(); // If this is not an identifier at all, bail out early. if (II == 0) { - MatchRHSPunctuation(tok::r_paren, LHSLoc); + T.consumeClose(); return; } @@ -536,10 +550,10 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { if (Tok.is(tok::code_completion)) { if (IsSetter) - Actions.CodeCompleteObjCPropertySetter(getCurScope(), ClassDecl); + Actions.CodeCompleteObjCPropertySetter(getCurScope()); else - Actions.CodeCompleteObjCPropertyGetter(getCurScope(), ClassDecl); - ConsumeCodeCompletionToken(); + Actions.CodeCompleteObjCPropertyGetter(getCurScope()); + return cutOffParsing(); } @@ -577,7 +591,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { ConsumeToken(); } - MatchRHSPunctuation(tok::r_paren, LHSLoc); + T.consumeClose(); } /// objc-method-proto: @@ -590,14 +604,13 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { /// objc-method-attributes: [OBJC2] /// __attribute__((deprecated)) /// -Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl, - tok::ObjCKeywordKind MethodImplKind, +Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); tok::TokenKind methodType = Tok.getKind(); SourceLocation mLoc = ConsumeToken(); - Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind, + Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind, MethodDefinition); // Since this rule is used for both method declarations and definitions, // the caller is (optionally) responsible for consuming the ';'. @@ -732,12 +745,15 @@ bool Parser::isTokIdentifier_in() const { /// objc-type-qualifiers objc-type-qualifier /// void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, - ObjCTypeNameContext Context) { + Declarator::TheContext Context) { + assert(Context == Declarator::ObjCParameterContext || + Context == Declarator::ObjCResultContext); + while (1) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPassingType(getCurScope(), DS, - Context == OTN_ParameterType); - ConsumeCodeCompletionToken(); + Context == Declarator::ObjCParameterContext); + return cutOffParsing(); } if (Tok.isNot(tok::identifier)) @@ -750,7 +766,7 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, ObjCDeclSpec::ObjCDeclQualifier Qual; switch (i) { - default: assert(0 && "Unknown decl qualifier"); + default: llvm_unreachable("Unknown decl qualifier"); case objc_in: Qual = ObjCDeclSpec::DQ_In; break; case objc_out: Qual = ObjCDeclSpec::DQ_Out; break; case objc_inout: Qual = ObjCDeclSpec::DQ_Inout; break; @@ -769,30 +785,95 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, } } +/// Take all the decl attributes out of the given list and add +/// them to the given attribute set. +static void takeDeclAttributes(ParsedAttributes &attrs, + AttributeList *list) { + while (list) { + AttributeList *cur = list; + list = cur->getNext(); + + if (!cur->isUsedAsTypeAttr()) { + // Clear out the next pointer. We're really completely + // destroying the internal invariants of the declarator here, + // but it doesn't matter because we're done with it. + cur->setNext(0); + attrs.add(cur); + } + } +} + +/// takeDeclAttributes - Take all the decl attributes from the given +/// declarator and add them to the given list. +static void takeDeclAttributes(ParsedAttributes &attrs, + Declarator &D) { + // First, take ownership of all attributes. + attrs.getPool().takeAllFrom(D.getAttributePool()); + attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); + + // Now actually move the attributes over. + takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList()); + takeDeclAttributes(attrs, D.getAttributes()); + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) + takeDeclAttributes(attrs, + const_cast<AttributeList*>(D.getTypeObject(i).getAttrs())); +} + /// objc-type-name: /// '(' objc-type-qualifiers[opt] type-name ')' /// '(' objc-type-qualifiers[opt] ')' /// ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, - ObjCTypeNameContext Context) { + Declarator::TheContext context, + ParsedAttributes *paramAttrs) { + assert(context == Declarator::ObjCParameterContext || + context == Declarator::ObjCResultContext); + assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext)); + assert(Tok.is(tok::l_paren) && "expected ("); - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + SourceLocation TypeStartLoc = Tok.getLocation(); + ObjCDeclContextSwitch ObjCDC(*this); // Parse type qualifiers, in, inout, etc. - ParseObjCTypeQualifierList(DS, Context); + ParseObjCTypeQualifierList(DS, context); ParsedType Ty; if (isTypeSpecifierQualifier()) { - TypeResult TypeSpec = - ParseTypeName(0, Declarator::ObjCPrototypeContext, &DS); - if (!TypeSpec.isInvalid()) - Ty = TypeSpec.get(); + // Parse an abstract declarator. + DeclSpec declSpec(AttrFactory); + declSpec.setObjCQualifiers(&DS); + ParseSpecifierQualifierList(declSpec); + Declarator declarator(declSpec, context); + ParseDeclarator(declarator); + + // If that's not invalid, extract a type. + if (!declarator.isInvalidType()) { + TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator); + if (!type.isInvalid()) + Ty = type.get(); + + // If we're parsing a parameter, steal all the decl attributes + // and add them to the decl spec. + if (context == Declarator::ObjCParameterContext) + takeDeclAttributes(*paramAttrs, declarator); + } + } else if (context == Declarator::ObjCResultContext && + Tok.is(tok::identifier)) { + if (!Ident_instancetype) + Ident_instancetype = PP.getIdentifierInfo("instancetype"); + + if (Tok.getIdentifierInfo() == Ident_instancetype) { + Ty = Actions.ActOnObjCInstanceType(Tok.getLocation()); + ConsumeToken(); + } } - + if (Tok.is(tok::r_paren)) - ConsumeParen(); + T.consumeClose(); else if (Tok.getLocation() == TypeStartLoc) { // If we didn't eat any tokens, then this isn't a type. Diag(Tok, diag::err_expected_type); @@ -800,7 +881,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, } else { // Otherwise, we found *something*, but didn't get a ')' in the right // place. Emit an error then return what we have as the type. - MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); } return Ty; } @@ -835,22 +916,22 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, /// Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, - Decl *IDecl, tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { ParsingDeclRAIIObject PD(*this); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, - /*ReturnType=*/ ParsedType(), IDecl); - ConsumeCodeCompletionToken(); + /*ReturnType=*/ ParsedType()); + cutOffParsing(); + return 0; } // Parse the return type if present. ParsedType ReturnType; ObjCDeclSpec DSRet; if (Tok.is(tok::l_paren)) - ReturnType = ParseObjCTypeName(DSRet, OTN_ResultType); + ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0); // If attributes exist before the method, parse them. ParsedAttributes methodAttrs(AttrFactory); @@ -859,8 +940,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, - ReturnType, IDecl); - ConsumeCodeCompletionToken(); + ReturnType); + cutOffParsing(); + return 0; } // Now parse the selector. @@ -876,7 +958,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, return 0; } - llvm::SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; + SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; if (Tok.isNot(tok::colon)) { // If attributes exist after the method, parse them. if (getLang().ObjC2) @@ -885,7 +967,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, IDecl, DSRet, ReturnType, + mType, DSRet, ReturnType, selLoc, Sel, 0, CParamInfo.data(), CParamInfo.size(), methodAttrs.getList(), MethodImplKind, @@ -894,8 +976,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, return Result; } - llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; - llvm::SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; + SmallVector<IdentifierInfo *, 12> KeyIdents; + SmallVector<SourceLocation, 12> KeyLocs; + SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope); @@ -914,9 +997,12 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfo.Type = ParsedType(); if (Tok.is(tok::l_paren)) // Parse the argument type if present. - ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, OTN_ParameterType); + ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, + Declarator::ObjCParameterContext, + ¶mAttrs); // If attributes exist before the argument name, parse them. + // Regardless, collect all the attributes we've parsed so far. ArgInfo.ArgAttrs = 0; if (getLang().ObjC2) { MaybeParseGNUAttributes(paramAttrs); @@ -925,7 +1011,6 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { - ConsumeCodeCompletionToken(); KeyIdents.push_back(SelIdent); Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), mType == tok::minus, @@ -933,8 +1018,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ReturnType, KeyIdents.data(), KeyIdents.size()); - KeyIdents.pop_back(); - break; + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -948,25 +1033,25 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfos.push_back(ArgInfo); KeyIdents.push_back(SelIdent); + KeyLocs.push_back(selLoc); // Make sure the attributes persist. allParamAttrs.takeAllFrom(paramAttrs.getPool()); // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { - ConsumeCodeCompletionToken(); Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), mType == tok::minus, /*AtParameterName=*/false, ReturnType, KeyIdents.data(), KeyIdents.size()); - break; + cutOffParsing(); + return 0; } // Check for another keyword selector. - SourceLocation Loc; - SelIdent = ParseObjCSelectorPiece(Loc); + SelIdent = ParseObjCSelectorPiece(selLoc); if (!SelIdent && Tok.isNot(tok::colon)) break; // We have a selector or a colon, continue parsing. @@ -1001,23 +1086,18 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (getLang().ObjC2) MaybeParseGNUAttributes(methodAttrs); - if (KeyIdents.size() == 0) { - // Leave prototype scope. - PrototypeScope.Exit(); + if (KeyIdents.size() == 0) return 0; - } Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); Decl *Result = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, IDecl, DSRet, ReturnType, - selLoc, Sel, &ArgInfos[0], + mType, DSRet, ReturnType, + KeyLocs, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs.getList(), MethodImplKind, isVariadic, MethodDefinition); - // Leave prototype scope. - PrototypeScope.Exit(); PD.complete(Result); return Result; @@ -1027,21 +1107,22 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, /// '<' identifier-list '>' /// bool Parser:: -ParseObjCProtocolReferences(llvm::SmallVectorImpl<Decl *> &Protocols, - llvm::SmallVectorImpl<SourceLocation> &ProtocolLocs, +ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, + SmallVectorImpl<SourceLocation> &ProtocolLocs, bool WarnOnDeclarations, SourceLocation &LAngleLoc, SourceLocation &EndLoc) { assert(Tok.is(tok::less) && "expected <"); LAngleLoc = ConsumeToken(); // the "<" - llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents; + SmallVector<IdentifierLocPair, 8> ProtocolIdents; while (1) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(), ProtocolIdents.size()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return true; } if (Tok.isNot(tok::identifier)) { @@ -1080,8 +1161,8 @@ bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) { assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'"); assert(getLang().ObjC1 && "Protocol qualifiers only exist in Objective-C"); SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<Decl *, 8> ProtocolDecl; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + SmallVector<Decl *, 8> ProtocolDecl; + SmallVector<SourceLocation, 8> ProtocolLocs; bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, LAngleLoc, EndProtoLoc); DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), @@ -1116,11 +1197,13 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, tok::ObjCKeywordKind visibility, SourceLocation atLoc) { assert(Tok.is(tok::l_brace) && "expected {"); - llvm::SmallVector<Decl *, 32> AllIvarDecls; - + SmallVector<Decl *, 32> AllIvarDecls; + ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); + ObjCDeclContextSwitch ObjCDC(*this); - SourceLocation LBraceLoc = ConsumeBrace(); // the "{" + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); // While we still have something to read, read the instance variables. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { @@ -1140,7 +1223,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtVisibility(getCurScope()); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } switch (Tok.getObjCKeywordID()) { @@ -1160,26 +1243,28 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_ObjCInstanceVariableList); - ConsumeCodeCompletionToken(); + return cutOffParsing(); } struct ObjCIvarCallback : FieldCallback { Parser &P; Decl *IDecl; tok::ObjCKeywordKind visibility; - llvm::SmallVectorImpl<Decl *> &AllIvarDecls; + SmallVectorImpl<Decl *> &AllIvarDecls; ObjCIvarCallback(Parser &P, Decl *IDecl, tok::ObjCKeywordKind V, - llvm::SmallVectorImpl<Decl *> &AllIvarDecls) : + SmallVectorImpl<Decl *> &AllIvarDecls) : P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) { } Decl *invoke(FieldDeclarator &FD) { + P.Actions.ActOnObjCContainerStartDefinition(IDecl); // Install the declarator into the interface decl. Decl *Field = P.Actions.ActOnIvar(P.getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), - IDecl, FD.D, FD.BitfieldSize, visibility); + FD.D, FD.BitfieldSize, visibility); + P.Actions.ActOnObjCContainerFinishDefinition(); if (Field) AllIvarDecls.push_back(Field); return Field; @@ -1198,13 +1283,16 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, SkipUntil(tok::r_brace, true, true); } } - SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); - Actions.ActOnLastBitfield(RBraceLoc, interfaceDecl, AllIvarDecls); + T.consumeClose(); + + Actions.ActOnObjCContainerStartDefinition(interfaceDecl); + Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); + Actions.ActOnObjCContainerFinishDefinition(); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, - AllIvarDecls.data(), AllIvarDecls.size(), - LBraceLoc, RBraceLoc, 0); + AllIvarDecls, + T.getOpenLocation(), T.getCloseLocation(), 0); return; } @@ -1232,7 +1320,8 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCProtocolDecl(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -1251,7 +1340,7 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, } if (Tok.is(tok::comma)) { // list of forward declarations. - llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs; + SmallVector<IdentifierLocPair, 8> ProtocolRefs; ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc)); // Parse the list of forward declarations. @@ -1282,8 +1371,8 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, // Last, and definitely not least, parse a protocol declaration. SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<Decl *, 8> ProtocolRefs; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + SmallVector<Decl *, 8> ProtocolRefs; + SmallVector<SourceLocation, 8> ProtocolLocs; if (Tok.is(tok::less) && ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, LAngleLoc, EndProtoLoc)) @@ -1295,7 +1384,8 @@ Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, ProtocolRefs.size(), ProtocolLocs.data(), EndProtoLoc, attrs.getList()); - ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol); + + ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); return ProtoType; } @@ -1318,7 +1408,8 @@ Decl *Parser::ParseObjCAtImplementationDeclaration( // Code completion after '@implementation'. if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCImplementationDecl(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -1337,7 +1428,8 @@ Decl *Parser::ParseObjCAtImplementationDeclaration( if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return 0; } if (Tok.is(tok::identifier)) { @@ -1356,6 +1448,7 @@ Decl *Parser::ParseObjCAtImplementationDeclaration( Decl *ImplCatType = Actions.ActOnStartCategoryImplementation( atLoc, nameId, nameLoc, categoryId, categoryLoc); + ObjCImpDecl = ImplCatType; PendingObjCImpDecl.push_back(ObjCImpDecl); return 0; @@ -1378,29 +1471,38 @@ Decl *Parser::ParseObjCAtImplementationDeclaration( superClassId, superClassLoc); if (Tok.is(tok::l_brace)) // we have ivars - ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, - tok::objc_private, atLoc); + ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, atLoc); + ObjCImpDecl = ImplClsType; PendingObjCImpDecl.push_back(ObjCImpDecl); - return 0; } -Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { +Parser::DeclGroupPtrTy +Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { assert(Tok.isObjCAtKeyword(tok::objc_end) && "ParseObjCAtEndDeclaration(): Expected @end"); - Decl *Result = ObjCImpDecl; ConsumeToken(); // the "end" identifier + SmallVector<Decl *, 8> DeclsInGroup; + Actions.DefaultSynthesizeProperties(getCurScope(), ObjCImpDecl); + for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) { + Decl *D = ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i]); + DeclsInGroup.push_back(D); + } + DeclsInGroup.push_back(ObjCImpDecl); + if (ObjCImpDecl) { - Actions.ActOnAtEnd(getCurScope(), atEnd, ObjCImpDecl); - ObjCImpDecl = 0; + Actions.ActOnAtEnd(getCurScope(), atEnd); PendingObjCImpDecl.pop_back(); } - else { + else // missing @implementation Diag(atEnd.getBegin(), diag::err_expected_implementation); - } - return Result; + + LateParsedObjCMethods.clear(); + ObjCImpDecl = 0; + return Actions.BuildDeclaratorGroup( + DeclsInGroup.data(), DeclsInGroup.size(), false); } Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() { @@ -1408,7 +1510,7 @@ Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() { if (PendingObjCImpDecl.empty()) return Actions.ConvertDeclToDeclGroup(0); Decl *ImpDecl = PendingObjCImpDecl.pop_back_val(); - Actions.ActOnAtEnd(getCurScope(), SourceRange(), ImpDecl); + Actions.ActOnAtEnd(getCurScope(), SourceRange()); return Actions.ConvertDeclToDeclGroup(ImpDecl); } @@ -1455,8 +1557,9 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { while (true) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl); - ConsumeCodeCompletionToken(); + Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -1474,9 +1577,9 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { ConsumeToken(); // consume '=' if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId, - ObjCImpDecl); - ConsumeCodeCompletionToken(); + Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -1486,7 +1589,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { propertyIvar = Tok.getIdentifierInfo(); propertyIvarLoc = ConsumeToken(); // consume ivar-name } - Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, ObjCImpDecl, + Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, propertyId, propertyIvar, propertyIvarLoc); if (Tok.isNot(tok::comma)) break; @@ -1509,8 +1612,9 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { ConsumeToken(); // consume dynamic while (true) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPropertyDefinition(getCurScope(), ObjCImpDecl); - ConsumeCodeCompletionToken(); + Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); + cutOffParsing(); + return 0; } if (Tok.isNot(tok::identifier)) { @@ -1521,7 +1625,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name - Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, ObjCImpDecl, + Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, propertyId, 0, SourceLocation()); if (Tok.isNot(tok::comma)) @@ -1560,31 +1664,46 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { Diag(Tok, diag::err_expected_lparen_after) << "@synchronized"; return StmtError(); } + + // The operand is surrounded with parentheses. ConsumeParen(); // '(' - ExprResult Res(ParseExpression()); - if (Res.isInvalid()) { - SkipUntil(tok::semi); - return StmtError(); - } - if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_lbrace); - return StmtError(); + ExprResult operand(ParseExpression()); + + if (Tok.is(tok::r_paren)) { + ConsumeParen(); // ')' + } else { + if (!operand.isInvalid()) + Diag(Tok, diag::err_expected_rparen); + + // Skip forward until we see a left brace, but don't consume it. + SkipUntil(tok::l_brace, true, true); } - ConsumeParen(); // ')' + + // Require a compound statement. if (Tok.isNot(tok::l_brace)) { - Diag(Tok, diag::err_expected_lbrace); + if (!operand.isInvalid()) + Diag(Tok, diag::err_expected_lbrace); return StmtError(); } - // Enter a scope to hold everything within the compound stmt. Compound - // statements can always hold declarations. - ParseScope BodyScope(this, Scope::DeclScope); - StmtResult SynchBody(ParseCompoundStatementBody()); + // Check the @synchronized operand now. + if (!operand.isInvalid()) + operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.take()); - BodyScope.Exit(); - if (SynchBody.isInvalid()) - SynchBody = Actions.ActOnNullStmt(Tok.getLocation()); - return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.take(), SynchBody.take()); + // Parse the compound statement within a new scope. + ParseScope bodyScope(this, Scope::DeclScope); + StmtResult body(ParseCompoundStatementBody()); + bodyScope.Exit(); + + // If there was a semantic or parse error earlier with the + // operand, fail now. + if (operand.isInvalid()) + return StmtError(); + + if (body.isInvalid()) + body = Actions.ActOnNullStmt(Tok.getLocation()); + + return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get()); } /// objc-try-catch-statement: @@ -1724,7 +1843,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// Decl *Parser::ParseObjCMethodDefinition() { - Decl *MDecl = ParseObjCMethodPrototype(ObjCImpDecl); + Decl *MDecl = ParseObjCMethodPrototype(); PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(), "parsing Objective-C method"); @@ -1749,42 +1868,26 @@ Decl *Parser::ParseObjCMethodDefinition() { if (Tok.isNot(tok::l_brace)) return 0; } - SourceLocation BraceLoc = Tok.getLocation(); - - // Enter a scope for the method body. - ParseScope BodyScope(this, - Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope); - - // Tell the actions module that we have entered a method definition with the - // specified Declarator for the method. - Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl); - - if (PP.isCodeCompletionEnabled()) { - if (trySkippingFunctionBodyForCodeCompletion()) { - BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(MDecl, 0); - } - } - - StmtResult FnBody(ParseCompoundStatementBody()); - - // If the function body could not be parsed, make a bogus compoundstmt. - if (FnBody.isInvalid()) - FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, - MultiStmtArg(Actions), false); - - // Leave the function body scope. - BodyScope.Exit(); - - // TODO: Pass argument information. - Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); + // Allow the rest of sema to find private method decl implementations. + if (MDecl) + Actions.AddAnyMethodToGlobalPool(MDecl); + + // Consume the tokens and store them for later parsing. + LexedMethod* LM = new LexedMethod(this, MDecl); + LateParsedObjCMethods.push_back(LM); + CachedTokens &Toks = LM->Toks; + // Begin by storing the '{' token. + Toks.push_back(Tok); + ConsumeBrace(); + // Consume everything up to (and including) the matching right brace. + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); return MDecl; } StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtStatement(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); return StmtError(); } @@ -1818,7 +1921,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { switch (Tok.getKind()) { case tok::code_completion: Actions.CodeCompleteObjCAtExpression(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); return ExprError(); case tok::string_literal: // primary-expression: string-literal @@ -1984,8 +2087,7 @@ ExprResult Parser::ParseObjCMessageExpression() { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMessageReceiver(getCurScope()); - ConsumeCodeCompletionToken(); - SkipUntil(tok::r_square); + cutOffParsing(); return ExprError(); } @@ -2116,22 +2218,23 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, else Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, 0, 0, false); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return ExprError(); } // Parse objc-selector SourceLocation Loc; IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); - SourceLocation SelectorLoc = Loc; - - llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; + SmallVector<IdentifierInfo *, 12> KeyIdents; + SmallVector<SourceLocation, 12> KeyLocs; ExprVector KeyExprs(Actions); if (Tok.is(tok::colon)) { while (1) { // Each iteration parses a single keyword argument. KeyIdents.push_back(selIdent); + KeyLocs.push_back(Loc); if (Tok.isNot(tok::colon)) { Diag(Tok, diag::err_expected_colon); @@ -2162,8 +2265,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, KeyIdents.size(), /*AtArgumentEpression=*/true); - ConsumeCodeCompletionToken(); - SkipUntil(tok::r_square); + cutOffParsing(); return ExprError(); } @@ -2196,8 +2298,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, KeyIdents.data(), KeyIdents.size(), /*AtArgumentEpression=*/false); - ConsumeCodeCompletionToken(); - SkipUntil(tok::r_square); + cutOffParsing(); return ExprError(); } @@ -2248,24 +2349,26 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, SourceLocation RBracLoc = ConsumeBracket(); // consume ']' unsigned nKeys = KeyIdents.size(); - if (nKeys == 0) + if (nKeys == 0) { KeyIdents.push_back(selIdent); + KeyLocs.push_back(Loc); + } Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]); if (SuperLoc.isValid()) return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel, - LBracLoc, SelectorLoc, RBracLoc, + LBracLoc, KeyLocs, RBracLoc, MultiExprArg(Actions, KeyExprs.take(), KeyExprs.size())); else if (ReceiverType) return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel, - LBracLoc, SelectorLoc, RBracLoc, + LBracLoc, KeyLocs, RBracLoc, MultiExprArg(Actions, KeyExprs.take(), KeyExprs.size())); return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel, - LBracLoc, SelectorLoc, RBracLoc, + LBracLoc, KeyLocs, RBracLoc, MultiExprArg(Actions, KeyExprs.take(), KeyExprs.size())); @@ -2278,7 +2381,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string // expressions. At this point, we know that the only valid thing that starts // with '@' is an @"". - llvm::SmallVector<SourceLocation, 4> AtLocs; + SmallVector<SourceLocation, 4> AtLocs; ExprVector AtStrings(Actions); AtLocs.push_back(AtLoc); AtStrings.push_back(Res.release()); @@ -2312,17 +2415,19 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { if (Tok.isNot(tok::l_paren)) return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode"); - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); TypeResult Ty = ParseTypeName(); - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); if (Ty.isInvalid()) return ExprError(); - return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, - Ty.get(), RParenLoc)); + return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, + T.getOpenLocation(), Ty.get(), + T.getCloseLocation())); } /// objc-protocol-expression @@ -2334,7 +2439,8 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { if (Tok.isNot(tok::l_paren)) return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol"); - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); if (Tok.isNot(tok::identifier)) return ExprError(Diag(Tok, diag::err_expected_ident)); @@ -2342,10 +2448,11 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { IdentifierInfo *protocolId = Tok.getIdentifierInfo(); ConsumeToken(); - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, - LParenLoc, RParenLoc)); + T.getOpenLocation(), + T.getCloseLocation())); } /// objc-selector-expression @@ -2356,15 +2463,16 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { if (Tok.isNot(tok::l_paren)) return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector"); - llvm::SmallVector<IdentifierInfo *, 12> KeyIdents; - SourceLocation LParenLoc = ConsumeParen(); + SmallVector<IdentifierInfo *, 12> KeyIdents; SourceLocation sLoc; + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents.data(), KeyIdents.size()); - ConsumeCodeCompletionToken(); - MatchRHSPunctuation(tok::r_paren, LParenLoc); + cutOffParsing(); return ExprError(); } @@ -2391,8 +2499,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents.data(), KeyIdents.size()); - ConsumeCodeCompletionToken(); - MatchRHSPunctuation(tok::r_paren, LParenLoc); + cutOffParsing(); return ExprError(); } @@ -2404,8 +2511,52 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { break; } } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); return Owned(Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, - LParenLoc, RParenLoc)); + T.getOpenLocation(), + T.getCloseLocation())); } + +Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) { + + assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!"); + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + LM.Toks.push_back(Tok); + PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); + + // MDecl might be null due to error in method prototype, etc. + Decl *MDecl = LM.D; + // Consume the previously pushed token. + ConsumeAnyToken(); + + assert(Tok.is(tok::l_brace) && "Inline objective-c method not starting with '{'"); + SourceLocation BraceLoc = Tok.getLocation(); + // Enter a scope for the method body. + ParseScope BodyScope(this, + Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope); + + // Tell the actions module that we have entered a method definition with the + // specified Declarator for the method. + Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl); + + if (PP.isCodeCompletionEnabled()) { + if (trySkippingFunctionBodyForCodeCompletion()) { + BodyScope.Exit(); + return Actions.ActOnFinishFunctionBody(MDecl, 0); + } + } + + StmtResult FnBody(ParseCompoundStatementBody()); + + // If the function body could not be parsed, make a bogus compoundstmt. + if (FnBody.isInvalid()) + FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, + MultiStmtArg(Actions), false); + + // Leave the function body scope. + BodyScope.Exit(); + + return Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp index c30ab75..2ccb6ea 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp @@ -38,7 +38,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, SourceLocation VisLoc = VisTok.getLocation(); Token Tok; - PP.Lex(Tok); + PP.LexUnexpandedToken(Tok); const IdentifierInfo *PushPop = Tok.getIdentifierInfo(); @@ -49,20 +49,20 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, VisType = 0; } else if (PushPop && PushPop->isStr("push")) { IsPush = true; - PP.Lex(Tok); + PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "visibility"; return; } - PP.Lex(Tok); + PP.LexUnexpandedToken(Tok); VisType = Tok.getIdentifierInfo(); if (!VisType) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "visibility"; return; } - PP.Lex(Tok); + PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::r_paren)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "visibility"; @@ -73,7 +73,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, << "visibility"; return; } - PP.Lex(Tok); + PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "visibility"; @@ -297,7 +297,7 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, } // Lex the declaration reference(s). - llvm::SmallVector<Token, 5> Identifiers; + SmallVector<Token, 5> Identifiers; SourceLocation RParenLoc; bool LexID = true; @@ -451,8 +451,11 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, } OpenCLOptions &f = Actions.getOpenCLOptions(); - if (ename->isStr("all")) { -#define OPENCLEXT(nm) f.nm = state; + // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, + // overriding all previously issued extension directives, but only if the + // behavior is set to disable." + if (state == 0 && ename->isStr("all")) { +#define OPENCLEXT(nm) f.nm = 0; #include "clang/Basic/OpenCLExtensions.def" } #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index b91bca5..a2b7cdd 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -79,7 +79,7 @@ StmtResult Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { const char *SemiError = 0; StmtResult Res; - + ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange attrs(AttrFactory); @@ -100,20 +100,25 @@ Retry: case tok::code_completion: Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement); - ConsumeCodeCompletionToken(); - return ParseStatementOrDeclaration(Stmts, OnlyStatement); - + cutOffParsing(); + return StmtError(); + case tok::identifier: { Token Next = NextToken(); if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement // identifier ':' statement return ParseLabeledStatement(attrs); } - + if (Next.isNot(tok::coloncolon)) { CXXScopeSpec SS; IdentifierInfo *Name = Tok.getIdentifierInfo(); SourceLocation NameLoc = Tok.getLocation(); + + if (getLang().CPlusPlus) + CheckForTemplateAndDigraph(Next, ParsedType(), + /*EnteringContext=*/false, *Name, SS); + Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next); switch (Classification.getKind()) { @@ -125,11 +130,11 @@ Retry: Tok.setKind(Name->getTokenID()); goto Retry; } - + // Fall through via the normal error path. // FIXME: This seems like it could only happen for context-sensitive // keywords. - + case Sema::NC_Error: // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. @@ -137,33 +142,33 @@ Retry: if (Tok.is(tok::semi)) ConsumeToken(); return StmtError(); - + case Sema::NC_Unknown: // Either we don't know anything about this identifier, or we know that - // we're in a syntactic context we haven't handled yet. - break; - + // we're in a syntactic context we haven't handled yet. + break; + case Sema::NC_Type: Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Classification.getType()); Tok.setAnnotationEndLoc(NameLoc); PP.AnnotateCachedTokens(Tok); break; - + case Sema::NC_Expression: Tok.setKind(tok::annot_primary_expr); setExprAnnotation(Tok, Classification.getExpression()); Tok.setAnnotationEndLoc(NameLoc); PP.AnnotateCachedTokens(Tok); break; - + case Sema::NC_TypeTemplate: case Sema::NC_FunctionTemplate: { ConsumeToken(); // the identifier UnqualifiedId Id; Id.setIdentifier(Name, NameLoc); if (AnnotateTemplateIdToken( - TemplateTy::make(Classification.getTemplateName()), + TemplateTy::make(Classification.getTemplateName()), Classification.getTemplateNameKind(), SS, Id, SourceLocation(), /*AllowTypeAnnotation=*/false)) { @@ -172,10 +177,10 @@ Retry: SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); if (Tok.is(tok::semi)) ConsumeToken(); - return StmtError(); + return StmtError(); } - - // If the next token is '::', jump right into parsing a + + // If the next token is '::', jump right into parsing a // nested-name-specifier. We don't want to leave the template-id // hanging. if (NextToken().is(tok::coloncolon) && TryAnnotateCXXScopeToken(false)){ @@ -184,22 +189,22 @@ Retry: SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); if (Tok.is(tok::semi)) ConsumeToken(); - return StmtError(); + return StmtError(); } - + // We've annotated a template-id, so try again now. goto Retry; } - + case Sema::NC_NestedNameSpecifier: // FIXME: Implement this! break; } } - + // Fall through } - + default: { if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; @@ -224,10 +229,8 @@ Retry: case tok::l_brace: // C99 6.8.2: compound-statement return ParseCompoundStatement(attrs); case tok::semi: { // C99 6.8.3p3: expression[opt] ';' - SourceLocation LeadingEmptyMacroLoc; - if (Tok.hasLeadingEmptyMacro()) - LeadingEmptyMacroLoc = PP.getLastEmptyMacroExpansionLoc(); - return Actions.ActOnNullStmt(ConsumeToken(), LeadingEmptyMacroLoc); + bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro(); + return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro); } case tok::kw_if: // C99 6.8.4.1: if-statement @@ -297,7 +300,7 @@ Retry: StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { // If a case keyword is missing, this is where it should be inserted. Token OldToken = Tok; - + // FIXME: Use the attributes // expression[opt] ';' ExprResult Expr(ParseExpression()); @@ -310,18 +313,18 @@ StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { ConsumeToken(); return StmtError(); } - + if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() && Actions.CheckCaseExpression(Expr.get())) { // If a constant expression is followed by a colon inside a switch block, // suggest a missing case keyword. Diag(OldToken, diag::err_expected_case_before_expression) << FixItHint::CreateInsertion(OldToken.getLocation(), "case "); - + // Recover parsing as a case statement. return ParseCaseStatement(Attrs, /*MissingCase=*/true, Expr); } - + // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get())); @@ -458,12 +461,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) { // Broken substmt shouldn't prevent the label from being added to the AST. if (SubStmt.isInvalid()) SubStmt = Actions.ActOnNullStmt(ColonLoc); - + LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), IdentTok.getLocation()); if (AttributeList *Attrs = attrs.getList()) Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); - + return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc, SubStmt.get()); } @@ -499,7 +502,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which // gets updated each time a new case is parsed, and whose body is unset so // far. When parsing 'case 4', this is the 'case 3' node. - StmtTy *DeepestParsedCaseStmt = 0; + Stmt *DeepestParsedCaseStmt = 0; // While we have case statements, eat and stack them. SourceLocation ColonLoc; @@ -509,14 +512,15 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCase(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } - + /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'. /// Disable this form of error recovery while we're parsing the case /// expression. ColonProtectionRAIIObject ColonProtection(*this); - + ExprResult LHS(MissingCase ? Expr : ParseConstantExpression()); MissingCase = false; if (LHS.isInvalid()) { @@ -537,7 +541,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, return StmtError(); } } - + ColonProtection.restore(); if (Tok.is(tok::colon)) { @@ -554,7 +558,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } - + StmtResult Case = Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc, RHS.get(), ColonLoc); @@ -631,7 +635,7 @@ StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) { << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } - + // Diagnose the common error "switch (X) {... default: }", which is not valid. if (Tok.is(tok::r_brace)) { SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); @@ -704,8 +708,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { Tok.getLocation(), "in compound statement ('{}')"); InMessageExpressionRAIIObject InMessage(*this, false); - - SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'. + BalancedDelimiterTracker T(*this, tok::l_brace); + if (T.consumeOpen()) + return StmtError(); StmtVector Stmts(Actions); @@ -714,40 +719,40 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { while (Tok.is(tok::kw___label__)) { SourceLocation LabelLoc = ConsumeToken(); Diag(LabelLoc, diag::ext_gnu_local_label); - - llvm::SmallVector<Decl *, 8> DeclsInGroup; + + SmallVector<Decl *, 8> DeclsInGroup; while (1) { if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); break; } - + IdentifierInfo *II = Tok.getIdentifierInfo(); SourceLocation IdLoc = ConsumeToken(); DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc)); - + if (!Tok.is(tok::comma)) break; ConsumeToken(); } - + DeclSpec DS(AttrFactory); DeclGroupPtrTy Res = Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup.data(), DeclsInGroup.size()); StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation()); - + ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); if (R.isUsable()) Stmts.push_back(R.release()); } - + while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { if (Tok.is(tok::annot_pragma_unused)) { HandlePragmaUnused(); continue; } - if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) || + if (getLang().MicrosoftExt && (Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { ParseMicrosoftIfExistsStatement(Stmts); continue; @@ -803,13 +808,15 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // We broke out of the while loop because we found a '}' or EOF. if (Tok.isNot(tok::r_brace)) { Diag(Tok, diag::err_expected_rbrace); - Diag(LBraceLoc, diag::note_matching) << "{"; + Diag(T.getOpenLocation(), diag::note_matching) << "{"; return StmtError(); } - SourceLocation RBraceLoc = ConsumeBrace(); - return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts), - isStmtExpr); + if (T.consumeClose()) + return StmtError(); + + return Actions.ActOnCompoundStmt(T.getOpenLocation(), T.getCloseLocation(), + move_arg(Stmts), isStmtExpr); } /// ParseParenExprOrCondition: @@ -827,13 +834,15 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, Decl *&DeclResult, SourceLocation Loc, bool ConvertToBoolean) { - SourceLocation LParenLoc = ConsumeParen(); - if (getLang().CPlusPlus) + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + + if (getLang().CPlusPlus) ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); else { ExprResult = ParseExpression(); DeclResult = 0; - + // If required, convert to a boolean value. if (!ExprResult.isInvalid() && ConvertToBoolean) ExprResult @@ -852,7 +861,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, } // Otherwise the condition is valid or the rparen is present. - MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); return false; } @@ -950,9 +959,13 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { C99orCXX && Tok.isNot(tok::l_brace)); ElseStmt = ParseStatement(); - + // Pop the 'else' scope if needed. InnerScope.Exit(); + } else if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteAfterIf(getCurScope()); + cutOffParsing(); + return StmtError(); } IfScope.Exit(); @@ -1027,7 +1040,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar); if (Switch.isInvalid()) { - // Skip the switch body. + // Skip the switch body. // FIXME: This is not optimal recovery, but parsing the body is more // dangerous due to the presence of case and default statements, which // will have no place to connect back with the switch. @@ -1038,7 +1051,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { SkipUntil(tok::semi); return move(Switch); } - + // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1063,7 +1076,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { if (Body.isInvalid()) // FIXME: Remove the case statement list from the Switch statement. Body = Actions.ActOnNullStmt(Tok.getLocation()); - + return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get()); } @@ -1196,16 +1209,17 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { } // Parse the parenthesized condition. - SourceLocation LPLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); ExprResult Cond = ParseExpression(); - SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc); + T.consumeClose(); DoScope.Exit(); if (Cond.isInvalid() || Body.isInvalid()) return StmtError(); - return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, LPLoc, - Cond.get(), RPLoc); + return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(), + Cond.get(), T.getCloseLocation()); } /// ParseForStatement @@ -1265,7 +1279,9 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { ParseScope ForScope(this, ScopeFlags); - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + ExprResult Value; bool ForEach = false, ForRange = false; @@ -1276,14 +1292,15 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); Decl *SecondVar = 0; - + if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteOrdinaryName(getCurScope(), + Actions.CodeCompleteOrdinaryName(getCurScope(), C99orCXXorObjC? Sema::PCC_ForInit : Sema::PCC_Expression); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } - + // Parse the first part of the for specifier. if (Tok.is(tok::semi)) { // for (; // no first part, eat the ';'. @@ -1302,13 +1319,16 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; StmtVector Stmts(Actions); - DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, + DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, DeclEnd, attrs, false, MightBeForRangeStmt ? &ForRangeInit : 0); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInit.ParsedForRangeDecl()) { + if (!getLang().CPlusPlus0x) + Diag(ForRangeInit.ColonLoc, diag::ext_for_range); + ForRange = true; } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); @@ -1316,10 +1336,11 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { Actions.ActOnForEachDeclStmt(DG); // ObjC: for (id x in expr) ConsumeToken(); // consume 'in' - + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCForCollection(getCurScope(), DG); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } Collection = ParseExpression(); } else { @@ -1342,10 +1363,11 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { ConsumeToken(); } else if (ForEach) { ConsumeToken(); // consume 'in' - + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCForCollection(getCurScope(), DeclGroupPtrTy()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } Collection = ParseExpression(); } else { @@ -1373,7 +1395,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { else { Second = ParseExpression(); if (!Second.isInvalid()) - Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, + Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, Second.get()); } SecondPartIsInvalid = Second.isInvalid(); @@ -1399,18 +1421,27 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { } } // Match the ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); // We need to perform most of the semantic analysis for a C++0x for-range // statememt before parsing the body, in order to be able to deduce the type // of an auto-typed loop variable. StmtResult ForRangeStmt; - if (ForRange) - ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, LParenLoc, + if (ForRange) { + ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, T.getOpenLocation(), FirstPart.take(), ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), - RParenLoc); + T.getCloseLocation()); + + + // Similarly, we need to do the semantic analysis for a for-range + // statement immediately in order to close over temporaries correctly. + } else if (ForEach) { + if (!Collection.isInvalid()) + Collection = + Actions.ActOnObjCForCollectionOperand(ForLoc, Collection.take()); + } // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1439,18 +1470,18 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { return StmtError(); if (ForEach) - // FIXME: It isn't clear how to communicate the late destruction of - // C++ temporaries used to create the collection. - return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, - FirstPart.take(), - Collection.take(), RParenLoc, - Body.take()); + return Actions.ActOnObjCForCollectionStmt(ForLoc, T.getOpenLocation(), + FirstPart.take(), + Collection.take(), + T.getCloseLocation(), + Body.take()); if (ForRange) return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); - return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart, - SecondVar, ThirdPart, RParenLoc, Body.take()); + return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.take(), + SecondPart, SecondVar, ThirdPart, + T.getCloseLocation(), Body.take()); } /// ParseGotoStatement @@ -1529,11 +1560,10 @@ StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) { if (Tok.isNot(tok::semi)) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteReturn(getCurScope()); - ConsumeCodeCompletionToken(); - SkipUntil(tok::semi, false, true); + cutOffParsing(); return StmtError(); } - + // FIXME: This is a hack to allow something like C++0x's generalized // initializer lists, but only enough of this feature to allow Clang to // parse libstdc++ 4.5's headers. @@ -1552,30 +1582,105 @@ StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) { return Actions.ActOnReturnStmt(ReturnLoc, R.take()); } -/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this -/// routine is called to skip/ignore tokens that comprise the MS asm statement. -StmtResult Parser::FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc) { - SourceLocation EndLoc; - if (Tok.is(tok::l_brace)) { - unsigned short savedBraceCount = BraceCount; - do { - EndLoc = Tok.getLocation(); - ConsumeAnyToken(); - } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof)); - } else { - // From the MS website: If used without braces, the __asm keyword means - // that the rest of the line is an assembly-language statement. - SourceManager &SrcMgr = PP.getSourceManager(); +/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, +/// this routine is called to collect the tokens for an MS asm statement. +StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { + SourceManager &SrcMgr = PP.getSourceManager(); + SourceLocation EndLoc = AsmLoc; + do { + bool InBraces = false; + unsigned short savedBraceCount = 0; + bool InAsmComment = false; + FileID FID; + unsigned LineNo = 0; + unsigned NumTokensRead = 0; + SourceLocation LBraceLoc; + + if (Tok.is(tok::l_brace)) { + // Braced inline asm: consume the opening brace. + InBraces = true; + savedBraceCount = BraceCount; + EndLoc = LBraceLoc = ConsumeBrace(); + ++NumTokensRead; + } else { + // Single-line inline asm; compute which line it is on. + std::pair<FileID, unsigned> ExpAsmLoc = + SrcMgr.getDecomposedExpansionLoc(EndLoc); + FID = ExpAsmLoc.first; + LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second); + } + SourceLocation TokLoc = Tok.getLocation(); - unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc); do { + // If we hit EOF, we're done, period. + if (Tok.is(tok::eof)) + break; + // When we consume the closing brace, we're done. + if (InBraces && BraceCount == savedBraceCount) + break; + + if (!InAsmComment && Tok.is(tok::semi)) { + // A semicolon in an asm is the start of a comment. + InAsmComment = true; + if (InBraces) { + // Compute which line the comment is on. + std::pair<FileID, unsigned> ExpSemiLoc = + SrcMgr.getDecomposedExpansionLoc(TokLoc); + FID = ExpSemiLoc.first; + LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second); + } + } else if (!InBraces || InAsmComment) { + // If end-of-line is significant, check whether this token is on a + // new line. + std::pair<FileID, unsigned> ExpLoc = + SrcMgr.getDecomposedExpansionLoc(TokLoc); + if (ExpLoc.first != FID || + SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { + // If this is a single-line __asm, we're done. + if (!InBraces) + break; + // We're no longer in a comment. + InAsmComment = false; + } else if (!InAsmComment && Tok.is(tok::r_brace)) { + // Single-line asm always ends when a closing brace is seen. + // FIXME: This is compatible with Apple gcc's -fasm-blocks; what + // does MSVC do here? + break; + } + } + + // Consume the next token; make sure we don't modify the brace count etc. + // if we are in a comment. EndLoc = TokLoc; - ConsumeAnyToken(); + if (InAsmComment) + PP.Lex(Tok); + else + ConsumeAnyToken(); TokLoc = Tok.getLocation(); - } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) && - Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) && - Tok.isNot(tok::eof)); - } + ++NumTokensRead; + } while (1); + + if (InBraces && BraceCount != savedBraceCount) { + // __asm without closing brace (this can happen at EOF). + Diag(Tok, diag::err_expected_rbrace); + Diag(LBraceLoc, diag::note_matching) << "{"; + return StmtError(); + } else if (NumTokensRead == 0) { + // Empty __asm. + Diag(Tok, diag::err_expected_lbrace); + return StmtError(); + } + // Multiple adjacent asm's form together into a single asm statement + // in the AST. + if (!Tok.is(tok::kw_asm)) + break; + EndLoc = ConsumeToken(); + } while (1); + // FIXME: Need to actually grab the data and pass it on to Sema. Ideally, + // what Sema wants is a string of the entire inline asm, with one instruction + // per line and all the __asm keywords stripped out, and a way of mapping + // from any character of that string to its location in the original source + // code. I'm not entirely sure how to go about that, though. Token t; t.setKind(tok::string_literal); t.setLiteralData("\"/*FIXME: not done*/\""); @@ -1611,20 +1716,24 @@ StmtResult Parser::FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc) { /// asm-clobbers ',' asm-string-literal /// /// [MS] ms-asm-statement: -/// '__asm' assembly-instruction ';'[opt] -/// '__asm' '{' assembly-instruction-list '}' ';'[opt] +/// ms-asm-block +/// ms-asm-block ms-asm-statement +/// +/// [MS] ms-asm-block: +/// '__asm' ms-asm-line '\n' +/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt] /// -/// [MS] assembly-instruction-list: -/// assembly-instruction ';'[opt] -/// assembly-instruction-list ';' assembly-instruction ';'[opt] +/// [MS] ms-asm-instruction-block +/// ms-asm-line +/// ms-asm-line '\n' ms-asm-instruction-block /// StmtResult Parser::ParseAsmStatement(bool &msAsm) { assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); - if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { + if (getLang().MicrosoftExt && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { msAsm = true; - return FuzzyParseMicrosoftAsmStatement(AsmLoc); + return ParseMicrosoftAsmStatement(AsmLoc); } DeclSpec DS(AttrFactory); SourceLocation Loc = Tok.getLocation(); @@ -1643,25 +1752,26 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { SkipUntil(tok::r_paren); return StmtError(); } - Loc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); ExprResult AsmString(ParseAsmStringLiteral()); if (AsmString.isInvalid()) return StmtError(); - llvm::SmallVector<IdentifierInfo *, 4> Names; + SmallVector<IdentifierInfo *, 4> Names; ExprVector Constraints(Actions); ExprVector Exprs(Actions); ExprVector Clobbers(Actions); if (Tok.is(tok::r_paren)) { // We have a simple asm expression like 'asm("foo")'. - SourceLocation RParenLoc = ConsumeParen(); + T.consumeClose(); return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, - /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, + /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, move_arg(Constraints), move_arg(Exprs), AsmString.take(), move_arg(Clobbers), - RParenLoc); + T.getCloseLocation()); } // Parse Outputs, if present. @@ -1670,12 +1780,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { // In C++ mode, parse "::" like ": :". AteExtraColon = Tok.is(tok::coloncolon); ConsumeToken(); - + if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) return StmtError(); } - + unsigned NumOutputs = Names.size(); // Parse Inputs, if present. @@ -1688,7 +1798,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { AteExtraColon = Tok.is(tok::coloncolon); ConsumeToken(); } - + if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) return StmtError(); @@ -1721,12 +1831,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { } } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc); + T.consumeClose(); return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(), move_arg(Constraints), move_arg(Exprs), AsmString.take(), move_arg(Clobbers), - RParenLoc); + T.getCloseLocation()); } /// ParseAsmOperands - Parse the asm-operands production as used by @@ -1742,9 +1852,9 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { /// // // FIXME: Avoid unnecessary std::string trashing. -bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, - llvm::SmallVectorImpl<ExprTy *> &Constraints, - llvm::SmallVectorImpl<ExprTy *> &Exprs) { +bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, + SmallVectorImpl<Expr *> &Constraints, + SmallVectorImpl<Expr *> &Exprs) { // 'asm-operands' isn't present? if (!isTokenStringLiteral() && Tok.isNot(tok::l_square)) return false; @@ -1752,7 +1862,8 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, while (1) { // Read the [id] if present. if (Tok.is(tok::l_square)) { - SourceLocation Loc = ConsumeBracket(); + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); @@ -1764,7 +1875,7 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, ConsumeToken(); Names.push_back(II); - MatchRHSPunctuation(tok::r_square, Loc); + T.consumeClose(); } else Names.push_back(0); @@ -1782,9 +1893,10 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, } // Read the parenthesized expression. - SourceLocation OpenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); ExprResult Res(ParseExpression()); - MatchRHSPunctuation(tok::r_paren, OpenLoc); + T.consumeClose(); if (Res.isInvalid()) { SkipUntil(tok::r_paren); return true; @@ -1808,7 +1920,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { return Actions.ActOnFinishFunctionBody(Decl, 0); } } - + PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); @@ -1841,6 +1953,8 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { // Constructor initializer list? if (Tok.is(tok::colon)) ParseConstructorInitializer(Decl); + else + Actions.ActOnDefaultCtorInitializers(Decl); if (PP.isCodeCompletionEnabled()) { if (trySkippingFunctionBodyForCodeCompletion()) { @@ -1977,8 +2091,8 @@ StmtResult Parser::ParseCXXCatchBlock() { SourceLocation CatchLoc = ConsumeToken(); - SourceLocation LParenLoc = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) return StmtError(); // C++ 3.3.2p3: @@ -1999,7 +2113,8 @@ StmtResult Parser::ParseCXXCatchBlock() { } else ConsumeToken(); - if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid()) + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return StmtError(); if (Tok.isNot(tok::l_brace)) @@ -2018,7 +2133,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { bool Result; if (ParseMicrosoftIfExistsCondition(Result)) return; - + if (Tok.isNot(tok::l_brace)) { Diag(Tok, diag::err_expected_lbrace); return; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 9eab40a..3d68a4a 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -26,12 +26,16 @@ using namespace clang; Decl * Parser::ParseDeclarationStartingWithTemplate(unsigned Context, SourceLocation &DeclEnd, - AccessSpecifier AS) { - if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) + AccessSpecifier AS, + AttributeList *AccessAttrs) { + ObjCDeclContextSwitch ObjCDC(*this); + + if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) { return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(), - DeclEnd); - - return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS); + DeclEnd); + } + return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS, + AccessAttrs); } /// \brief RAII class that manages the template parameter depth. @@ -75,7 +79,8 @@ namespace { Decl * Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, SourceLocation &DeclEnd, - AccessSpecifier AS) { + AccessSpecifier AS, + AttributeList *AccessAttrs) { assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) && "Token does not start a template declaration."); @@ -129,7 +134,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, // Parse the '<' template-parameter-list '>' SourceLocation LAngleLoc, RAngleLoc; - llvm::SmallVector<Decl*, 4> TemplateParams; + SmallVector<Decl*, 4> TemplateParams; if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc, RAngleLoc)) { // Skip until the semi-colon or a }. @@ -159,7 +164,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, isSpecialization, LastParamListWasEmpty), ParsingTemplateParams, - DeclEnd, AS); + DeclEnd, AS, AccessAttrs); } /// \brief Parse a single declaration that declares a template, @@ -188,13 +193,15 @@ Parser::ParseSingleDeclarationAfterTemplate( const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd, - AccessSpecifier AS) { + AccessSpecifier AS, + AttributeList *AccessAttrs) { assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && "Template information required"); if (Context == Declarator::MemberContext) { // We are parsing a member template. - ParseCXXClassMemberDeclaration(AS, TemplateInfo, &DiagsFromTParams); + ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo, + &DiagsFromTParams); return 0; } @@ -289,7 +296,7 @@ Parser::ParseSingleDeclarationAfterTemplate( /// /// \returns true if an error occurred, false otherwise. bool Parser::ParseTemplateParameters(unsigned Depth, - llvm::SmallVectorImpl<Decl*> &TemplateParams, + SmallVectorImpl<Decl*> &TemplateParams, SourceLocation &LAngleLoc, SourceLocation &RAngleLoc) { // Get the template parameter list. @@ -322,7 +329,7 @@ bool Parser::ParseTemplateParameters(unsigned Depth, /// template-parameter-list ',' template-parameter bool Parser::ParseTemplateParameterList(unsigned Depth, - llvm::SmallVectorImpl<Decl*> &TemplateParams) { + SmallVectorImpl<Decl*> &TemplateParams) { while (1) { if (Decl *TmpParam = ParseTemplateParameter(Depth, TemplateParams.size())) { @@ -468,8 +475,10 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { Ellipsis = true; EllipsisLoc = ConsumeToken(); - if (!getLang().CPlusPlus0x) - Diag(EllipsisLoc, diag::ext_variadic_templates); + Diag(EllipsisLoc, + getLang().CPlusPlus0x + ? diag::warn_cxx98_compat_variadic_templates + : diag::ext_variadic_templates); } // Grab the template parameter name (if given) @@ -516,7 +525,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { // Handle the template <...> part. SourceLocation TemplateLoc = ConsumeToken(); - llvm::SmallVector<Decl*,8> TemplateParams; + SmallVector<Decl*,8> TemplateParams; SourceLocation LAngleLoc, RAngleLoc; { ParseScope TemplateParmScope(this, Scope::TemplateParamScope); @@ -540,8 +549,10 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { if (Tok.is(tok::ellipsis)) { EllipsisLoc = ConsumeToken(); - if (!getLang().CPlusPlus0x) - Diag(EllipsisLoc, diag::ext_variadic_templates); + Diag(EllipsisLoc, + getLang().CPlusPlus0x + ? diag::warn_cxx98_compat_variadic_templates + : diag::ext_variadic_templates); } // Get the identifier, if given. @@ -558,7 +569,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { return 0; } - TemplateParamsTy *ParamList = + TemplateParameterList *ParamList = Actions.ActOnTemplateParameterList(Depth, SourceLocation(), TemplateLoc, LAngleLoc, TemplateParams.data(), @@ -1157,6 +1168,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { FD = cast<FunctionDecl>(LMT.D); // Reinject the template parameters. + SmallVector<ParseScope*, 4> TemplateParamScopeStack; DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD); if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); @@ -1164,17 +1176,31 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { } else { Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); + // Get the list of DeclContext to reenter. + SmallVector<DeclContext*, 4> DeclContextToReenter; DeclContext *DD = FD->getLexicalParent(); while (DD && DD->isRecord()) { - if (ClassTemplatePartialSpecializationDecl* MD = - dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(DD)) - Actions.ActOnReenterTemplateScope(getCurScope(), MD); - else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(DD)) - Actions.ActOnReenterTemplateScope(getCurScope(), - MD->getDescribedClassTemplate()); - + DeclContextToReenter.push_back(DD); DD = DD->getLexicalParent(); } + + // Reenter template scopes from outmost to innermost. + SmallVector<DeclContext*, 4>::reverse_iterator II = + DeclContextToReenter.rbegin(); + for (; II != DeclContextToReenter.rend(); ++II) { + if (ClassTemplatePartialSpecializationDecl* MD = + dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) { + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope)); + Actions.ActOnReenterTemplateScope(getCurScope(), MD); + } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) { + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope, + MD->getDescribedClassTemplate() != 0 )); + Actions.ActOnReenterTemplateScope(getCurScope(), + MD->getDescribedClassTemplate()); + } + } } assert(!LMT.Toks.empty() && "Empty body!"); @@ -1205,21 +1231,25 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { if (Tok.is(tok::kw_try)) { ParseFunctionTryBlock(LMT.D, FnScope); - return; - } - if (Tok.is(tok::colon)) { - ParseConstructorInitializer(LMT.D); + } else { + if (Tok.is(tok::colon)) + ParseConstructorInitializer(LMT.D); + else + Actions.ActOnDefaultCtorInitializers(LMT.D); - // Error recovery. - if (!Tok.is(tok::l_brace)) { + if (Tok.is(tok::l_brace)) { + ParseFunctionStatementBody(LMT.D, FnScope); + Actions.MarkAsLateParsedTemplate(FD, false); + } else Actions.ActOnFinishFunctionBody(LMT.D, 0); - return; - } - } else - Actions.ActOnDefaultCtorInitializers(LMT.D); + } - ParseFunctionStatementBody(LMT.D, FnScope); - Actions.MarkAsLateParsedTemplate(FD, false); + // Exit scopes. + FnScope.Exit(); + SmallVector<ParseScope*, 4>::reverse_iterator I = + TemplateParamScopeStack.rbegin(); + for (; I != TemplateParamScopeStack.rend(); ++I) + delete *I; DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D); if (grp) @@ -1229,15 +1259,10 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { /// \brief Lex a delayed template function for late parsing. void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { tok::TokenKind kind = Tok.getKind(); - // We may have a constructor initializer or function-try-block here. - if (kind == tok::colon || kind == tok::kw_try) - ConsumeAndStoreUntil(tok::l_brace, Toks); - else { - Toks.push_back(Tok); - ConsumeBrace(); + if (!ConsumeAndStoreFunctionPrologue(Toks)) { + // Consume everything up to (and including) the matching right brace. + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); } - // Consume everything up to (and including) the matching right brace. - ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); // If we're in a function-try-block, we need to store all the catch blocks. if (kind == tok::kw_try) { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index 2ba0fc6..d53839f 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -377,6 +377,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { /// /// [C++0x] attribute-specifier: /// '[' '[' attribute-list ']' ']' +/// alignment-specifier /// /// [C++0x] attribute-list: /// attribute[opt] @@ -409,6 +410,9 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { /// any token but '(', ')', '[', ']', '{', or '}' bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing, tok::TokenKind *After) { + if (Tok.is(tok::kw_alignas)) + return true; + if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) return false; @@ -552,7 +556,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) || Tok.is(tok::kw___fastcall) || - Tok.is(tok::kw___thiscall)) + Tok.is(tok::kw___thiscall) || + Tok.is(tok::kw___unaligned)) return TPResult::True(); // attributes indicate declaration TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); if (TPR != TPResult::Ambiguous()) @@ -605,8 +610,14 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { // Obviously starts an expression. case tok::numeric_constant: case tok::char_constant: + case tok::wide_char_constant: + case tok::utf16_char_constant: + case tok::utf32_char_constant: case tok::string_literal: case tok::wide_string_literal: + case tok::utf8_string_literal: + case tok::utf16_string_literal: + case tok::utf32_string_literal: case tok::l_square: case tok::l_paren: case tok::amp: @@ -674,6 +685,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw_const: case tok::kw_double: case tok::kw_enum: + case tok::kw_half: case tok::kw_float: case tok::kw_int: case tok::kw_long: @@ -705,8 +717,10 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___unaligned: case tok::kw___vector: case tok::kw___pixel: + case tok::kw__Atomic: return TPResult::False(); default: @@ -863,6 +877,9 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw_virtual: case tok::kw_explicit: + // Modules + case tok::kw___module_private__: + // type-specifier: // simple-type-specifier // class-specifier @@ -896,7 +913,9 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw___thiscall: case tok::kw___w64: case tok::kw___ptr64: + case tok::kw___ptr32: case tok::kw___forceinline: + case tok::kw___unaligned: return TPResult::True(); // Borland @@ -976,6 +995,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: + case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw_void: @@ -1016,6 +1036,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw___underlying_type: return TPResult::True(); + // C1x _Atomic + case tok::kw__Atomic: + return TPResult::True(); + default: return TPResult::False(); } diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 5c50290..c909643 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -72,7 +72,7 @@ Parser::Parser(Preprocessor &pp, Sema &actions) /// If a crash happens while the parser is active, print out a line indicating /// what the current token is. -void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const { +void PrettyStackTraceParserEntry::print(raw_ostream &OS) const { const Token &Tok = P.getCurToken(); if (Tok.is(tok::eof)) { OS << "<eof> parser at end of file\n"; @@ -122,34 +122,6 @@ void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK, << FixItHint::CreateInsertion(EndLoc, ")"); } -/// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'), -/// this helper function matches and consumes the specified RHS token if -/// present. If not present, it emits a corresponding diagnostic indicating -/// that the parser failed to match the RHS of the token at LHSLoc. -SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok, - SourceLocation LHSLoc) { - - if (Tok.is(RHSTok)) - return ConsumeAnyToken(); - - SourceLocation R = Tok.getLocation(); - const char *LHSName = "unknown"; - diag::kind DID = diag::err_parse_error; - switch (RHSTok) { - default: break; - case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break; - case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break; - case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break; - case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break; - case tok::greatergreatergreater: - LHSName = "<<<"; DID = diag::err_expected_ggg; break; - } - Diag(Tok, DID); - Diag(LHSLoc, diag::note_matching) << LHSName; - SkipUntil(RHSTok); - return R; -} - static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { switch (ExpectedTok) { case tok::semi: return Tok.is(tok::colon); // : for ; @@ -298,6 +270,9 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, case tok::string_literal: case tok::wide_string_literal: + case tok::utf8_string_literal: + case tok::utf16_string_literal: + case tok::utf32_string_literal: ConsumeStringToken(); break; @@ -440,6 +415,7 @@ void Parser::Initialize() { ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref"); } + Ident_instancetype = 0; Ident_final = 0; Ident_override = 0; @@ -550,7 +526,12 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS) { DelayedCleanupPoint CleanupRAII(TopLevelDeclCleanupPool); ParenBraceBracketBalancer BalancerRAIIObj(*this); - + + if (PP.isCodeCompletionReached()) { + cutOffParsing(); + return DeclGroupPtrTy(); + } + Decl *SingleDecl = 0; switch (Tok.getKind()) { case tok::semi: @@ -590,10 +571,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, break; } case tok::at: - // @ is not a legal token unless objc is enabled, no need to check for ObjC. - /// FIXME: ParseObjCAtDirectives should return a DeclGroup for things like - /// @class foo, bar; - SingleDecl = ParseObjCAtDirectives(); + return ParseObjCAtDirectives(); break; case tok::minus: case tok::plus: @@ -608,8 +586,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Actions.CodeCompleteOrdinaryName(getCurScope(), ObjCImpDecl? Sema::PCC_ObjCImplementation : Sema::PCC_Namespace); - ConsumeCodeCompletionToken(); - return ParseExternalDeclaration(attrs); + cutOffParsing(); + return DeclGroupPtrTy(); case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -676,6 +654,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParseMicrosoftIfExistsExternalDeclaration(); return DeclGroupPtrTy(); + case tok::kw___import_module__: + return ParseModuleImport(); + default: dont_know: // We can't tell whether this is a function-definition or declaration yet. @@ -808,6 +789,11 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, AccessSpecifier AS) { ParsingDeclSpec DS(*this); DS.takeAttributesFrom(attrs); + // Must temporarily exit the objective-c container scope for + // parsing c constructs and re-enter objc container scope + // afterwards. + ObjCDeclContextSwitch ObjCDC(*this); + return ParseDeclarationOrFunctionDefinition(DS, AS); } @@ -877,9 +863,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); + D.setFunctionDefinition(true); Decl *DP = Actions.HandleDeclarator(ParentScope, D, - move(TemplateParameterLists), - /*IsFunctionDefinition=*/true); + move(TemplateParameterLists)); D.complete(DP); D.getMutableDeclSpec().abort(); @@ -1133,13 +1119,12 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { ConsumeToken(); } - if (Tok.isNot(tok::l_paren)) { + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { Diag(Tok, diag::err_expected_lparen_after) << "asm"; return ExprError(); } - Loc = ConsumeParen(); - ExprResult Result(ParseAsmStringLiteral()); if (Result.isInvalid()) { @@ -1148,9 +1133,10 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { *EndLoc = Tok.getLocation(); ConsumeAnyToken(); } else { - Loc = MatchRHSPunctuation(tok::r_paren, Loc); + // Close the paren and get the location of the end bracket + T.consumeClose(); if (EndLoc) - *EndLoc = Loc; + *EndLoc = T.getCloseLocation(); } return move(Result); @@ -1190,7 +1176,7 @@ TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) { /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. -bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { +bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) && "Cannot be a type or scope token!"); @@ -1208,7 +1194,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { 0, /*IsTypename*/true)) return true; if (!SS.isSet()) { - if (getLang().Microsoft) + if (getLang().MicrosoftExt) Diag(Tok.getLocation(), diag::warn_expected_qualified_after_typename); else Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); @@ -1264,13 +1250,18 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { return true; if (Tok.is(tok::identifier)) { + IdentifierInfo *CorrectedII = 0; // Determine whether the identifier is a type name. if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, NextToken().is(tok::period), ParsedType(), - /*NonTrivialTypeSourceInfo*/true)) { + /*NonTrivialTypeSourceInfo*/true, + NeedType ? &CorrectedII : NULL)) { + // A FixIt was applied as a result of typo correction + if (CorrectedII) + Tok.setIdentifierInfo(CorrectedII); // This is a typename. Replace the current token in-place with an // annotation type token. Tok.setKind(tok::annot_typename); @@ -1405,20 +1396,27 @@ bool Parser::isTokenEqualOrMistypedEqualEqual(unsigned DiagID) { return Tok.is(tok::equal); } -void Parser::CodeCompletionRecovery() { +SourceLocation Parser::handleUnexpectedCodeCompletionToken() { + assert(Tok.is(tok::code_completion)); + PrevTokLocation = Tok.getLocation(); + for (Scope *S = getCurScope(); S; S = S->getParent()) { if (S->getFlags() & Scope::FnScope) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_RecoveryInFunction); - return; + cutOffParsing(); + return PrevTokLocation; } if (S->getFlags() & Scope::ClassScope) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class); - return; + cutOffParsing(); + return PrevTokLocation; } } Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace); + cutOffParsing(); + return PrevTokLocation; } // Anchor the Parser::FieldCallback vtable to this translation unit. @@ -1463,13 +1461,12 @@ bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) { Token Condition = Tok; SourceLocation IfExistsLoc = ConsumeToken(); - SourceLocation LParenLoc = Tok.getLocation(); - if (Tok.isNot(tok::l_paren)) { + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc; SkipUntil(tok::semi); return true; } - ConsumeParen(); // eat the '('. // Parse nested-name-specifier. CXXScopeSpec SS; @@ -1488,7 +1485,8 @@ bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) { return true; } - if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid()) + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return true; // Check if the symbol exists. @@ -1533,3 +1531,86 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { } ConsumeBrace(); } + +Parser::DeclGroupPtrTy Parser::ParseModuleImport() { + assert(Tok.is(tok::kw___import_module__) && + "Improper start to module import"); + SourceLocation ImportLoc = ConsumeToken(); + + // Parse the module name. + if (!Tok.is(tok::identifier)) { + Diag(Tok, diag::err_module_expected_ident); + SkipUntil(tok::semi); + return DeclGroupPtrTy(); + } + + IdentifierInfo &ModuleName = *Tok.getIdentifierInfo(); + SourceLocation ModuleNameLoc = ConsumeToken(); + DeclResult Import = Actions.ActOnModuleImport(ImportLoc, ModuleName, ModuleNameLoc); + ExpectAndConsumeSemi(diag::err_module_expected_semi); + if (Import.isInvalid()) + return DeclGroupPtrTy(); + + return Actions.ConvertDeclToDeclGroup(Import.get()); +} + +bool Parser::BalancedDelimiterTracker::consumeOpen() { + // Try to consume the token we are holding + if (P.Tok.is(Kind)) { + P.QuantityTracker.push(Kind); + Cleanup = true; + if (P.QuantityTracker.getDepth(Kind) < MaxDepth) { + LOpen = P.ConsumeAnyToken(); + return false; + } else { + P.Diag(P.Tok, diag::err_parser_impl_limit_overflow); + P.SkipUntil(tok::eof); + } + } + return true; +} + +bool Parser::BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, + const char *Msg, + tok::TokenKind SkipToToc ) { + LOpen = P.Tok.getLocation(); + if (!P.ExpectAndConsume(Kind, DiagID, Msg, SkipToToc)) { + P.QuantityTracker.push(Kind); + Cleanup = true; + if (P.QuantityTracker.getDepth(Kind) < MaxDepth) { + return false; + } else { + P.Diag(P.Tok, diag::err_parser_impl_limit_overflow); + P.SkipUntil(tok::eof); + } + } + return true; +} + +bool Parser::BalancedDelimiterTracker::consumeClose() { + if (P.Tok.is(Close)) { + LClose = P.ConsumeAnyToken(); + if (Cleanup) + P.QuantityTracker.pop(Kind); + + Cleanup = false; + return false; + } else { + const char *LHSName = "unknown"; + diag::kind DID = diag::err_parse_error; + switch (Close) { + default: break; + case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break; + case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break; + case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break; + case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break; + case tok::greatergreatergreater: + LHSName = "<<<"; DID = diag::err_expected_ggg; break; + } + P.Diag(P.Tok, DID); + P.Diag(LOpen, diag::note_matching) << LHSName; + if (P.SkipUntil(Close)) + LClose = P.Tok.getLocation(); + } + return true; +} diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h index 3765f92..ef17aee 100644 --- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h +++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h @@ -30,9 +30,9 @@ namespace clang { class ExtensionRAIIObject { void operator=(const ExtensionRAIIObject &); // DO NOT IMPLEMENT ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT - Diagnostic &Diags; + DiagnosticsEngine &Diags; public: - ExtensionRAIIObject(Diagnostic &diags) : Diags(diags) { + ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) { Diags.IncrementAllExtensionsSilenced(); } |