diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
17 files changed, 4984 insertions, 3664 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp index 5678ece..0f5a1b3 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp @@ -23,9 +23,9 @@ #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaConsumer.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CrashRecoveryContext.h" #include <cstdio> +#include <memory> using namespace clang; @@ -36,7 +36,7 @@ class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { const Parser &P; public: PrettyStackTraceParserEntry(const Parser &p) : P(p) {} - virtual void print(raw_ostream &OS) const; + void print(raw_ostream &OS) const override; }; /// If a crash happens while the parser is active, print out a line indicating @@ -88,7 +88,8 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, CodeCompleteConsumer *CompletionConsumer, bool SkipFunctionBodies) { - OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); + std::unique_ptr<Sema> S( + new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); @@ -109,8 +110,8 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { ASTConsumer *Consumer = &S.getASTConsumer(); - OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S, - SkipFunctionBodies)); + std::unique_ptr<Parser> ParseOP( + new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); PrettyStackTraceParserEntry CrashInfo(P); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index 7792305..30a9120 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -19,13 +19,6 @@ #include "clang/Sema/Scope.h" using namespace clang; -/// Get the FunctionDecl for a function or function template decl. -static FunctionDecl *getFunctionDecl(Decl *D) { - if (FunctionDecl *fn = dyn_cast<FunctionDecl>(D)) - return fn; - return cast<FunctionTemplateDecl>(D)->getTemplatedDecl(); -} - /// 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. @@ -42,8 +35,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, "Current token not a '{', ':', '=', or 'try'!"); MultiTemplateParamsArg TemplateParams( - TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, - TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); + TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() + : nullptr, + TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); NamedDecl *FnD; D.setFunctionDefinitionKind(DefinitionKind); @@ -52,7 +46,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, TemplateParams); else { FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, - TemplateParams, 0, + TemplateParams, nullptr, VS, ICIS_NoInit); if (FnD) { Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs); @@ -69,30 +63,24 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, D.complete(FnD); - if (Tok.is(tok::equal)) { - ConsumeToken(); - + if (TryConsumeToken(tok::equal)) { if (!FnD) { SkipUntil(tok::semi); - return 0; + return nullptr; } bool Delete = false; SourceLocation KWLoc; - if (Tok.is(tok::kw_delete)) { - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_deleted_function : - diag::ext_deleted_function); - - KWLoc = ConsumeToken(); + if (TryConsumeToken(tok::kw_delete, KWLoc)) { + Diag(KWLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_deleted_function + : diag::ext_deleted_function); Actions.SetDeclDeleted(FnD, KWLoc); Delete = true; - } else if (Tok.is(tok::kw_default)) { - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_defaulted_function : - diag::ext_defaulted_function); - - KWLoc = ConsumeToken(); + } else if (TryConsumeToken(tok::kw_default, KWLoc)) { + Diag(KWLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_defaulted_function + : diag::ext_defaulted_function); Actions.SetDeclDefaulted(FnD, KWLoc); } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); @@ -102,9 +90,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) << Delete; SkipUntil(tok::semi); - } else { - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - Delete ? "delete" : "default", tok::semi); + } else if (ExpectAndConsume(tok::semi, diag::err_expected_after, + Delete ? "delete" : "default")) { + SkipUntil(tok::semi); } return FnD; @@ -115,9 +103,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, // the tokens and store them for parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && DefinitionKind == FDK_Definition && - !D.getDeclSpec().isConstexprSpecified() && - !(FnD && getFunctionDecl(FnD) && - getFunctionDecl(FnD)->getResultType()->getContainedAutoType()) && + !D.getDeclSpec().isConstexprSpecified() && + !(FnD && FnD->getAsFunction() && + FnD->getAsFunction()->getReturnType()->getContainedAutoType()) && ((Actions.CurContext->isDependentContext() || (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) && @@ -127,7 +115,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, LexTemplateFunctionForLateParsing(Toks); if (FnD) { - FunctionDecl *FD = getFunctionDecl(FnD); + FunctionDecl *FD = FnD->getAsFunction(); Actions.CheckForFunctionRedefinition(FD); Actions.MarkAsLateParsedTemplate(FD, FnD, Toks); } @@ -179,7 +167,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, // If you remove this, you can remove the code that clears the flag // after parsing the member. if (D.getDeclSpec().isFriendSpecified()) { - FunctionDecl *FD = getFunctionDecl(FnD); + FunctionDecl *FD = FnD->getAsFunction(); Actions.CheckForFunctionRedefinition(FD); FD->setLateTemplateParsed(true); } @@ -275,7 +263,8 @@ void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() { /// delayed (such as default arguments) and parse them. void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; - ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); + ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, + HasTemplateScope); TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); if (HasTemplateScope) { Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); @@ -288,14 +277,16 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, HasClassScope); if (HasClassScope) - Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); + Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), + Class.TagOrTemplate); for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations(); } if (HasClassScope) - Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); + Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), + Class.TagOrTemplate); } void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { @@ -315,7 +306,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { Scope::FunctionDeclarationScope | Scope::DeclScope); for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { // Introduce the parameter into scope. - Actions.ActOnDelayedCXXMethodParameter(getCurScope(), + Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { @@ -346,11 +337,10 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { } else DefArgResult = ParseAssignmentExpression(); if (DefArgResult.isInvalid()) - Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); + Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param, + EqualLoc); else { - if (Tok.is(tok::cxx_defaultarg_end)) - ConsumeToken(); - else { + if (!TryConsumeToken(tok::cxx_defaultarg_end)) { // The last two tokens are the terminator and the saved value of // Tok; the last token in the default argument is the one before // those. @@ -360,7 +350,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { (*Toks)[Toks->size() - 3].getLocation()); } Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, - DefArgResult.take()); + DefArgResult.get()); } assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, @@ -372,7 +362,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { ConsumeAnyToken(); delete Toks; - LM.DefaultArgs[I].Toks = 0; + LM.DefaultArgs[I].Toks = nullptr; } } @@ -446,7 +436,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { // Error recovery. if (!Tok.is(tok::l_brace)) { FnScope.Exit(); - Actions.ActOnFinishFunctionBody(LM.D, 0); + Actions.ActOnFinishFunctionBody(LM.D, nullptr); while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); return; @@ -464,7 +454,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { ParseFunctionStatementBody(LM.D, FnScope); // Clear the late-template-parsed bit if we set it before. - if (LM.D) getFunctionDecl(LM.D)->setLateTemplateParsed(false); + if (LM.D) + LM.D->getAsFunction()->setLateTemplateParsed(false); if (Tok.getLocation() != origLoc) { // Due to parsing error, we either went over the cached tokens or @@ -477,6 +468,9 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); } + + if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D)) + Actions.ActOnFinishInlineMethodDef(MD); } /// ParseLexedMemberInitializers - We finished parsing the member specification @@ -536,10 +530,13 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { SourceLocation EqualLoc; + Actions.ActOnStartCXXInClassMemberInitializer(); + ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false, EqualLoc); - Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release()); + Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc, + Init.get()); // The next token should be our artificial terminating EOF token. if (Tok.isNot(tok::eof)) { @@ -580,6 +577,9 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, switch (Tok.getKind()) { case tok::eof: + case tok::annot_module_begin: + case tok::annot_module_end: + case tok::annot_module_include: // Ran out of tokens. return false; @@ -675,7 +675,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false); if (Tok.isNot(tok::l_brace)) - return Diag(Tok.getLocation(), diag::err_expected_lbrace); + return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace; Toks.push_back(Tok); ConsumeBrace(); @@ -708,8 +708,8 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { Toks.push_back(Tok); ConsumeParen(); if (!ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/true)) { - Diag(Tok.getLocation(), diag::err_expected_rparen); - Diag(OpenLoc, diag::note_matching) << "("; + Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; + Diag(OpenLoc, diag::note_matching) << tok::l_paren; return true; } } @@ -756,13 +756,15 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { /*ConsumeFinalToken=*/false)) { // We're not just missing the initializer, we're also missing the // function body! - return Diag(Tok.getLocation(), diag::err_expected_lbrace); + return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace; } } else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) { // We found something weird in a mem-initializer-id. - return Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 - ? diag::err_expected_lparen_or_lbrace - : diag::err_expected_lparen); + if (getLangOpts().CPlusPlus11) + return Diag(Tok.getLocation(), diag::err_expected_either) + << tok::l_paren << tok::l_brace; + else + return Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; } tok::TokenKind kind = Tok.getKind(); @@ -784,11 +786,10 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { // Grab the initializer (or the subexpression of the template argument). // FIXME: If we support lambdas here, we'll need to set StopAtSemi to false // if we might be inside the braces of a lambda-expression. - if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace, - Toks, /*StopAtSemi=*/true)) { - Diag(Tok, IsLParen ? diag::err_expected_rparen : - diag::err_expected_rbrace); - Diag(OpenLoc, diag::note_matching) << (IsLParen ? "(" : "{"); + tok::TokenKind CloseKind = IsLParen ? tok::r_paren : tok::r_brace; + if (!ConsumeAndStoreUntil(CloseKind, Toks, /*StopAtSemi=*/true)) { + Diag(Tok, diag::err_expected) << CloseKind; + Diag(OpenLoc, diag::note_matching) << kind; return true; } @@ -822,7 +823,8 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { ConsumeBrace(); return false; } else if (!MightBeTemplateArgument) { - return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma); + return Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace + << tok::comma; } } } @@ -836,8 +838,9 @@ bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) { ConsumeToken(); while (Tok.isNot(tok::colon)) { - if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks, /*StopAtSemi*/true, - /*ConsumeFinalToken*/false)) + if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks, + /*StopAtSemi=*/true, + /*ConsumeFinalToken=*/false)) return false; // If we found a nested conditional, consume it. @@ -925,15 +928,15 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, ? tok::semi : tok::r_paren); Sema::TentativeAnalysisScope Scope(Actions); - TPResult Result = TPResult::Error(); + TPResult Result = TPResult::Error; ConsumeToken(); switch (CIK) { case CIK_DefaultInitializer: Result = TryParseInitDeclaratorList(); // If we parsed a complete, ambiguous init-declarator-list, this // is only syntactically-valid if it's followed by a semicolon. - if (Result == TPResult::Ambiguous() && Tok.isNot(tok::semi)) - Result = TPResult::False(); + if (Result == TPResult::Ambiguous && Tok.isNot(tok::semi)) + Result = TPResult::False; break; case CIK_DefaultArgument: @@ -942,13 +945,13 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, &InvalidAsDeclaration, /*VersusTemplateArgument*/true); // If this is an expression or a declaration with a missing // 'typename', assume it's not a declaration. - if (Result == TPResult::Ambiguous() && InvalidAsDeclaration) - Result = TPResult::False(); + if (Result == TPResult::Ambiguous && InvalidAsDeclaration) + Result = TPResult::False; break; } // If what follows could be a declaration, it is a declaration. - if (Result != TPResult::False() && Result != TPResult::Error()) { + if (Result != TPResult::False && Result != TPResult::Error) { PA.Revert(); return true; } @@ -965,6 +968,9 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, goto consume_token; case tok::eof: + case tok::annot_module_begin: + case tok::annot_module_end: + case tok::annot_module_include: // Ran out of tokens. return false; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 7b80934..62d4376 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -13,10 +13,12 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" -#include "clang/Basic/OpenCL.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" @@ -51,7 +53,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, DS.addAttributes(Attrs->getList()); ParseSpecifierQualifierList(DS, AS, DSC); if (OwnedType) - *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : 0; + *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; // Parse the abstract-declarator, if present. Declarator DeclaratorInfo(DS, Context); @@ -69,9 +71,11 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, /// isAttributeLateParsed - Return true if the attribute has arguments that /// require late parsing. static bool isAttributeLateParsed(const IdentifierInfo &II) { +#define CLANG_ATTR_LATE_PARSED_LIST return llvm::StringSwitch<bool>(II.getName()) -#include "clang/Parse/AttrLateParsed.inc" +#include "clang/Parse/AttrParserStringSwitches.inc" .Default(false); +#undef CLANG_ATTR_LATE_PARSED_LIST } /// ParseGNUAttributes - Parse a non-empty attributes list. @@ -117,7 +121,8 @@ static bool isAttributeLateParsed(const IdentifierInfo &II) { /// We follow the C++ model, but don't allow junk after the identifier. void Parser::ParseGNUAttributes(ParsedAttributes &attrs, SourceLocation *endLoc, - LateParsedAttrList *LateAttrs) { + LateParsedAttrList *LateAttrs, + Declarator *D) { assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); while (Tok.is(tok::kw___attribute)) { @@ -132,49 +137,54 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, return; } // 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(); + while (true) { + // Allow empty/non-empty attributes. ((__vector_size__(16),,,,)) + if (TryConsumeToken(tok::comma)) continue; - } - // we have an identifier or declaration specifier (const, int, etc.) + + // Expect an identifier or declaration specifier (const, int, etc.) + if (Tok.isNot(tok::identifier) && !isDeclarationSpecifier()) + break; + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - if (Tok.is(tok::l_paren)) { - // handle "parameterized" attributes - if (LateAttrs && isAttributeLateParsed(*AttrName)) { - LateParsedAttribute *LA = - new LateParsedAttribute(this, *AttrName, AttrNameLoc); - LateAttrs->push_back(LA); - - // Attributes in a class are parsed at the end of the class, along - // with other late-parsed declarations. - if (!ClassStack.empty() && !LateAttrs->parseSoon()) - 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, - 0, SourceLocation(), AttributeList::AS_GNU); - } - } else { - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + if (Tok.isNot(tok::l_paren)) { + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, AttributeList::AS_GNU); + continue; + } + + // Handle "parameterized" attributes + if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { + ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr, + SourceLocation(), AttributeList::AS_GNU, D); + continue; } + + // Handle attributes with arguments that require late parsing. + LateParsedAttribute *LA = + new LateParsedAttribute(this, *AttrName, AttrNameLoc); + LateAttrs->push_back(LA); + + // Attributes in a class are parsed at the end of the class, along + // with other late-parsed declarations. + if (!ClassStack.empty() && !LateAttrs->parseSoon()) + 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); } - if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) + + if (ExpectAndConsume(tok::r_paren)) SkipUntil(tok::r_paren, StopAtSemi); SourceLocation Loc = Tok.getLocation(); - if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) + if (ExpectAndConsume(tok::r_paren)) SkipUntil(tok::r_paren, StopAtSemi); if (endLoc) *endLoc = Loc; @@ -190,16 +200,30 @@ static StringRef normalizeAttrName(StringRef Name) { /// \brief Determine whether the given attribute has an identifier argument. static bool attributeHasIdentifierArg(const IdentifierInfo &II) { +#define CLANG_ATTR_IDENTIFIER_ARG_LIST return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrIdentifierArg.inc" +#include "clang/Parse/AttrParserStringSwitches.inc" .Default(false); +#undef CLANG_ATTR_IDENTIFIER_ARG_LIST } /// \brief Determine whether the given attribute parses a type argument. static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { +#define CLANG_ATTR_TYPE_ARG_LIST + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) +#include "clang/Parse/AttrParserStringSwitches.inc" + .Default(false); +#undef CLANG_ATTR_TYPE_ARG_LIST +} + +/// \brief Determine whether the given attribute requires parsing its arguments +/// in an unevaluated context or not. +static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) { +#define CLANG_ATTR_ARG_CONTEXT_LIST return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) -#include "clang/Parse/AttrTypeArg.inc" +#include "clang/Parse/AttrParserStringSwitches.inc" .Default(false); +#undef CLANG_ATTR_ARG_CONTEXT_LIST } IdentifierLoc *Parser::ParseIdentifierLoc() { @@ -214,7 +238,10 @@ IdentifierLoc *Parser::ParseIdentifierLoc() { void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, - SourceLocation *EndLoc) { + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax) { BalancedDelimiterTracker Parens(*this, tok::l_paren); Parens.consumeOpen(); @@ -230,61 +257,26 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, if (T.isUsable()) Attrs.addNewTypeAttr(&AttrName, - SourceRange(AttrNameLoc, Parens.getCloseLocation()), 0, - AttrNameLoc, T.get(), AttributeList::AS_GNU); + SourceRange(AttrNameLoc, Parens.getCloseLocation()), + ScopeName, ScopeLoc, T.get(), Syntax); else Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()), - 0, AttrNameLoc, 0, 0, AttributeList::AS_GNU); + ScopeName, ScopeLoc, nullptr, 0, Syntax); } -/// Parse the arguments to a parameterized GNU attribute or -/// a C++11 attribute in "gnu" namespace. -void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { - - assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); - - // Availability attributes have their own grammar. - // FIXME: All these cases fail to pass in the syntax and scope, and might be - // written as C++11 gnu:: attributes. - if (AttrKind == AttributeList::AT_Availability) { - ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc); - return; - } - // Thread safety attributes are parsed in an unevaluated context. - // FIXME: Share the bulk of the parsing code here and just pull out - // the unevaluated context. - if (IsThreadSafetyAttribute(AttrName->getName())) { - ParseThreadSafetyAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc); - return; - } - // Type safety attributes have their own grammar. - if (AttrKind == AttributeList::AT_TypeTagForDatatype) { - ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc); - return; - } - // Some attributes expect solely a type parameter. - if (attributeIsTypeArgAttr(*AttrName)) { - ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc); - return; - } - +unsigned Parser::ParseAttributeArgsCommon( + IdentifierInfo *AttrName, SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { // Ignore the left paren location for now. ConsumeParen(); ArgsVector ArgExprs; - if (Tok.is(tok::identifier)) { // If this attribute wants an 'identifier' argument, make it so. bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName); + AttributeList::Kind AttrKind = + AttributeList::getKind(AttrName, ScopeName, Syntax); // If we don't know how to parse this attribute, but this is the only // token in this argument, assume it's meant to be an identifier. @@ -304,112 +296,117 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, ConsumeToken(); // Parse the non-empty comma-separated list of expressions. - while (1) { + do { + std::unique_ptr<EnterExpressionEvaluationContext> Unevaluated; + if (attributeParsedArgsUnevaluated(*AttrName)) + Unevaluated.reset( + new EnterExpressionEvaluationContext(Actions, Sema::Unevaluated)); + ExprResult ArgExpr(ParseAssignmentExpression()); if (ArgExpr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); - return; + return 0; } - ArgExprs.push_back(ArgExpr.release()); - if (Tok.isNot(tok::comma)) - break; - ConsumeToken(); // Eat the comma, move to the next argument - } + ArgExprs.push_back(ArgExpr.get()); + // Eat the comma, move to the next argument + } while (TryConsumeToken(tok::comma)); } SourceLocation RParen = Tok.getLocation(); - if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) { + if (!ExpectAndConsume(tok::r_paren)) { SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, ArgExprs.data(), ArgExprs.size(), Syntax); } + + if (EndLoc) + *EndLoc = RParen; + + return static_cast<unsigned>(ArgExprs.size()); } -/// \brief Parses a single argument for a declspec, including the -/// surrounding parens. -void Parser::ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs) -{ - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, - AttrName->getNameStart(), tok::r_paren)) - return; +/// Parse the arguments to a parameterized GNU attribute or +/// a C++11 attribute in "gnu" namespace. +void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax, + Declarator *D) { - ExprResult ArgExpr(ParseConstantExpression()); - if (ArgExpr.isInvalid()) { - T.skipToEnd(); + assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); + + AttributeList::Kind AttrKind = + AttributeList::getKind(AttrName, ScopeName, Syntax); + + if (AttrKind == AttributeList::AT_Availability) { + ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, + ScopeLoc, Syntax); + return; + } else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) { + ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); + return; + } else if (AttrKind == AttributeList::AT_TypeTagForDatatype) { + ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); + return; + } else if (attributeIsTypeArgAttr(*AttrName)) { + ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, + ScopeLoc, Syntax); return; } - ArgsUnion ExprList = ArgExpr.take(); - Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, &ExprList, 1, - AttributeList::AS_Declspec); - T.consumeClose(); -} + // These may refer to the function arguments, but need to be parsed early to + // participate in determining whether it's a redeclaration. + std::unique_ptr<ParseScope> PrototypeScope; + if (AttrName->isStr("enable_if") && D && D->isFunctionDeclarator()) { + DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo(); + PrototypeScope.reset(new ParseScope(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | + Scope::DeclScope)); + for (unsigned i = 0; i != FTI.NumParams; ++i) { + ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param); + Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param); + } + } -/// \brief Determines whether a declspec is a "simple" one requiring no -/// arguments. -bool Parser::IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident) { - return llvm::StringSwitch<bool>(Ident->getName()) - .Case("dllimport", true) - .Case("dllexport", true) - .Case("noreturn", true) - .Case("nothrow", true) - .Case("noinline", true) - .Case("naked", true) - .Case("appdomain", true) - .Case("process", true) - .Case("jitintrinsic", true) - .Case("noalias", true) - .Case("restrict", true) - .Case("novtable", true) - .Case("selectany", true) - .Case("thread", true) - .Case("safebuffers", true ) - .Default(false); + ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, + ScopeLoc, Syntax); } -/// \brief Attempts to parse a declspec which is not simple (one that takes -/// parameters). Will return false if we properly handled the declspec, or -/// true if it is an unknown declspec. -void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, - SourceLocation Loc, - ParsedAttributes &Attrs) { - // Try to handle the easy case first -- these declspecs all take a single - // parameter as their argument. - if (llvm::StringSwitch<bool>(Ident->getName()) - .Case("uuid", true) - .Case("align", true) - .Case("allocate", true) - .Default(false)) { - ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs); - } else if (Ident->getName() == "deprecated") { - // The deprecated declspec has an optional single argument, so we will - // check for a l-paren to decide whether we should parse an argument or - // not. - if (Tok.getKind() == tok::l_paren) - ParseMicrosoftDeclSpecWithSingleArg(Ident, Loc, Attrs); - else - Attrs.addNew(Ident, Loc, 0, Loc, 0, 0, AttributeList::AS_Declspec); - } else if (Ident->getName() == "property") { +bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs) { + // If the attribute isn't known, we will not attempt to parse any + // arguments. + if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName, + getTargetInfo().getTriple(), getLangOpts())) { + // Eat the left paren, then skip to the ending right paren. + ConsumeParen(); + SkipUntil(tok::r_paren); + return false; + } + + SourceLocation OpenParenLoc = Tok.getLocation(); + + if (AttrName->getName() == "property") { // The property declspec is more complex in that it can take one or two // assignment expressions as a parameter, but the lhs of the assignment // must be named get or put. - if (Tok.isNot(tok::l_paren)) { - Diag(Tok.getLocation(), diag::err_expected_lparen_after) - << Ident->getNameStart(); - return; - } + BalancedDelimiterTracker T(*this, tok::l_paren); T.expectAndConsume(diag::err_expected_lparen_after, - Ident->getNameStart(), tok::r_paren); + AttrName->getNameStart(), tok::r_paren); enum AccessorKind { AK_Invalid = -1, - AK_Put = 0, AK_Get = 1 // indices into AccessorNames + AK_Put = 0, + AK_Get = 1 // indices into AccessorNames }; - IdentifierInfo *AccessorNames[] = { 0, 0 }; + IdentifierInfo *AccessorNames[] = {nullptr, nullptr}; bool HasInvalidAccessor = false; // Parse the accessor specifications. @@ -418,8 +415,9 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, if (!Tok.is(tok::identifier)) { // If the user wrote a completely empty list, use a special diagnostic. if (Tok.is(tok::r_paren) && !HasInvalidAccessor && - AccessorNames[AK_Put] == 0 && AccessorNames[AK_Get] == 0) { - Diag(Loc, diag::err_ms_property_no_getter_or_putter); + AccessorNames[AK_Put] == nullptr && + AccessorNames[AK_Get] == nullptr) { + Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter); break; } @@ -435,39 +433,38 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, } else if (KindStr == "put") { Kind = AK_Put; - // Recover from the common mistake of using 'set' instead of 'put'. + // Recover from the common mistake of using 'set' instead of 'put'. } else if (KindStr == "set") { Diag(KindLoc, diag::err_ms_property_has_set_accessor) - << FixItHint::CreateReplacement(KindLoc, "put"); + << FixItHint::CreateReplacement(KindLoc, "put"); Kind = AK_Put; - // Handle the mistake of forgetting the accessor kind by skipping - // this accessor. + // Handle the mistake of forgetting the accessor kind by skipping + // this accessor. } else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) { Diag(KindLoc, diag::err_ms_property_missing_accessor_kind); ConsumeToken(); HasInvalidAccessor = true; goto next_property_accessor; - // Otherwise, complain about the unknown accessor kind. + // Otherwise, complain about the unknown accessor kind. } else { Diag(KindLoc, diag::err_ms_property_unknown_accessor); HasInvalidAccessor = true; Kind = AK_Invalid; // Try to keep parsing unless it doesn't look like an accessor spec. - if (!NextToken().is(tok::equal)) break; + if (!NextToken().is(tok::equal)) + break; } // Consume the identifier. ConsumeToken(); // Consume the '='. - if (Tok.is(tok::equal)) { - ConsumeToken(); - } else { + if (!TryConsumeToken(tok::equal)) { Diag(Tok.getLocation(), diag::err_ms_property_expected_equal) - << KindStr; + << KindStr; break; } @@ -479,7 +476,7 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, if (Kind == AK_Invalid) { // Just drop invalid accessors. - } else if (AccessorNames[Kind] != NULL) { + } else if (AccessorNames[Kind] != nullptr) { // Complain about the repeated accessor, ignore it, and keep parsing. Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr; } else { @@ -489,41 +486,38 @@ void Parser::ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, next_property_accessor: // Keep processing accessors until we run out. - if (Tok.is(tok::comma)) { - ConsumeAnyToken(); + if (TryConsumeToken(tok::comma)) continue; // If we run into the ')', stop without consuming it. - } else if (Tok.is(tok::r_paren)) { + if (Tok.is(tok::r_paren)) break; - } else { - Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen); - break; - } + + Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen); + break; } // Only add the property attribute if it was well-formed. - if (!HasInvalidAccessor) { - Attrs.addNewPropertyAttr(Ident, Loc, 0, SourceLocation(), + if (!HasInvalidAccessor) + Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(), AccessorNames[AK_Get], AccessorNames[AK_Put], AttributeList::AS_Declspec); - } T.skipToEnd(); - } else { - // We don't recognize this as a valid declspec, but instead of creating the - // attribute and allowing sema to warn about it, we will warn here instead. - // This is because some attributes have multiple spellings, but we need to - // disallow that for declspecs (such as align vs aligned). If we made the - // attribute, we'd have to split the valid declspec spelling logic into - // both locations. - Diag(Loc, diag::warn_ms_declspec_unknown) << Ident; - - // If there's an open paren, we should eat the open and close parens under - // the assumption that this unknown declspec has parameters. - BalancedDelimiterTracker T(*this, tok::l_paren); - if (!T.consumeOpen()) - T.skipToEnd(); + return !HasInvalidAccessor; } + + unsigned NumArgs = + ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, + SourceLocation(), AttributeList::AS_Declspec); + + // If this attribute's args were parsed, and it was expected to have + // arguments but none were provided, emit a diagnostic. + const AttributeList *Attr = Attrs.getList(); + if (Attr && Attr->getMaxArgs() && !NumArgs) { + Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; + return false; + } + return true; } /// [MS] decl-specifier: @@ -543,7 +537,11 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) { // An empty declspec is perfectly legal and should not warn. Additionally, // you can specify multiple attributes per declspec. - while (Tok.getKind() != tok::r_paren) { + while (Tok.isNot(tok::r_paren)) { + // Attribute not present. + if (TryConsumeToken(tok::comma)) + continue; + // We expect either a well-known identifier or a generic string. Anything // else is a malformed declspec. bool IsString = Tok.getKind() == tok::string_literal ? true : false; @@ -571,17 +569,19 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) { AttrNameLoc = ConsumeToken(); } - if (IsString || IsSimpleMicrosoftDeclSpec(AttrName)) - // If we have a generic string, we will allow it because there is no - // documented list of allowable string declspecs, but we know they exist - // (for instance, SAL declspecs in older versions of MSVC). - // - // Alternatively, if the identifier is a simple one, then it requires no - // arguments and can be turned into an attribute directly. - Attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + bool AttrHandled = false; + + // Parse attribute arguments. + if (Tok.is(tok::l_paren)) + AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs); + else if (AttrName->getName() == "property") + // The property attribute must have an argument list. + Diag(Tok.getLocation(), diag::err_expected_lparen_after) + << AttrName->getName(); + + if (!AttrHandled) + Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, AttributeList::AS_Declspec); - else - ParseComplexMicrosoftDeclSpec(AttrName, AttrNameLoc, Attrs); } T.consumeClose(); } @@ -595,7 +595,7 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, AttributeList::AS_Keyword); } } @@ -605,7 +605,7 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { while (Tok.is(tok::kw___pascal)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, AttributeList::AS_Keyword); } } @@ -615,61 +615,16 @@ void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) { while (Tok.is(tok::kw___kernel)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, AttributeList::AS_Keyword); } } -void Parser::ParseOpenCLQualifiers(DeclSpec &DS) { - // FIXME: The mapping from attribute spelling to semantics should be - // performed in Sema, not here. - SourceLocation Loc = Tok.getLocation(); - switch(Tok.getKind()) { - // OpenCL qualifiers: - case tok::kw___private: - case tok::kw_private: - DS.getAttributes().addNewInteger( - Actions.getASTContext(), - PP.getIdentifierInfo("address_space"), Loc, 0); - break; - - case tok::kw___global: - DS.getAttributes().addNewInteger( - Actions.getASTContext(), - PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_global); - break; - - case tok::kw___local: - DS.getAttributes().addNewInteger( - Actions.getASTContext(), - PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_local); - break; - - case tok::kw___constant: - DS.getAttributes().addNewInteger( - Actions.getASTContext(), - PP.getIdentifierInfo("address_space"), Loc, LangAS::opencl_constant); - break; - - case tok::kw___read_only: - DS.getAttributes().addNewInteger( - Actions.getASTContext(), - PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_only); - break; - - case tok::kw___write_only: - DS.getAttributes().addNewInteger( - Actions.getASTContext(), - PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_write_only); - break; - - case tok::kw___read_write: - DS.getAttributes().addNewInteger( - Actions.getASTContext(), - PP.getIdentifierInfo("opencl_image_access"), Loc, CLIA_read_write); - break; - default: break; - } +void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + SourceLocation AttrNameLoc = Tok.getLocation(); + Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + AttributeList::AS_Keyword); } /// \brief Parse a version number. @@ -804,7 +759,10 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, SourceLocation AvailabilityLoc, ParsedAttributes &attrs, - SourceLocation *endLoc) { + SourceLocation *endLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax) { enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr; @@ -812,7 +770,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { - Diag(Tok, diag::err_expected_lparen); + Diag(Tok, diag::err_expected) << tok::l_paren; return; } @@ -825,8 +783,10 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, IdentifierLoc *Platform = ParseIdentifierLoc(); // Parse the ',' following the platform name. - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren)) + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); return; + } // If we haven't grabbed the pointers for the identifiers // "introduced", "deprecated", and "obsoleted", do so now. @@ -855,29 +815,34 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, << Keyword << SourceRange(UnavailableLoc); } UnavailableLoc = KeywordLoc; - - if (Tok.isNot(tok::comma)) - break; - - ConsumeToken(); continue; } if (Tok.isNot(tok::equal)) { - Diag(Tok, diag::err_expected_equal_after) - << Keyword; + Diag(Tok, diag::err_expected_after) << Keyword << tok::equal; SkipUntil(tok::r_paren, StopAtSemi); return; } ConsumeToken(); if (Keyword == Ident_message) { - if (Tok.isNot(tok::string_literal)) { // Also reject wide string literals. + if (Tok.isNot(tok::string_literal)) { Diag(Tok, diag::err_expected_string_literal) << /*Source='availability attribute'*/2; SkipUntil(tok::r_paren, StopAtSemi); return; } MessageExpr = ParseStringLiteralExpression(); + // Also reject wide string literals. + if (StringLiteral *MessageStringLiteral = + cast_or_null<StringLiteral>(MessageExpr.get())) { + if (MessageStringLiteral->getCharByteWidth() != 1) { + Diag(MessageStringLiteral->getSourceRange().getBegin(), + diag::err_expected_string_literal) + << /*Source='availability attribute'*/ 2; + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + } break; } @@ -915,11 +880,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, << Keyword << VersionRange; } - if (Tok.isNot(tok::comma)) - break; - - ConsumeToken(); - } while (true); + } while (TryConsumeToken(tok::comma)); // Closing ')'. if (T.consumeClose()) @@ -950,15 +911,97 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, // Record this attribute attrs.addNew(&Availability, SourceRange(AvailabilityLoc, T.getCloseLocation()), - 0, AvailabilityLoc, + ScopeName, ScopeLoc, Platform, Changes[Introduced], Changes[Deprecated], Changes[Obsoleted], - UnavailableLoc, MessageExpr.take(), - AttributeList::AS_GNU); + UnavailableLoc, MessageExpr.get(), + Syntax); } +/// \brief Parse the contents of the "objc_bridge_related" attribute. +/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')' +/// related_class: +/// Identifier +/// +/// opt-class_method: +/// Identifier: | <empty> +/// +/// opt-instance_method: +/// Identifier | <empty> +/// +void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, + SourceLocation ObjCBridgeRelatedLoc, + ParsedAttributes &attrs, + SourceLocation *endLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax) { + // Opening '('. + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { + Diag(Tok, diag::err_expected) << tok::l_paren; + return; + } + + // Parse the related class name. + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_objcbridge_related_expected_related_class); + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + IdentifierLoc *RelatedClass = ParseIdentifierLoc(); + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + + // Parse optional class method name. + IdentifierLoc *ClassMethod = nullptr; + if (Tok.is(tok::identifier)) { + ClassMethod = ParseIdentifierLoc(); + if (!TryConsumeToken(tok::colon)) { + Diag(Tok, diag::err_objcbridge_related_selector_name); + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + } + if (!TryConsumeToken(tok::comma)) { + if (Tok.is(tok::colon)) + Diag(Tok, diag::err_objcbridge_related_selector_name); + else + Diag(Tok, diag::err_expected) << tok::comma; + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + + // Parse optional instance method name. + IdentifierLoc *InstanceMethod = nullptr; + if (Tok.is(tok::identifier)) + InstanceMethod = ParseIdentifierLoc(); + else if (Tok.isNot(tok::r_paren)) { + Diag(Tok, diag::err_expected) << tok::r_paren; + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + + // Closing ')'. + if (T.consumeClose()) + return; + + if (endLoc) + *endLoc = T.getCloseLocation(); + + // Record this attribute + attrs.addNew(&ObjCBridgeRelated, + SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()), + ScopeName, ScopeLoc, + RelatedClass, + ClassMethod, + InstanceMethod, + Syntax); +} // Late Parsed Attributes: // See other examples of late parsing in lib/Parse/ParseCXXInlineMethods @@ -1038,13 +1081,6 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, // Consume the previously pushed token. ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); - if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) { - // FIXME: Do not warn on C++11 attributes, once we start supporting - // them here. - Diag(Tok, diag::warn_attribute_on_function_definition) - << LA.AttrName.getName(); - } - ParsedAttributes Attrs(AttrFactory); SourceLocation endLoc; @@ -1071,7 +1107,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, Actions.ActOnReenterFunctionContext(Actions.CurScope, D); ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - 0, SourceLocation(), AttributeList::AS_GNU); + nullptr, SourceLocation(), AttributeList::AS_GNU, + nullptr); if (HasFunScope) { Actions.ActOnExitFunctionContext(); @@ -1084,15 +1121,21 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, // If there are multiple decls, then the decl cannot be within the // function scope. ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - 0, SourceLocation(), AttributeList::AS_GNU); + nullptr, SourceLocation(), AttributeList::AS_GNU, + nullptr); } } else { Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); } - for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) { + const AttributeList *AL = Attrs.getList(); + if (OnDefinition && AL && !AL->isCXX11Attribute() && + AL->isKnownToGCC()) + Diag(Tok, diag::warn_attribute_on_function_definition) + << &LA.AttrName; + + for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs); - } if (Tok.getLocation() != OrigLoc) { // Due to a parsing error, we either went over the cached tokens or @@ -1106,101 +1149,29 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, } } -/// \brief Wrapper around a case statement checking if AttrName is -/// one of the thread safety attributes -bool Parser::IsThreadSafetyAttribute(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(); - - ArgsVector ArgExprs; - bool ArgExprsOk = true; - - // now parse the list of expressions - while (Tok.isNot(tok::r_paren)) { - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); - 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, ArgExprs.data(), - ArgExprs.size(), AttributeList::AS_GNU); - } - if (EndLoc) - *EndLoc = T.getCloseLocation(); -} - void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, - SourceLocation *EndLoc) { + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + AttributeList::Syntax Syntax) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; T.skipToEnd(); return; } IdentifierLoc *ArgumentKind = ParseIdentifierLoc(); - if (Tok.isNot(tok::comma)) { - Diag(Tok, diag::err_expected_comma); + if (ExpectAndConsume(tok::comma)) { T.skipToEnd(); return; } - ConsumeToken(); SourceRange MatchingCTypeRange; TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange); @@ -1211,10 +1182,9 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, bool LayoutCompatible = false; bool MustBeNull = false; - while (Tok.is(tok::comma)) { - ConsumeToken(); + while (TryConsumeToken(tok::comma)) { if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; T.skipToEnd(); return; } @@ -1232,10 +1202,9 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, } if (!T.consumeClose()) { - Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, 0, AttrNameLoc, - ArgumentKind, MatchingCType.release(), - LayoutCompatible, MustBeNull, - AttributeList::AS_GNU); + Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc, + ArgumentKind, MatchingCType.get(), + LayoutCompatible, MustBeNull, Syntax); } if (EndLoc) @@ -1337,8 +1306,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, // parsing c none objective-c decls. ObjCDeclContextSwitch ObjCDC(*this); - Decl *SingleDecl = 0; - Decl *OwnedType = 0; + Decl *SingleDecl = nullptr; + Decl *OwnedType = nullptr; switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: @@ -1508,8 +1477,7 @@ void Parser::SkipMalformedDecl() { // This declaration isn't over yet. Keep skipping. continue; } - if (Tok.is(tok::semi)) - ConsumeToken(); + TryConsumeToken(tok::semi); return; case tok::l_square: @@ -1562,6 +1530,9 @@ void Parser::SkipMalformedDecl() { break; case tok::eof: + case tok::annot_module_begin: + case tok::annot_module_end: + case tok::annot_module_include: return; default: @@ -1632,7 +1603,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } else { if (Tok.is(tok::l_brace)) { Diag(Tok, diag::err_function_definition_not_allowed); - SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + SkipMalformedDecl(); + return DeclGroupPtrTy(); } } } @@ -1648,9 +1620,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // don't need to parse the container in advance. if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) { bool IsForRangeLoop = false; - if (Tok.is(tok::colon)) { + if (TryConsumeToken(tok::colon, FRI->ColonLoc)) { IsForRangeLoop = true; - FRI->ColonLoc = ConsumeToken(); if (Tok.is(tok::l_brace)) FRI->RangeExpr = ParseBraceInitializer(); else @@ -1666,7 +1637,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } SmallVector<Decl *, 8> DeclsInGroup; - Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D); + Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes( + D, ParsedTemplateInfo(), FRI); if (LateParsedAttrs.size() > 0) ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); D.complete(FirstDecl); @@ -1677,9 +1649,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // If we don't have a comma, it is either the end of the list (a ';') or an // error, bail out. - while (Tok.is(tok::comma)) { - SourceLocation CommaLoc = ConsumeToken(); - + SourceLocation CommaLoc; + while (TryConsumeToken(tok::comma, CommaLoc)) { if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) { // This comma was followed by a line-break and something which can't be // the start of a declarator. The comma was probably a typo for a @@ -1724,8 +1695,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // Otherwise things are very confused and we skip to recover. if (!isDeclarationSpecifier()) { SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); - if (Tok.is(tok::semi)) - ConsumeToken(); + TryConsumeToken(tok::semi); } } @@ -1744,7 +1714,7 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) { return true; } - D.setAsmLabel(AsmLabel.release()); + D.setAsmLabel(AsmLabel.get()); D.SetRangeEnd(Loc); } @@ -1774,18 +1744,18 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) { /// According to the standard grammar, =default and =delete are function /// definitions, but that definitely doesn't fit with the parser here. /// -Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, - const ParsedTemplateInfo &TemplateInfo) { +Decl *Parser::ParseDeclarationAfterDeclarator( + Declarator &D, const ParsedTemplateInfo &TemplateInfo) { if (ParseAsmAttributesAfterDeclarator(D)) - return 0; + return nullptr; return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo); } -Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, - const ParsedTemplateInfo &TemplateInfo) { +Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( + Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) { // Inform the current actions module that we just parsed this declarator. - Decl *ThisDecl = 0; + Decl *ThisDecl = nullptr; switch (TemplateInfo.Kind) { case ParsedTemplateInfo::NonTemplate: ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); @@ -1808,7 +1778,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D); if (ThisRes.isInvalid()) { SkipUntil(tok::semi, StopBeforeMatch); - return 0; + return nullptr; } ThisDecl = ThisRes.get(); } else { @@ -1832,8 +1802,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, // Recover as if it were an explicit specialization. TemplateParameterLists FakedParamLists; FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0, - LAngleLoc)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr, + 0, LAngleLoc)); ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D); @@ -1848,7 +1818,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, // Parse declarator '=' initializer. // If a '==' or '+=' is found, suggest a fixit to '='. if (isTokenEqualOrEqualTypo()) { - ConsumeToken(); + SourceLocation EqualLoc = ConsumeToken(); if (Tok.is(tok::kw_delete)) { if (D.isFunctionDeclarator()) @@ -1872,21 +1842,37 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, Actions.CodeCompleteInitializer(getCurScope(), ThisDecl); Actions.FinalizeDeclaration(ThisDecl); cutOffParsing(); - return 0; + return nullptr; } ExprResult Init(ParseInitializer()); + // If this is the only decl in (possibly) range based for statement, + // our best guess is that the user meant ':' instead of '='. + if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) { + Diag(EqualLoc, diag::err_single_decl_assign_in_for_range) + << FixItHint::CreateReplacement(EqualLoc, ":"); + // We are trying to stop parser from looking for ';' in this for + // statement, therefore preventing spurious errors to be issued. + FRI->ColonLoc = EqualLoc; + Init = ExprError(); + FRI->RangeExpr = Init; + } + if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl); ExitScope(); } if (Init.isInvalid()) { - SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + SmallVector<tok::TokenKind, 2> StopTokens; + StopTokens.push_back(tok::comma); + if (D.getContext() == Declarator::ForContext) + StopTokens.push_back(tok::r_paren); + SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch); Actions.ActOnInitializerError(ThisDecl); } else - Actions.AddInitializerToDecl(ThisDecl, Init.take(), + Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/false, TypeContainsAuto); } } else if (Tok.is(tok::l_paren)) { @@ -1925,7 +1911,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(), T.getCloseLocation(), Exprs); - Actions.AddInitializerToDecl(ThisDecl, Initializer.take(), + Actions.AddInitializerToDecl(ThisDecl, Initializer.get(), /*DirectInit=*/true, TypeContainsAuto); } } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) && @@ -1948,7 +1934,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, if (Init.isInvalid()) { Actions.ActOnInitializerError(ThisDecl); } else - Actions.AddInitializerToDecl(ThisDecl, Init.take(), + Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true, TypeContainsAuto); } else { @@ -1975,8 +1961,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, // Validate declspec for type-name. unsigned Specs = DS.getParsedSpecifiers(); - if ((DSC == DSC_type_specifier || DSC == DSC_trailing) && - !DS.hasTypeSpecifier()) { + if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) { Diag(Tok, diag::err_expected_type); DS.SetTypeSpecError(); } else if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() && @@ -2050,7 +2035,7 @@ static bool isValidAfterIdentifierInDeclarator(const Token &T) { /// bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, const ParsedTemplateInfo &TemplateInfo, - AccessSpecifier AS, DeclSpecContext DSC, + AccessSpecifier AS, DeclSpecContext DSC, ParsedAttributesWithRange &Attrs) { assert(Tok.is(tok::identifier) && "should have identifier"); @@ -2074,8 +2059,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // within a type specifier. Outside of C++, we allow this even if the // language doesn't "officially" support implicit int -- we support // implicit int as an extension in C99 and C11. - if (DSC != DSC_type_specifier && DSC != DSC_trailing && - !getLangOpts().CPlusPlus && + if (!isTypeSpecifier(DSC) && !getLangOpts().CPlusPlus && isValidAfterIdentifierInDeclarator(NextToken())) { // If this token is valid for implicit int, e.g. "static x = 4", then // we just avoid eating the identifier, so it will be parsed as the @@ -2098,8 +2082,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // This is a common problem in C (saying 'foo' instead of 'struct foo'). // // C++ doesn't need this, and isTagName doesn't take SS. - if (SS == 0) { - const char *TagName = 0, *FixitTagName = 0; + if (SS == nullptr) { + const char *TagName = nullptr, *FixitTagName = nullptr; tok::TokenKind TagKind = tok::unknown; switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) { @@ -2145,7 +2129,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // Determine whether this identifier could plausibly be the name of something // being declared (with a missing type). - if (DSC != DSC_type_specifier && DSC != DSC_trailing && + if (!isTypeSpecifier(DSC) && (!SS || DSC == DSC_top_level || DSC == DSC_class)) { // Look ahead to the next token to try to figure out what this declaration // was supposed to be. @@ -2155,15 +2139,14 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // x(int n); // 'x' is not a type // x (*p)[]; // 'x' is a type // - // Since we're in an error case (or the rare 'implicit int in C++' MS - // extension), we can afford to perform a tentative parse to determine - // which case we're in. + // Since we're in an error case, we can afford to perform a tentative + // parse to determine which case we're in. TentativeParsingAction PA(*this); ConsumeToken(); TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false); PA.Revert(); - if (TPR != TPResult::False()) { + if (TPR != TPResult::False) { // The identifier is followed by a parenthesized declarator. // It's supposed to be a type. break; @@ -2202,39 +2185,33 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, } } - // This is almost certainly an invalid type name. Let the action emit a - // diagnostic and attempt to recover. + // This is almost certainly an invalid type name. Let Sema emit a diagnostic + // and attempt to recover. ParsedType T; IdentifierInfo *II = Tok.getIdentifierInfo(); - if (Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T)) { - // The action emitted a diagnostic, so we don't have to. - if (T) { - // The action has suggested that the type T could be used. Set that as - // the type in the declaration specifiers, consume the would-be type - // name token, and we're done. - const char *PrevSpec; - unsigned DiagID; - DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T); - DS.SetRangeEnd(Tok.getLocation()); - ConsumeToken(); - // There may be other declaration specifiers after this. - return true; - } else if (II != Tok.getIdentifierInfo()) { - // If no type was suggested, the correction is to a keyword - Tok.setKind(II->getTokenID()); - // There may be other declaration specifiers after this. - return true; - } - - // Fall through; the action had no suggestion for us. - } else { - // The action did not emit a diagnostic, so emit one now. - SourceRange R; - if (SS) R = SS->getRange(); - Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R; + Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T, + getLangOpts().CPlusPlus && + NextToken().is(tok::less)); + if (T) { + // The action has suggested that the type T could be used. Set that as + // the type in the declaration specifiers, consume the would-be type + // name token, and we're done. + const char *PrevSpec; + unsigned DiagID; + DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T, + Actions.getASTContext().getPrintingPolicy()); + DS.SetRangeEnd(Tok.getLocation()); + ConsumeToken(); + // There may be other declaration specifiers after this. + return true; + } else if (II != Tok.getIdentifierInfo()) { + // If no type was suggested, the correction is to a keyword + Tok.setKind(II->getTokenID()); + // There may be other declaration specifiers after this. + return true; } - // Mark this as an error. + // Otherwise, the action had no suggestion for us. Mark this as an error. DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); @@ -2256,8 +2233,13 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { return DSC_class; if (Context == Declarator::FileContext) return DSC_top_level; + if (Context == Declarator::TemplateTypeArgContext) + return DSC_template_type_arg; if (Context == Declarator::TrailingReturnContext) return DSC_trailing; + if (Context == Declarator::AliasDeclContext || + Context == Declarator::AliasTemplateContext) + return DSC_alias_declaration; return DSC_normal; } @@ -2282,8 +2264,8 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start, } else ER = ParseConstantExpression(); - if (getLangOpts().CPlusPlus11 && Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); + if (getLangOpts().CPlusPlus11) + TryConsumeToken(tok::ellipsis, EllipsisLoc); return ER; } @@ -2305,7 +2287,7 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, SourceLocation KWLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return; SourceLocation EllipsisLoc; @@ -2320,8 +2302,8 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, *EndLoc = T.getCloseLocation(); ArgsVector ArgExprs; - ArgExprs.push_back(ArgExpr.release()); - Attrs.addNew(KWName, KWLoc, 0, KWLoc, ArgExprs.data(), 1, + ArgExprs.push_back(ArgExpr.get()); + Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1, AttributeList::AS_Keyword, EllipsisLoc); } @@ -2339,7 +2321,6 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, assert(DS.hasTagDefinition() && "shouldn't call this"); bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); - bool HasMissingSemi = false; if (getLangOpts().CPlusPlus && (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || @@ -2349,63 +2330,77 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, return true; } + bool HasScope = Tok.is(tok::annot_cxxscope); + // Make a copy in case GetLookAheadToken invalidates the result of NextToken. + Token AfterScope = HasScope ? NextToken() : Tok; + // Determine whether the following tokens could possibly be a // declarator. - if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { - const Token &Next = NextToken(); + bool MightBeDeclarator = true; + if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) { + // A declarator-id can't start with 'typename'. + MightBeDeclarator = false; + } else if (AfterScope.is(tok::annot_template_id)) { + // If we have a type expressed as a template-id, this cannot be a + // declarator-id (such a type cannot be redeclared in a simple-declaration). + TemplateIdAnnotation *Annot = + static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue()); + if (Annot->Kind == TNK_Type_template) + MightBeDeclarator = false; + } else if (AfterScope.is(tok::identifier)) { + const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken(); + // These tokens cannot come after the declarator-id in a // simple-declaration, and are likely to come after a type-specifier. - HasMissingSemi = Next.is(tok::star) || Next.is(tok::amp) || - Next.is(tok::ampamp) || Next.is(tok::identifier) || - Next.is(tok::annot_cxxscope) || - Next.is(tok::coloncolon); - } else if (Tok.is(tok::annot_cxxscope) && - NextToken().is(tok::identifier) && - DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { - // We almost certainly have a missing semicolon. Look up the name and - // check; if it names a type, we're missing a semicolon. - CXXScopeSpec SS; - Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), - Tok.getAnnotationRange(), SS); - const Token &Next = NextToken(); - IdentifierInfo *Name = Next.getIdentifierInfo(); - Sema::NameClassification Classification = - Actions.ClassifyName(getCurScope(), SS, Name, Next.getLocation(), - NextToken(), /*IsAddressOfOperand*/false); - switch (Classification.getKind()) { - case Sema::NC_Error: - SkipMalformedDecl(); - return true; + if (Next.is(tok::star) || Next.is(tok::amp) || Next.is(tok::ampamp) || + Next.is(tok::identifier) || Next.is(tok::annot_cxxscope) || + Next.is(tok::coloncolon)) { + // Missing a semicolon. + MightBeDeclarator = false; + } else if (HasScope) { + // If the declarator-id has a scope specifier, it must redeclare a + // previously-declared entity. If that's a type (and this is not a + // typedef), that's an error. + CXXScopeSpec SS; + Actions.RestoreNestedNameSpecifierAnnotation( + Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); + IdentifierInfo *Name = AfterScope.getIdentifierInfo(); + Sema::NameClassification Classification = Actions.ClassifyName( + getCurScope(), SS, Name, AfterScope.getLocation(), Next, + /*IsAddressOfOperand*/false); + switch (Classification.getKind()) { + case Sema::NC_Error: + SkipMalformedDecl(); + return true; - case Sema::NC_Keyword: - case Sema::NC_NestedNameSpecifier: - llvm_unreachable("typo correction and nested name specifiers not " - "possible here"); + case Sema::NC_Keyword: + case Sema::NC_NestedNameSpecifier: + llvm_unreachable("typo correction and nested name specifiers not " + "possible here"); - case Sema::NC_Type: - case Sema::NC_TypeTemplate: - // Not a previously-declared non-type entity. - HasMissingSemi = true; - break; + case Sema::NC_Type: + case Sema::NC_TypeTemplate: + // Not a previously-declared non-type entity. + MightBeDeclarator = false; + break; - case Sema::NC_Unknown: - case Sema::NC_Expression: - case Sema::NC_VarTemplate: - case Sema::NC_FunctionTemplate: - // Might be a redeclaration of a prior entity. - HasMissingSemi = false; - break; + case Sema::NC_Unknown: + case Sema::NC_Expression: + case Sema::NC_VarTemplate: + case Sema::NC_FunctionTemplate: + // Might be a redeclaration of a prior entity. + break; + } } - } else if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) { - HasMissingSemi = true; } - if (!HasMissingSemi) + if (MightBeDeclarator) return false; + const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()), - diag::err_expected_semi_after_tagdecl) - << DeclSpec::getSpecifierName(DS.getTypeSpecType()); + diag::err_expected_after) + << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi; // Try to recover from the typo, by dropping the tag definition and parsing // the problematic tokens as a type. @@ -2461,9 +2456,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); bool AttrsLastTime = false; ParsedAttributesWithRange attrs(AttrFactory); + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); while (1) { bool isInvalid = false; - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID = 0; SourceLocation Loc = Tok.getLocation(); @@ -2484,7 +2480,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // 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); + DS.Finish(Diags, PP, Policy); return; case tok::l_square: @@ -2586,7 +2582,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if ((DSContext == DSC_top_level || DSContext == DSC_class) && TemplateId->Name && Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) { - if (isConstructorDeclarator()) { + if (isConstructorDeclarator(/*Unqualified*/false)) { // The user meant this to be an out-of-line constructor // definition, but template arguments are not allowed // there. Just allow this as a constructor; we'll @@ -2618,7 +2614,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParsedType T = getTypeAnnotation(Tok); isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Tok.getAnnotationEndLoc(), - PrevSpec, DiagID, T); + PrevSpec, DiagID, T, Policy); if (isInvalid) break; } @@ -2636,7 +2632,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if ((DSContext == DSC_top_level || DSContext == DSC_class) && Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(), &SS)) { - if (isConstructorDeclarator()) + if (isConstructorDeclarator(/*Unqualified*/false)) goto DoneWithDeclSpec; // As noted in C++ [class.qual]p2 (cited above), when the name @@ -2677,7 +2673,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ConsumeToken(); // The C++ scope. isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - DiagID, TypeRep); + DiagID, TypeRep, Policy); if (isInvalid) break; @@ -2696,7 +2692,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (Tok.getAnnotationValue()) { ParsedType T = getTypeAnnotation(Tok); isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - DiagID, T); + DiagID, T, Policy); } else DS.SetTypeSpecError(); @@ -2734,24 +2730,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // typedef-name case tok::kw_decltype: case tok::identifier: { + // This identifier can only be a typedef name if we haven't already seen + // a type-specifier. Without this check we misparse: + // typedef int X; struct Y { short X; }; as 'short int'. + if (DS.hasTypeSpecifier()) + goto DoneWithDeclSpec; + // In C++, check to see if this is a scope specifier like foo::bar::, if // so handle it as such. This is important for ctor parsing. if (getLangOpts().CPlusPlus) { if (TryAnnotateCXXScopeToken(EnteringContext)) { - if (!DS.hasTypeSpecifier()) - DS.SetTypeSpecError(); + DS.SetTypeSpecError(); goto DoneWithDeclSpec; } if (!Tok.is(tok::identifier)) continue; } - // This identifier can only be a typedef name if we haven't already seen - // a type-specifier. Without this check we misparse: - // typedef int X; struct Y { short X; }; as 'short int'. - if (DS.hasTypeSpecifier()) - goto DoneWithDeclSpec; - // Check for need to substitute AltiVec keyword tokens. if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid)) break; @@ -2765,11 +2760,21 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope()); + // MSVC: If we weren't able to parse a default template argument, and it's + // just a simple identifier, create a DependentNameType. This will allow us + // to defer the name lookup to template instantiation time, as long we forge a + // NestedNameSpecifier for the current context. + if (!TypeRep && DSContext == DSC_template_type_arg && + getLangOpts().MSVCCompat && getCurScope()->isTemplateParamScope()) { + TypeRep = Actions.ActOnDelayedDefaultTemplateArg( + *Tok.getIdentifierInfo(), Tok.getLocation()); + } + // If this is not a typedef name, don't parse it as part of the declspec, // it must be an implicit int or an error. if (!TypeRep) { ParsedAttributesWithRange Attrs(AttrFactory); - if (ParseImplicitInt(DS, 0, TemplateInfo, AS, DSContext, Attrs)) { + if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) { if (!Attrs.empty()) { AttrsLastTime = true; attrs.takeAllFrom(Attrs); @@ -2783,11 +2788,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // check whether this is a constructor declaration. if (getLangOpts().CPlusPlus && DSContext == DSC_class && Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && - isConstructorDeclarator()) + isConstructorDeclarator(/*Unqualified*/true)) goto DoneWithDeclSpec; isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - DiagID, TypeRep); + DiagID, TypeRep, Policy); if (isInvalid) break; @@ -2819,7 +2824,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // constructor declaration. if (getLangOpts().CPlusPlus && DSContext == DSC_class && Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) && - isConstructorDeclarator()) + isConstructorDeclarator(TemplateId->SS.isEmpty())) goto DoneWithDeclSpec; // Turn the template-id annotation token into a type annotation @@ -2830,7 +2835,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // GNU attributes support. case tok::kw___attribute: - ParseGNUAttributes(DS.getAttributes(), 0, LateAttrs); + ParseGNUAttributes(DS.getAttributes(), nullptr, LateAttrs); continue; // Microsoft declspec support. @@ -2843,10 +2848,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID); IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); - // FIXME: This does not work correctly if it is set to be a declspec - // attribute, and a GNU attribute is simply incorrect. - DS.getAttributes().addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, - AttributeList::AS_GNU); + DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, + nullptr, 0, AttributeList::AS_Keyword); break; } @@ -2876,46 +2879,46 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // storage-class-specifier case tok::kw_typedef: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); break; case tok::kw_extern: if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread) Diag(Tok, diag::ext_thread_before) << "extern"; isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); break; case tok::kw___private_extern__: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern, - Loc, PrevSpec, DiagID); + Loc, PrevSpec, DiagID, Policy); break; case tok::kw_static: if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread) Diag(Tok, diag::ext_thread_before) << "static"; isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); break; case tok::kw_auto: if (getLangOpts().CPlusPlus11) { if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); if (!isInvalid) Diag(Tok, diag::ext_auto_storage_class) << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); } else isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, - DiagID); + DiagID, Policy); } else isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); break; case tok::kw_register: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); break; case tok::kw_mutable: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); break; case tok::kw___thread: isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc, @@ -2977,19 +2980,19 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // type-specifier case tok::kw_short: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_long: if (DS.getTypeSpecWidth() != DeclSpec::TSW_long) isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, - DiagID); + DiagID, Policy); else isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw___int64: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_signed: isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, @@ -3009,43 +3012,43 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; case tok::kw_void: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_char: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_int: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw___int128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_half: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_float: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_double: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_wchar_t: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_char16_t: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_char32_t: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw_bool: case tok::kw__Bool: @@ -3059,62 +3062,30 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = true; } else { isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, - DiagID); + DiagID, Policy); } break; case tok::kw__Decimal32: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw__Decimal64: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw__Decimal128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, - DiagID); + DiagID, Policy); break; case tok::kw___vector: - isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy); break; case tok::kw___pixel: - isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); - break; - case tok::kw_image1d_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_t, Loc, - PrevSpec, DiagID); - break; - case tok::kw_image1d_array_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_array_t, Loc, - PrevSpec, DiagID); - break; - case tok::kw_image1d_buffer_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_buffer_t, Loc, - PrevSpec, DiagID); - break; - case tok::kw_image2d_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_t, Loc, - PrevSpec, DiagID); - break; - case tok::kw_image2d_array_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_array_t, Loc, - PrevSpec, DiagID); - break; - case tok::kw_image3d_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image3d_t, Loc, - PrevSpec, DiagID); - break; - case tok::kw_sampler_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_sampler_t, Loc, - PrevSpec, DiagID); - break; - case tok::kw_event_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_event_t, Loc, - PrevSpec, DiagID); + isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy); break; case tok::kw___unknown_anytype: isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, Policy); break; // class-specifier: @@ -3198,9 +3169,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; // OpenCL qualifiers: - case tok::kw_private: - if (!getLangOpts().OpenCL) - goto DoneWithDeclSpec; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -3208,7 +3176,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___read_only: case tok::kw___write_only: case tok::kw___read_write: - ParseOpenCLQualifiers(DS); + ParseOpenCLQualifiers(DS.getAttributes()); break; case tok::less: @@ -3305,13 +3273,12 @@ ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) { ParseDeclarator(DeclaratorInfo.D); } - if (Tok.is(tok::colon)) { - ConsumeToken(); + if (TryConsumeToken(tok::colon)) { ExprResult Res(ParseConstantExpression()); if (Res.isInvalid()) SkipUntil(tok::semi, StopBeforeMatch); else - DeclaratorInfo.BitfieldSize = Res.release(); + DeclaratorInfo.BitfieldSize = Res.get(); } // If attributes exist after the declarator, parse them. @@ -3322,12 +3289,9 @@ ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) { // 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)) + if (!TryConsumeToken(tok::comma, CommaLoc)) return; - // Consume the comma. - CommaLoc = ConsumeToken(); - FirstDeclarator = false; } } @@ -3358,7 +3322,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, 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)) { + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // Each iteration of this loop reads one struct-declaration. // Check for extraneous top-level semicolon. @@ -3394,7 +3358,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, SmallVectorImpl<Decl *> &FieldDecls) : P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {} - void invoke(ParsingFieldDeclarator &FD) { + void invoke(ParsingFieldDeclarator &FD) override { // Install the declarator into the current TagDecl. Decl *Field = P.Actions.ActOnField(P.getCurScope(), TagDecl, FD.D.getDeclSpec().getSourceRange().getBegin(), @@ -3415,9 +3379,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, continue; } ConsumeToken(); - ExpectAndConsume(tok::l_paren, diag::err_expected_lparen); + ExpectAndConsume(tok::l_paren); if (!Tok.is(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::semi); continue; } @@ -3426,21 +3390,22 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, Tok.getIdentifierInfo(), Fields); FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end()); ConsumeToken(); - ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); + ExpectAndConsume(tok::r_paren); } - if (Tok.is(tok::semi)) { - ConsumeToken(); - } else if (Tok.is(tok::r_brace)) { + if (TryConsumeToken(tok::semi)) + continue; + + if (Tok.is(tok::r_brace)) { ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list); break; - } else { - ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); - // Skip to end of block or statement to avoid ext-warning on extra ';'. - SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); - // If we stopped at a ';', eat it. - if (Tok.is(tok::semi)) ConsumeToken(); } + + ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); + // Skip to end of block or statement to avoid ext-warning on extra ';'. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + // If we stopped at a ';', eat it. + TryConsumeToken(tok::semi); } T.consumeClose(); @@ -3557,7 +3522,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; if (SS.isSet() && Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; if (Tok.isNot(tok::l_brace)) { // Has no name and is not a definition. // Skip the rest of this declarator, up until the comma or semicolon. @@ -3570,7 +3535,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // Must have either 'enum name' or 'enum {...}'. if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) && !(AllowFixedUnderlyingType && Tok.is(tok::colon))) { - Diag(Tok, diag::err_expected_ident_lbrace); + Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; // Skip the rest of this declarator, up until the comma or semicolon. SkipUntil(tok::comma, StopAtSemi); @@ -3578,7 +3543,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } // If an identifier is present, consume and remember it. - IdentifierInfo *Name = 0; + IdentifierInfo *Name = nullptr; SourceLocation NameLoc; if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); @@ -3617,13 +3582,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind()); // If the next token starts an expression, we know we're parsing a // bit-field. This is the common case. - if (TPR == TPResult::True()) + if (TPR == TPResult::True) PossibleBitfield = true; // If the next token starts a type-specifier-seq, it may be either a // a fixed underlying type or the start of a function-style cast in C++; // lookahead one more token to see if it's obvious that we have a // fixed underlying type. - else if (TPR == TPResult::False() && + else if (TPR == TPResult::False && GetLookAheadToken(2).getKind() == tok::semi) { // Consume the ':'. ConsumeToken(); @@ -3643,7 +3608,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // FIXME: The standard is not entirely clear on how to disambiguate in // this case. if ((getLangOpts().CPlusPlus && - isCXXDeclarationSpecifier(TPResult::True()) != TPResult::True()) || + isCXXDeclarationSpecifier(TPResult::True) != TPResult::True) || (!getLangOpts().CPlusPlus && !isDeclarationSpecifier(true))) { // We'll parse this as a bitfield later. PossibleBitfield = true; @@ -3696,15 +3661,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } else { TUK = Sema::TUK_Definition; } - } else if (DSC != DSC_type_specifier && + } else if (!isTypeSpecifier(DSC) && (Tok.is(tok::semi) || (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(CanBeBitfield)))) { TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; if (Tok.isNot(tok::semi)) { // A semicolon was missing after this declaration. Diagnose and recover. - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - "enum"); + ExpectAndConsume(tok::semi, diag::err_expected_after, "enum"); PP.EnterToken(Tok); Tok.setKind(tok::semi); } @@ -3753,13 +3717,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, bool Owned = false; bool IsDependent = false; - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, ScopedEnumKWLoc, - IsScopedUsingClassTag, BaseType); + IsScopedUsingClassTag, BaseType, + DSC == DSC_type_specifier); if (IsDependent) { // This enum has a dependent nested-name-specifier. Handle it as a @@ -3770,9 +3735,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } - TypeResult Type = Actions.ActOnDependentTag(getCurScope(), DeclSpec::TST_enum, - TUK, SS, Name, StartLoc, - NameLoc); + TypeResult Type = Actions.ActOnDependentTag( + getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc); if (Type.isInvalid()) { DS.SetTypeSpecError(); return; @@ -3780,7 +3744,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, - PrevSpec, DiagID, Type.get())) + PrevSpec, DiagID, Type.get(), + Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; return; @@ -3803,7 +3768,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, - PrevSpec, DiagID, TagDecl, Owned)) + PrevSpec, DiagID, TagDecl, Owned, + Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; } @@ -3819,7 +3785,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, /// void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // Enter the scope of the enum body and start the definition. - ParseScope EnumScope(this, Scope::DeclScope); + ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope); Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl); BalancedDelimiterTracker T(*this, tok::l_brace); @@ -3831,10 +3797,19 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { SmallVector<Decl *, 32> EnumConstantDecls; - Decl *LastEnumConstDecl = 0; + Decl *LastEnumConstDecl = nullptr; // Parse the enumerator-list. - while (Tok.is(tok::identifier)) { + while (Tok.isNot(tok::r_brace)) { + // Parse enumerator. If failed, try skipping till the start of the next + // enumerator definition. + if (Tok.isNot(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; + if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) && + TryConsumeToken(tok::comma)) + continue; + break; + } IdentifierInfo *Ident = Tok.getIdentifierInfo(); SourceLocation IdentLoc = ConsumeToken(); @@ -3848,11 +3823,10 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { ExprResult AssignedVal; ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); + if (TryConsumeToken(tok::equal, EqualLoc)) { AssignedVal = ParseConstantExpression(); if (AssignedVal.isInvalid()) - SkipUntil(tok::comma, tok::r_brace, StopAtSemi | StopBeforeMatch); + SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch); } // Install the enumerator constant into EnumDecl. @@ -3860,7 +3834,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { LastEnumConstDecl, IdentLoc, Ident, attrs.getList(), EqualLoc, - AssignedVal.release()); + AssignedVal.get()); PD.complete(EnumConstDecl); EnumConstantDecls.push_back(EnumConstDecl); @@ -3874,11 +3848,25 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { continue; } - if (Tok.isNot(tok::comma)) - break; - SourceLocation CommaLoc = ConsumeToken(); + // Emumerator definition must be finished, only comma or r_brace are + // allowed here. + SourceLocation CommaLoc; + if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) { + if (EqualLoc.isValid()) + Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace + << tok::comma; + else + Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator); + if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) { + if (TryConsumeToken(tok::comma, CommaLoc)) + continue; + } else { + break; + } + } - if (Tok.isNot(tok::identifier)) { + // If comma is followed by r_brace, emit appropriate warning. + if (Tok.is(tok::r_brace) && CommaLoc.isValid()) { if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11) Diag(CommaLoc, getLangOpts().CPlusPlus ? diag::ext_enumerator_list_comma_cxx : @@ -3887,6 +3875,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { else if (getLangOpts().CPlusPlus11) Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma) << FixItHint::CreateRemoval(CommaLoc); + break; } } @@ -3910,7 +3899,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // was probably forgotten. bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope; if (!isValidAfterTypeSpecifier(CanBeBitfield)) { - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, "enum"); + ExpectAndConsume(tok::semi, diag::err_expected_after, "enum"); // Push this token back into the preprocessor and change our current token // to ';' so that the rest of the code recovers as though there were an // ';' after the definition. @@ -3924,12 +3913,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { bool Parser::isTypeQualifier() const { switch (Tok.getKind()) { default: return false; - - // type-qualifier only in OpenCL - case tok::kw_private: - return getLangOpts().OpenCL; - - // type-qualifier + // type-qualifier case tok::kw_const: case tok::kw_volatile: case tok::kw_restrict: @@ -3975,16 +3959,6 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { case tok::kw__Decimal128: case tok::kw___vector: - // OpenCL specific types: - case tok::kw_image1d_t: - case tok::kw_image1d_array_t: - case tok::kw_image1d_buffer_t: - case tok::kw_image2d_t: - case tok::kw_image2d_array_t: - case tok::kw_image3d_t: - case tok::kw_sampler_t: - case tok::kw_event_t: - // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: @@ -4057,16 +4031,6 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw__Decimal128: case tok::kw___vector: - // OpenCL specific types: - case tok::kw_image1d_t: - case tok::kw_image1d_array_t: - case tok::kw_image1d_buffer_t: - case tok::kw_image2d_t: - case tok::kw_image2d_array_t: - case tok::kw_image3d_t: - case tok::kw_sampler_t: - case tok::kw_event_t: - // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: @@ -4111,9 +4075,6 @@ bool Parser::isTypeSpecifierQualifier() { return true; - case tok::kw_private: - return getLangOpts().OpenCL; - // C11 _Atomic case tok::kw__Atomic: return true; @@ -4129,9 +4090,6 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { switch (Tok.getKind()) { default: return false; - case tok::kw_private: - return getLangOpts().OpenCL; - case tok::identifier: // foo::bar // Unfortunate hack to support "Class.factoryMethod" notation. if (getLangOpts().ObjC1 && NextToken().is(tok::period)) @@ -4213,16 +4171,6 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw__Decimal128: case tok::kw___vector: - // OpenCL specific types: - case tok::kw_image1d_t: - case tok::kw_image1d_array_t: - case tok::kw_image1d_buffer_t: - case tok::kw_image2d_t: - case tok::kw_image2d_array_t: - case tok::kw_image3d_t: - case tok::kw_sampler_t: - case tok::kw_event_t: - // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: @@ -4300,7 +4248,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { } } -bool Parser::isConstructorDeclarator() { +bool Parser::isConstructorDeclarator(bool IsUnqualified) { TentativeParsingAction TPA(*this); // Parse the C++ scope specifier. @@ -4382,12 +4330,35 @@ bool Parser::isConstructorDeclarator() { case tok::coloncolon: // C(X :: Y); // C(X :: *p); - case tok::r_paren: - // C(X ) // Assume this isn't a constructor, rather than assuming it's a // constructor with an unnamed parameter of an ill-formed type. break; + case tok::r_paren: + // C(X ) + if (NextToken().is(tok::colon) || NextToken().is(tok::kw_try)) { + // Assume these were meant to be constructors: + // C(X) : (the name of a bit-field cannot be parenthesized). + // C(X) try (this is otherwise ill-formed). + IsConstructor = true; + } + if (NextToken().is(tok::semi) || NextToken().is(tok::l_brace)) { + // If we have a constructor name within the class definition, + // assume these were meant to be constructors: + // C(X) { + // C(X) ; + // ... because otherwise we would be declaring a non-static data + // member that is ill-formed because it's of the same type as its + // surrounding class. + // + // FIXME: We can actually do this whether or not the name is qualified, + // because if it is qualified in this context it must be being used as + // a constructor name. However, we do not implement that rule correctly + // currently, so we're somewhat conservative here. + IsConstructor = IsUnqualified; + } + break; + default: IsConstructor = true; break; @@ -4426,7 +4397,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, while (1) { bool isInvalid = false; - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID = 0; SourceLocation Loc = Tok.getLocation(); @@ -4455,9 +4426,6 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, break; // OpenCL qualifiers: - case tok::kw_private: - if (!getLangOpts().OpenCL) - goto DoneWithTypeQuals; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -4465,7 +4433,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___read_only: case tok::kw___write_only: case tok::kw___read_write: - ParseOpenCLQualifiers(DS); + ParseOpenCLQualifiers(DS.getAttributes()); break; case tok::kw___uptr: @@ -4506,7 +4474,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, DoneWithTypeQuals: // If this is not a type-qualifier token, we're done reading type // qualifiers. First verify that DeclSpec's are consistent. - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy()); if (EndLoc.isValid()) DS.SetRangeEnd(EndLoc); return; @@ -4575,7 +4543,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Member pointers get special handling, since there's no place for the // scope spec in the generic path below. if (getLangOpts().CPlusPlus && - (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) || + (Tok.is(tok::coloncolon) || + (Tok.is(tok::identifier) && + (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) || Tok.is(tok::annot_cxxscope))) { bool EnteringContext = D.getContext() == Declarator::FileContext || D.getContext() == Declarator::MemberContext; @@ -4710,17 +4680,17 @@ void Parser::ParseDeclaratorInternal(Declarator &D, } } -static void diagnoseMisplacedEllipsis(Parser &P, Declarator &D, - SourceLocation EllipsisLoc) { - if (EllipsisLoc.isValid()) { - FixItHint Insertion; - if (!D.getEllipsisLoc().isValid()) { - Insertion = FixItHint::CreateInsertion(D.getIdentifierLoc(), "..."); - D.setEllipsisLoc(EllipsisLoc); - } - P.Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration) - << FixItHint::CreateRemoval(EllipsisLoc) << Insertion << !D.hasName(); - } +// When correcting from misplaced brackets before the identifier, the location +// is saved inside the declarator so that other diagnostic messages can use +// them. This extracts and returns that location, or returns the provided +// location if a stored location does not exist. +static SourceLocation getMissingDeclaratorIdLoc(Declarator &D, + SourceLocation Loc) { + if (D.getName().StartLocation.isInvalid() && + D.getName().EndLocation.isValid()) + return D.getName().EndLocation; + + return Loc; } /// ParseDirectDeclarator @@ -4768,6 +4738,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) { DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec()); if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) { + // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in + // this context it is a bitfield. Also in range-based for statement colon + // may delimit for-range-declaration. + ColonProtectionRAIIObject X(*this, + D.getContext() == Declarator::MemberContext || + (D.getContext() == Declarator::ForContext && + getLangOpts().CPlusPlus11)); + // ParseDeclaratorInternal might already have parsed the scope. if (D.getCXXScopeSpec().isEmpty()) { bool EnteringContext = D.getContext() == Declarator::FileContext || @@ -4802,7 +4780,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // The ellipsis was put in the wrong place. Recover, and explain to // the user what they should have done. ParseDeclarator(D); - diagnoseMisplacedEllipsis(*this, D, EllipsisLoc); + if (EllipsisLoc.isValid()) + DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D); return; } else D.setEllipsisLoc(EllipsisLoc); @@ -4837,7 +4816,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // Once we're past the identifier, if the scope was bad, mark the // whole declarator bad. D.getCXXScopeSpec().isInvalid()) { - D.SetIdentifier(0, Tok.getLocation()); + D.SetIdentifier(nullptr, Tok.getLocation()); D.setInvalidType(true); } else { // Parsed the unqualified-id; update range information and move along. @@ -4852,6 +4831,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { "There's a C++-specific check for tok::identifier above"); assert(Tok.getIdentifierInfo() && "Not an identifier?"); D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + D.SetRangeEnd(Tok.getLocation()); ConsumeToken(); goto PastIdentifier; } else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) { @@ -4861,7 +4841,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { !isCXX11VirtSpecifier(Tok)) { Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id) << FixItHint::CreateRemoval(Tok.getLocation()); - D.SetIdentifier(0, Tok.getLocation()); + D.SetIdentifier(nullptr, Tok.getLocation()); ConsumeToken(); goto PastIdentifier; } @@ -4888,7 +4868,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } else if (D.mayOmitIdentifier()) { // This could be something simple like "int" (in which case the declarator // portion is empty), if an abstract-declarator is allowed. - D.SetIdentifier(0, Tok.getLocation()); + D.SetIdentifier(nullptr, Tok.getLocation()); // The grammar for abstract-pack-declarator does not allow grouping parens. // FIXME: Revisit this once core issue 1488 is resolved. @@ -4898,10 +4878,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } else { if (Tok.getKind() == tok::annot_pragma_parser_crash) LLVM_BUILTIN_TRAP; - if (D.getContext() == Declarator::MemberContext) - Diag(Tok, diag::err_expected_member_name_or_semi) - << D.getDeclSpec().getSourceRange(); - else if (getLangOpts().CPlusPlus) { + if (Tok.is(tok::l_square)) + return ParseMisplacedBracketDeclarator(D); + if (D.getContext() == Declarator::MemberContext) { + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_member_name_or_semi) + << (D.getDeclSpec().isEmpty() ? SourceRange() + : D.getDeclSpec().getSourceRange()); + } else if (getLangOpts().CPlusPlus) { if (Tok.is(tok::period) || Tok.is(tok::arrow)) Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); else { @@ -4910,12 +4894,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) { Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus; else - Diag(Tok, diag::err_expected_unqualified_id) + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus; } - } else - Diag(Tok, diag::err_expected_ident_lparen); - D.SetIdentifier(0, Tok.getLocation()); + } else { + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_either) + << tok::identifier << tok::l_paren; + } + D.SetIdentifier(nullptr, Tok.getLocation()); D.setInvalidType(true); } @@ -5051,7 +5039,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // An ellipsis cannot be placed outside parentheses. if (EllipsisLoc.isValid()) - diagnoseMisplacedEllipsis(*this, D, EllipsisLoc); + DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D); return; } @@ -5060,7 +5048,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // argument list. Recognize that this declarator will never have an // identifier (and remember where it would have been), then call into // ParseFunctionDeclarator to handle of argument list. - D.SetIdentifier(0, Tok.getLocation()); + D.SetIdentifier(nullptr, Tok.getLocation()); // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. @@ -5122,7 +5110,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D, ParsedAttributes FnAttrs(AttrFactory); TypeResult TrailingReturnType; - Actions.ActOnStartFunctionDeclarator(); /* LocalEndLoc is the end location for the local FunctionTypeLoc. EndLoc is the end location for the function declarator. They differ for trailing return types. */ @@ -5191,6 +5178,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // FIXME: currently, "static" case isn't handled correctly. bool IsCXX11MemberFunction = getLangOpts().CPlusPlus11 && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && (D.getContext() == Declarator::MemberContext ? !D.getDeclSpec().isFriendSpecified() : D.getContext() == Declarator::FileContext && @@ -5246,12 +5234,10 @@ void Parser::ParseFunctionDeclarator(Declarator &D, DynamicExceptionRanges.data(), DynamicExceptions.size(), NoexceptExpr.isUsable() ? - NoexceptExpr.get() : 0, + NoexceptExpr.get() : nullptr, StartLoc, LocalEndLoc, D, TrailingReturnType), FnAttrs, EndLoc); - - Actions.ActOnEndFunctionDeclarator(); } /// isFunctionDeclaratorIdentifierList - This parameter list may have an @@ -5303,10 +5289,10 @@ void Parser::ParseFunctionDeclaratorIdentifierList( // Maintain an efficient lookup of params we have seen so far. llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar; - while (1) { + do { // If this isn't an identifier, report the error and skip until ')'. if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); // Forget we parsed anything. ParamInfo.clear(); @@ -5326,17 +5312,13 @@ void Parser::ParseFunctionDeclaratorIdentifierList( // Remember this identifier in ParamInfo. ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, Tok.getLocation(), - 0)); + nullptr)); } // Eat the identifier. ConsumeToken(); - // The list continues if we see a comma. - if (Tok.isNot(tok::comma)) - break; - ConsumeToken(); - } + } while (TryConsumeToken(tok::comma)); } /// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list @@ -5375,13 +5357,11 @@ void Parser::ParseParameterDeclarationClause( ParsedAttributes &FirstArgAttrs, SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, SourceLocation &EllipsisLoc) { - while (1) { - if (Tok.is(tok::ellipsis)) { - // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq - // before deciding this was a parameter-declaration-clause. - EllipsisLoc = ConsumeToken(); // Consume the ellipsis. + do { + // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq + // before deciding this was a parameter-declaration-clause. + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) break; - } // Parse the declaration-specifiers. // Just use the ParsingDeclaration "scope" of the declarator. @@ -5422,11 +5402,11 @@ void Parser::ParseParameterDeclarationClause( // DefArgToks is used when the parsing of default arguments needs // to be delayed. - CachedTokens *DefArgToks = 0; + CachedTokens *DefArgToks = nullptr; // If no parameter was specified, verify that *something* was specified, // otherwise we have a missing type and identifier. - if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 && + if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr && ParmDeclarator.getNumTypeObjects() == 0) { // Completely missing, emit error. Diag(DSStart, diag::err_missing_param); @@ -5455,8 +5435,8 @@ void Parser::ParseParameterDeclarationClause( if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) { delete DefArgToks; - DefArgToks = 0; - Actions.ActOnParamDefaultArgumentError(Param); + DefArgToks = nullptr; + Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); } else { // Mark the end of the default argument so that we know when to // stop when we parse it later on. @@ -5485,12 +5465,12 @@ void Parser::ParseParameterDeclarationClause( } else DefArgResult = ParseAssignmentExpression(); if (DefArgResult.isInvalid()) { - Actions.ActOnParamDefaultArgumentError(Param); + Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch); } else { // Inform the actions module about the default argument Actions.ActOnParamDefaultArgument(Param, EqualLoc, - DefArgResult.take()); + DefArgResult.get()); } } } @@ -5500,26 +5480,17 @@ void Parser::ParseParameterDeclarationClause( Param, DefArgToks)); } - // If the next token is a comma, consume it and keep reading arguments. - if (Tok.isNot(tok::comma)) { - if (Tok.is(tok::ellipsis)) { - EllipsisLoc = ConsumeToken(); // Consume the ellipsis. - - if (!getLangOpts().CPlusPlus) { - // We have ellipsis without a preceding ',', which is ill-formed - // in C. Complain and provide the fix. - Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis) - << FixItHint::CreateInsertion(EllipsisLoc, ", "); - } - } - + if (TryConsumeToken(tok::ellipsis, EllipsisLoc) && + !getLangOpts().CPlusPlus) { + // We have ellipsis without a preceding ',', which is ill-formed + // in C. Complain and provide the fix. + Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis) + << FixItHint::CreateInsertion(EllipsisLoc, ", "); break; } - // Consume the comma. - ConsumeToken(); - } - + // If the next token is a comma, consume it and keep reading arguments. + } while (TryConsumeToken(tok::comma)); } /// [C90] direct-declarator '[' constant-expression[opt] ']' @@ -5544,8 +5515,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { MaybeParseCXX11Attributes(attrs); // Remember that we parsed the empty array type. - ExprResult NumElements; - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr, T.getOpenLocation(), T.getCloseLocation()), attrs, T.getCloseLocation()); @@ -5562,7 +5532,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, - ExprRes.release(), + ExprRes.get(), T.getOpenLocation(), T.getCloseLocation()), attrs, T.getCloseLocation()); @@ -5571,8 +5541,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // If valid, this location is the position where we read the 'static' keyword. SourceLocation StaticLoc; - if (Tok.is(tok::kw_static)) - StaticLoc = ConsumeToken(); + TryConsumeToken(tok::kw_static, StaticLoc); // If there is a type-qualifier-list, read it now. // Type qualifiers in an array subscript are a C99 feature. @@ -5581,8 +5550,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // If we haven't already read 'static', check to see if there is one after the // type-qualifier-list. - if (!StaticLoc.isValid() && Tok.is(tok::kw_static)) - StaticLoc = ConsumeToken(); + if (!StaticLoc.isValid()) + TryConsumeToken(tok::kw_static, StaticLoc); // Handle "direct-declarator [ type-qual-list[opt] * ]". bool isStar = false; @@ -5633,12 +5602,102 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), isStar, - NumElements.release(), + NumElements.get(), T.getOpenLocation(), T.getCloseLocation()), attrs, T.getCloseLocation()); } +/// Diagnose brackets before an identifier. +void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { + assert(Tok.is(tok::l_square) && "Missing opening bracket"); + assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier"); + + SourceLocation StartBracketLoc = Tok.getLocation(); + Declarator TempDeclarator(D.getDeclSpec(), D.getContext()); + + while (Tok.is(tok::l_square)) { + ParseBracketDeclarator(TempDeclarator); + } + + // Stuff the location of the start of the brackets into the Declarator. + // The diagnostics from ParseDirectDeclarator will make more sense if + // they use this location instead. + if (Tok.is(tok::semi)) + D.getName().EndLocation = StartBracketLoc; + + SourceLocation SuggestParenLoc = Tok.getLocation(); + + // Now that the brackets are removed, try parsing the declarator again. + ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); + + // Something went wrong parsing the brackets, in which case, + // ParseBracketDeclarator has emitted an error, and we don't need to emit + // one here. + if (TempDeclarator.getNumTypeObjects() == 0) + return; + + // Determine if parens will need to be suggested in the diagnostic. + bool NeedParens = false; + if (D.getNumTypeObjects() != 0) { + switch (D.getTypeObject(D.getNumTypeObjects() - 1).Kind) { + case DeclaratorChunk::Pointer: + case DeclaratorChunk::Reference: + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::MemberPointer: + NeedParens = true; + break; + case DeclaratorChunk::Array: + case DeclaratorChunk::Function: + case DeclaratorChunk::Paren: + break; + } + } + + if (NeedParens) { + // Create a DeclaratorChunk for the inserted parens. + ParsedAttributes attrs(AttrFactory); + SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd()); + D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), attrs, + SourceLocation()); + } + + // Adding back the bracket info to the end of the Declarator. + for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) { + const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i); + ParsedAttributes attrs(AttrFactory); + attrs.set(Chunk.Common.AttrList); + D.AddTypeInfo(Chunk, attrs, SourceLocation()); + } + + // The missing identifier would have been diagnosed in ParseDirectDeclarator. + // If parentheses are required, always suggest them. + if (!D.getIdentifier() && !NeedParens) + return; + + SourceLocation EndBracketLoc = TempDeclarator.getLocEnd(); + + // Generate the move bracket error message. + SourceRange BracketRange(StartBracketLoc, EndBracketLoc); + SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd()); + + if (NeedParens) { + Diag(EndLoc, diag::err_brackets_go_after_unqualified_id) + << getLangOpts().CPlusPlus + << FixItHint::CreateInsertion(SuggestParenLoc, "(") + << FixItHint::CreateInsertion(EndLoc, ")") + << FixItHint::CreateInsertionFromRange( + EndLoc, CharSourceRange(BracketRange, true)) + << FixItHint::CreateRemoval(BracketRange); + } else { + Diag(EndLoc, diag::err_brackets_go_after_unqualified_id) + << getLangOpts().CPlusPlus + << FixItHint::CreateInsertionFromRange( + EndLoc, CharSourceRange(BracketRange, true)) + << FixItHint::CreateRemoval(BracketRange); + } +} + /// [GNU] typeof-specifier: /// typeof ( expressions ) /// typeof ( type-name ) @@ -5674,11 +5733,12 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { return; } - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec, - DiagID, CastTy)) + DiagID, CastTy, + Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; return; } @@ -5696,11 +5756,12 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { return; } - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec, - DiagID, Operand.get())) + DiagID, Operand.get(), + Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; } @@ -5731,10 +5792,11 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) { DS.setTypeofParensRange(T.getRange()); DS.SetRangeEnd(T.getCloseLocation()); - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec, - DiagID, Result.release())) + DiagID, Result.get(), + Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; } @@ -5774,6 +5836,7 @@ bool Parser::TryAltiVecVectorTokenOutOfLine() { bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, bool &isInvalid) { + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); if (Tok.getIdentifierInfo() == Ident_vector) { Token Next = NextToken(); switch (Next.getKind()) { @@ -5788,15 +5851,15 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, case tok::kw_double: case tok::kw_bool: case tok::kw___pixel: - isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy); return true; case tok::identifier: if (Next.getIdentifierInfo() == Ident_pixel) { - isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy); return true; } if (Next.getIdentifierInfo() == Ident_bool) { - isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID); + isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy); return true; } break; @@ -5805,11 +5868,11 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, } } else if ((Tok.getIdentifierInfo() == Ident_pixel) && DS.isTypeAltiVecVector()) { - isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID); + isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy); return true; } else if ((Tok.getIdentifierInfo() == Ident_bool) && DS.isTypeAltiVecVector()) { - isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID); + isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy); return true; } return false; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index dd29f99..6200363 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -13,9 +13,12 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/OperatorKinds.h" -#include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" @@ -61,11 +64,11 @@ Decl *Parser::ParseNamespace(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceDecl(getCurScope()); cutOffParsing(); - return 0; + return nullptr; } SourceLocation IdentLoc; - IdentifierInfo *Ident = 0; + IdentifierInfo *Ident = nullptr; std::vector<SourceLocation> ExtraIdentLoc; std::vector<IdentifierInfo*> ExtraIdent; std::vector<SourceLocation> ExtraNamespaceLoc; @@ -90,11 +93,11 @@ Decl *Parser::ParseNamespace(unsigned Context, } if (Tok.is(tok::equal)) { - if (Ident == 0) { - Diag(Tok, diag::err_expected_ident); + if (!Ident) { + Diag(Tok, diag::err_expected) << tok::identifier; // Skip to end of the definition and eat the ';'. SkipUntil(tok::semi); - return 0; + return nullptr; } if (!attrs.empty()) Diag(attrTok, diag::err_unexpected_namespace_attributes_alias); @@ -111,9 +114,13 @@ Decl *Parser::ParseNamespace(unsigned Context, Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); } - Diag(Tok, Ident ? diag::err_expected_lbrace : - diag::err_expected_ident_lbrace); - return 0; + + if (Ident) + Diag(Tok, diag::err_expected) << tok::l_brace; + else + Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; + + return nullptr; } if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || @@ -125,7 +132,7 @@ Decl *Parser::ParseNamespace(unsigned Context, } Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace); - return 0; + return nullptr; } if (!ExtraIdent.empty()) { @@ -195,7 +202,7 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, ParsedAttributes& attrs, BalancedDelimiterTracker &Tracker) { if (index == Ident.size()) { - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); @@ -239,7 +246,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceAliasDecl(getCurScope()); cutOffParsing(); - return 0; + return nullptr; } CXXScopeSpec SS; @@ -250,7 +257,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, Diag(Tok, diag::err_expected_namespace_name); // Skip to end of the definition and eat the ';'. SkipUntil(tok::semi); - return 0; + return nullptr; } // Parse identifier. @@ -259,8 +266,8 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, // Eat the ';'. DeclEnd = Tok.getLocation(); - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name, - "", tok::semi); + if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name)) + SkipUntil(tok::semi); return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, Alias, SS, IdentLoc, Ident); @@ -274,27 +281,16 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, /// 'extern' string-literal declaration /// Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { - assert(Tok.is(tok::string_literal) && "Not a string literal!"); - SmallString<8> LangBuffer; - bool Invalid = false; - StringRef Lang = PP.getSpelling(Tok, LangBuffer, &Invalid); - if (Invalid) - return 0; - - // FIXME: This is incorrect: linkage-specifiers are parsed in translation - // phase 7, so string-literal concatenation is supposed to occur. - // extern "" "C" "" "+" "+" { } is legal. - if (Tok.hasUDSuffix()) - Diag(Tok, diag::err_invalid_string_udl); - SourceLocation Loc = ConsumeStringToken(); + assert(isTokenStringLiteral() && "Not a string literal!"); + ExprResult Lang = ParseStringLiteralExpression(false); ParseScope LinkageScope(this, Scope::DeclScope); - Decl *LinkageSpec - = Actions.ActOnStartLinkageSpecification(getCurScope(), - DS.getSourceRange().getBegin(), - Loc, Lang, - Tok.is(tok::l_brace) ? Tok.getLocation() - : SourceLocation()); + Decl *LinkageSpec = + Lang.isInvalid() + ? nullptr + : Actions.ActOnStartLinkageSpecification( + getCurScope(), DS.getSourceRange().getBegin(), Lang.get(), + Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); @@ -308,8 +304,9 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { // ... but anyway remember that such an "extern" was seen. DS.setExternInLinkageSpec(true); ParseExternalDeclaration(attrs, &DS); - return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec, - SourceLocation()); + return LinkageSpec ? Actions.ActOnFinishLinkageSpecification( + getCurScope(), LinkageSpec, SourceLocation()) + : nullptr; } DS.abort(); @@ -318,16 +315,48 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs); - MaybeParseMicrosoftAttributes(attrs); - ParseExternalDeclaration(attrs); + + unsigned NestedModules = 0; + while (true) { + switch (Tok.getKind()) { + case tok::annot_module_begin: + ++NestedModules; + ParseTopLevelDecl(); + continue; + + case tok::annot_module_end: + if (!NestedModules) + break; + --NestedModules; + ParseTopLevelDecl(); + continue; + + case tok::annot_module_include: + ParseTopLevelDecl(); + continue; + + case tok::eof: + break; + + case tok::r_brace: + if (!NestedModules) + break; + // Fall through. + default: + ParsedAttributesWithRange attrs(AttrFactory); + MaybeParseCXX11Attributes(attrs); + MaybeParseMicrosoftAttributes(attrs); + ParseExternalDeclaration(attrs); + continue; + } + + break; } T.consumeClose(); - return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec, - T.getCloseLocation()); + return LinkageSpec ? Actions.ActOnFinishLinkageSpecification( + getCurScope(), LinkageSpec, T.getCloseLocation()) + : nullptr; } /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or @@ -346,7 +375,7 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteUsing(getCurScope()); cutOffParsing(); - return 0; + return nullptr; } // 'using namespace' means this is a using-directive. @@ -392,14 +421,14 @@ Decl *Parser::ParseUsingDirective(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteUsingDirective(getCurScope()); cutOffParsing(); - return 0; + return nullptr; } CXXScopeSpec SS; // Parse (optional) nested-name-specifier. ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); - IdentifierInfo *NamespcName = 0; + IdentifierInfo *NamespcName = nullptr; SourceLocation IdentLoc = SourceLocation(); // Parse namespace-name. @@ -408,7 +437,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context, // If there was invalid namespace name, skip to end of decl, and eat ';'. SkipUntil(tok::semi); // FIXME: Are there cases, when we would like to call ActOnUsingDirective? - return 0; + return nullptr; } // Parse identifier. @@ -424,10 +453,10 @@ Decl *Parser::ParseUsingDirective(unsigned Context, // Eat ';'. DeclEnd = Tok.getLocation(); - ExpectAndConsume(tok::semi, - GNUAttr ? diag::err_expected_semi_after_attribute_list - : diag::err_expected_semi_after_namespace_name, - "", tok::semi); + if (ExpectAndConsume(tok::semi, + GNUAttr ? diag::err_expected_semi_after_attribute_list + : diag::err_expected_semi_after_namespace_name)) + SkipUntil(tok::semi); return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS, IdentLoc, NamespcName, attrs.getList()); @@ -461,21 +490,20 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. - if (Tok.is(tok::kw_typename)) { - TypenameLoc = ConsumeToken(); + if (TryConsumeToken(tok::kw_typename, TypenameLoc)) HasTypenameKeyword = true; - } // Parse nested-name-specifier. - IdentifierInfo *LastII = 0; + IdentifierInfo *LastII = nullptr; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false, - /*MayBePseudoDtor=*/0, /*IsTypename=*/false, + /*MayBePseudoDtor=*/nullptr, + /*IsTypename=*/false, /*LastII=*/&LastII); // Check nested-name specifier. if (SS.isInvalid()) { SkipUntil(tok::semi); - return 0; + return nullptr; } SourceLocation TemplateKWLoc; @@ -504,7 +532,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, /*AllowConstructorName=*/ true, ParsedType(), TemplateKWLoc, Name)) { SkipUntil(tok::semi); - return 0; + return nullptr; } ParsedAttributesWithRange Attrs(AttrFactory); @@ -551,7 +579,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Diag(Range.getBegin(), diag::err_alias_declaration_specialization) << SpecKind << Range; SkipUntil(tok::semi); - return 0; + return nullptr; } // Name must be an identifier. @@ -559,7 +587,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier); // No removal fixit: can't recover from this. SkipUntil(tok::semi); - return 0; + return nullptr; } else if (HasTypenameKeyword) Diag(TypenameLoc, diag::err_alias_declaration_not_identifier) << FixItHint::CreateRemoval(SourceRange(TypenameLoc, @@ -568,7 +596,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) << FixItHint::CreateRemoval(SS.getRange()); - TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? + TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ? Declarator::AliasTemplateContext : Declarator::AliasDeclContext, AS, OwnedType, &Attrs); @@ -584,10 +612,11 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // Eat ';'. DeclEnd = Tok.getLocation(); - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - !Attrs.empty() ? "attributes list" : - IsAliasDecl ? "alias declaration" : "using declaration", - tok::semi); + if (ExpectAndConsume(tok::semi, diag::err_expected_after, + !Attrs.empty() ? "attributes list" + : IsAliasDecl ? "alias declaration" + : "using declaration")) + SkipUntil(tok::semi); // Diagnose an attempt to declare a templated using-declaration. // In C++11, alias-declarations can be templates: @@ -600,7 +629,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // Unfortunately, we have to bail out instead of recovering by // ignoring the parameters, just in case the nested name specifier // depends on the parameters. - return 0; + return nullptr; } // "typename" keyword is allowed for identifiers only, @@ -615,7 +644,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, if (IsAliasDecl) { TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; MultiTemplateParamsArg TemplateParamsArg( - TemplateParams ? TemplateParams->data() : 0, + TemplateParams ? TemplateParams->data() : nullptr, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, UsingLoc, Name, Attrs.getList(), @@ -649,31 +678,43 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { - Diag(Tok, diag::err_expected_lparen); + Diag(Tok, diag::err_expected) << tok::l_paren; SkipMalformedDecl(); - return 0; + return nullptr; } ExprResult AssertExpr(ParseConstantExpression()); if (AssertExpr.isInvalid()) { SkipMalformedDecl(); - return 0; + return nullptr; } - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi)) - return 0; + ExprResult AssertMessage; + if (Tok.is(tok::r_paren)) { + Diag(Tok, getLangOpts().CPlusPlus1z + ? diag::warn_cxx1y_compat_static_assert_no_message + : diag::ext_static_assert_no_message) + << (getLangOpts().CPlusPlus1z + ? FixItHint() + : FixItHint::CreateInsertion(Tok.getLocation(), ", \"\"")); + } else { + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::semi); + return nullptr; + } - if (!isTokenStringLiteral()) { - Diag(Tok, diag::err_expected_string_literal) - << /*Source='static_assert'*/1; - SkipMalformedDecl(); - return 0; - } + if (!isTokenStringLiteral()) { + Diag(Tok, diag::err_expected_string_literal) + << /*Source='static_assert'*/1; + SkipMalformedDecl(); + return nullptr; + } - ExprResult AssertMessage(ParseStringLiteralExpression()); - if (AssertMessage.isInvalid()) { - SkipMalformedDecl(); - return 0; + AssertMessage = ParseStringLiteralExpression(); + if (AssertMessage.isInvalid()) { + SkipMalformedDecl(); + return nullptr; + } } T.consumeClose(); @@ -682,8 +723,8 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert); return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, - AssertExpr.take(), - AssertMessage.take(), + AssertExpr.get(), + AssertMessage.get(), T.getCloseLocation()); } @@ -738,7 +779,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // C++11 [dcl.type.simple]p4: // The operand of the decltype specifier is an unevaluated operand. EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, - 0, /*IsDecltype=*/true); + nullptr,/*IsDecltype=*/true); Result = ParseExpression(); if (Result.isInvalid()) { DS.SetTypeSpecError(); @@ -758,7 +799,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { return EndLoc; } - Result = Actions.ActOnDecltypeExpression(Result.take()); + Result = Actions.ActOnDecltypeExpression(Result.get()); } // Match the ')' @@ -779,14 +820,15 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { } assert(!Result.isInvalid()); - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); // Check for duplicate type specifiers (e.g. "int decltype(a)"). if (Result.get() ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec, - DiagID, Result.release()) + DiagID, Result.get(), Policy) : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, PrevSpec, - DiagID)) { + DiagID, Policy)) { Diag(StartLoc, DiagID) << PrevSpec; DS.SetTypeSpecError(); } @@ -834,10 +876,11 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { if (T.getCloseLocation().isInvalid()) return; - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec, - DiagID, Result.release())) + DiagID, Result.get(), + Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; DS.setTypeofParensRange(T.getRange()); } @@ -963,7 +1006,7 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, } // We have an identifier; check whether it is actually a type. - IdentifierInfo *CorrectedII = 0; + IdentifierInfo *CorrectedII = nullptr; ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, false, ParsedType(), /*IsCtorOrDtorName=*/false, @@ -983,9 +1026,10 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, DS.SetRangeEnd(EndLocation); DS.getTypeSpecScope() = SS; - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; - DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type); + DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type, + Actions.getASTContext().getPrintingPolicy()); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); @@ -997,8 +1041,8 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { Tok.is(tok::kw___virtual_inheritance)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0, - AttributeList::AS_GNU); + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + AttributeList::AS_Keyword); } } @@ -1021,6 +1065,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::l_paren: // struct foo {...} ( x); case tok::comma: // __builtin_offsetof(struct foo{...} , case tok::kw_operator: // struct foo operator ++() {...} + case tok::kw___declspec: // struct foo {...} __declspec(...) return true; case tok::colon: return CouldBeBitfield; // enum E { ... } : 2; @@ -1179,51 +1224,38 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // C++11 attributes SourceLocation AttrFixitLoc = Tok.getLocation(); - if (TagType == DeclSpec::TST_struct && - !Tok.is(tok::identifier) && - Tok.getIdentifierInfo() && - (Tok.is(tok::kw___is_arithmetic) || - Tok.is(tok::kw___is_convertible) || - Tok.is(tok::kw___is_empty) || - Tok.is(tok::kw___is_floating_point) || - Tok.is(tok::kw___is_function) || - Tok.is(tok::kw___is_fundamental) || - Tok.is(tok::kw___is_integral) || - Tok.is(tok::kw___is_member_function_pointer) || - Tok.is(tok::kw___is_member_pointer) || - Tok.is(tok::kw___is_pod) || - Tok.is(tok::kw___is_pointer) || - Tok.is(tok::kw___is_same) || - Tok.is(tok::kw___is_scalar) || - Tok.is(tok::kw___is_signed) || - Tok.is(tok::kw___is_unsigned) || - Tok.is(tok::kw___is_void))) - // 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 - // allow libstdc++ 4.2 and libc++ to work properly. - TryKeywordIdentFallback(true); + // GNU libstdc++ and libc++ use certain intrinsic names as the + // name of struct templates, but some are keywords in GCC >= 4.3 + // MSVC and Clang. For compatibility, convert the token to an identifier + // and issue a warning diagnostic. + if (TagType == DeclSpec::TST_struct && !Tok.is(tok::identifier) && + !Tok.isAnnotation()) { + const IdentifierInfo *II = Tok.getIdentifierInfo(); + // We rarely end up here so the following check is efficient. + if (II && II->getName().startswith("__is_")) + TryKeywordIdentFallback(true); + } // Parse the (optional) nested-name-specifier. CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLangOpts().CPlusPlus) { - // "FOO : BAR" is not a potential typo for "FOO::BAR". + // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it + // is a base-specifier-list. ColonProtectionRAIIObject X(*this); if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) DS.SetTypeSpecError(); if (SS.isSet()) if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; } TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; // Parse the (optional) class name or simple-template-id. - IdentifierInfo *Name = 0; + IdentifierInfo *Name = nullptr; SourceLocation NameLoc; - TemplateIdAnnotation *TemplateId = 0; + TemplateIdAnnotation *TemplateId = nullptr; if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); @@ -1243,13 +1275,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } Diag(NameLoc, diag::err_explicit_spec_non_template) - << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) - << (TagType == DeclSpec::TST_class? 0 - : TagType == DeclSpec::TST_struct? 1 - : TagType == DeclSpec::TST_union? 2 - : 3) - << Name - << SourceRange(LAngleLoc, RAngleLoc); + << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + << TagTokKind << Name << SourceRange(LAngleLoc, RAngleLoc); // Strip off the last template parameter list if it was empty, since // we've removed its template argument list. @@ -1257,14 +1284,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TemplateParams && TemplateParams->size() > 1) { TemplateParams->pop_back(); } else { - TemplateParams = 0; + TemplateParams = nullptr; const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind = ParsedTemplateInfo::NonTemplate; } } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { // Pretend this is just a forward declaration. - TemplateParams = 0; + TemplateParams = nullptr; const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind = ParsedTemplateInfo::NonTemplate; const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc @@ -1286,6 +1313,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (SS.isNotEmpty()) Range.setBegin(SS.getBeginLoc()); + // FIXME: Name may be null here. Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template) << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range; @@ -1318,11 +1346,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // new struct s; // or // &T::operator struct s; - // For these, DSC is DSC_type_specifier. + // For these, DSC is DSC_type_specifier or DSC_alias_declaration. // If there are attributes after class name, parse them. MaybeParseCXX11Attributes(Attributes); + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); Sema::TagUseKind TUK; if (DSC == DSC_trailing) TUK = Sema::TUK_Reference; @@ -1375,14 +1404,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TUK = Sema::TUK_Reference; PA.Revert(); - } else if (DSC != DSC_type_specifier && + } else if (!isTypeSpecifier(DSC) && (Tok.is(tok::semi) || (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; if (Tok.isNot(tok::semi)) { + const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); // A semicolon was missing after this declaration. Diagnose and recover. - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - DeclSpec::getSpecifierName(TagType)); + ExpectAndConsume(tok::semi, diag::err_expected_after, + DeclSpec::getSpecifierName(TagType, PPol)); PP.EnterToken(Tok); Tok.setKind(tok::semi); } @@ -1424,7 +1454,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (DS.getTypeSpecType() != DeclSpec::TST_error) { // We have a declaration or reference to an anonymous class. Diag(StartLoc, diag::err_anon_type_definition) - << DeclSpec::getSpecifierName(TagType); + << DeclSpec::getSpecifierName(TagType, Policy); } // If we are parsing a definition and stop at a base-clause, continue on @@ -1503,7 +1533,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TUK == Sema::TUK_Friend) { Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation); - TemplateParams = 0; + TemplateParams = nullptr; } else { SourceLocation LAngleLoc = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); @@ -1516,25 +1546,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // "template<>", so that we treat this construct as a class // template specialization. FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0, - LAngleLoc)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr, + 0, LAngleLoc)); TemplateParams = &FakedParamLists; } } // Build the class template specialization. - TagOrTempResult - = Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK, - StartLoc, DS.getModulePrivateSpecLoc(), SS, - TemplateId->Template, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - attrs.getList(), - MultiTemplateParamsArg( - TemplateParams? &(*TemplateParams)[0] : 0, - TemplateParams? TemplateParams->size() : 0)); + TagOrTempResult = Actions.ActOnClassTemplateSpecialization( + getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), + *TemplateId, attrs.getList(), + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] + : nullptr, + TemplateParams ? TemplateParams->size() : 0)); } } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Sema::TUK_Declaration) { @@ -1560,7 +1584,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TagType, StartLoc, SS, Name, NameLoc, attrs.getList(), MultiTemplateParamsArg( - TemplateParams? &(*TemplateParams)[0] : 0, + TemplateParams? &(*TemplateParams)[0] + : nullptr, TemplateParams? TemplateParams->size() : 0)); } else { if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) @@ -1572,7 +1597,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // recover by ignoring the 'template' keyword. Diag(Tok, diag::err_template_defn_explicit_instantiation) << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); - TemplateParams = 0; + TemplateParams = nullptr; } bool IsDependent = false; @@ -1591,7 +1616,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, SourceLocation(), false, - clang::TypeResult()); + clang::TypeResult(), + DSC == DSC_type_specifier); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -1614,17 +1640,18 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); } - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; bool Result; if (!TypeResult.isInvalid()) { Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, - PrevSpec, DiagID, TypeResult.get()); + PrevSpec, DiagID, TypeResult.get(), Policy); } else if (!TagOrTempResult.isInvalid()) { Result = DS.SetTypeSpecType(TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, - PrevSpec, DiagID, TagOrTempResult.get(), Owned); + PrevSpec, DiagID, TagOrTempResult.get(), Owned, + Policy); } else { DS.SetTypeSpecError(); return; @@ -1645,8 +1672,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TUK == Sema::TUK_Definition && (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { if (Tok.isNot(tok::semi)) { - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - DeclSpec::getSpecifierName(TagType)); + const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); + ExpectAndConsume(tok::semi, diag::err_expected_after, + DeclSpec::getSpecifierName(TagType, PPol)); // Push this token back into the preprocessor and change our current token // to ';' so that the rest of the code recovers as though there were an // ';' after the definition. @@ -1684,10 +1712,8 @@ void Parser::ParseBaseClause(Decl *ClassDecl) { // If the next token is a comma, consume it and keep reading // base-specifiers. - if (Tok.isNot(tok::comma)) break; - - // Consume the comma. - ConsumeToken(); + if (!TryConsumeToken(tok::comma)) + break; } // Attach the base specifiers @@ -1713,10 +1739,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { MaybeParseCXX11Attributes(Attributes); // Parse the 'virtual' keyword. - if (Tok.is(tok::kw_virtual)) { - ConsumeToken(); + if (TryConsumeToken(tok::kw_virtual)) IsVirtual = true; - } CheckMisplacedCXX11Attribute(Attributes, StartLoc); @@ -1753,9 +1777,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { // actually part of the base-specifier-list grammar productions, but we // parse it here for convenience. SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); - + TryConsumeToken(tok::ellipsis, EllipsisLoc); + // Find the complete source range for the base-specifier. SourceRange Range(StartLoc, EndLocation); @@ -1789,12 +1812,12 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, Decl *ThisDecl) { // We just declared a member function. If this member function // has any default arguments, we'll need to parse them later. - LateParsedMethodDeclaration *LateMethod = 0; + LateParsedMethodDeclaration *LateMethod = nullptr; DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo(); - for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) { - if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) { + for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) { + if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) { if (!LateMethod) { // Push this method onto the stack of late-parsed method // declarations. @@ -1804,17 +1827,16 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, // Add all of the parameters prior to this one (they don't // have default arguments). - LateMethod->DefaultArgs.reserve(FTI.NumArgs); + LateMethod->DefaultArgs.reserve(FTI.NumParams); for (unsigned I = 0; I < ParamIdx; ++I) LateMethod->DefaultArgs.push_back( - LateParsedDefaultArgument(FTI.ArgInfo[I].Param)); + LateParsedDefaultArgument(FTI.Params[I].Param)); } // Add this parameter to the list of parameters (it may or may // not have a default argument). - LateMethod->DefaultArgs.push_back( - LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param, - FTI.ArgInfo[ParamIdx].DefaultArgTokens)); + LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument( + FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens)); } } } @@ -1826,29 +1848,27 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, /// override /// final VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const { - if (!getLangOpts().CPlusPlus) + if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier)) return VirtSpecifiers::VS_None; - if (Tok.is(tok::identifier)) { - IdentifierInfo *II = Tok.getIdentifierInfo(); + IdentifierInfo *II = Tok.getIdentifierInfo(); - // Initialize the contextual keywords. - if (!Ident_final) { - Ident_final = &PP.getIdentifierTable().get("final"); - if (getLangOpts().MicrosoftExt) - Ident_sealed = &PP.getIdentifierTable().get("sealed"); - Ident_override = &PP.getIdentifierTable().get("override"); - } + // Initialize the contextual keywords. + if (!Ident_final) { + Ident_final = &PP.getIdentifierTable().get("final"); + if (getLangOpts().MicrosoftExt) + Ident_sealed = &PP.getIdentifierTable().get("sealed"); + Ident_override = &PP.getIdentifierTable().get("override"); + } - if (II == Ident_override) - return VirtSpecifiers::VS_Override; + if (II == Ident_override) + return VirtSpecifiers::VS_Override; - if (II == Ident_sealed) - return VirtSpecifiers::VS_Sealed; + if (II == Ident_sealed) + return VirtSpecifiers::VS_Sealed; - if (II == Ident_final) - return VirtSpecifiers::VS_Final; - } + if (II == Ident_final) + return VirtSpecifiers::VS_Final; return VirtSpecifiers::VS_None; } @@ -1867,7 +1887,7 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, // C++ [class.mem]p8: // A virt-specifier-seq shall contain at most one of each virt-specifier. - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec)) Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier) << PrevSpec @@ -1891,24 +1911,52 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, } /// isCXX11FinalKeyword - Determine whether the next token is a C++11 -/// contextual 'final' keyword. +/// 'final' or Microsoft 'sealed' contextual keyword. bool Parser::isCXX11FinalKeyword() const { - if (!getLangOpts().CPlusPlus) - return false; + VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); + return Specifier == VirtSpecifiers::VS_Final || + Specifier == VirtSpecifiers::VS_Sealed; +} - if (!Tok.is(tok::identifier)) - return false; +/// \brief Parse a C++ member-declarator up to, but not including, the optional +/// brace-or-equal-initializer or pure-specifier. +void Parser::ParseCXXMemberDeclaratorBeforeInitializer( + Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize, + LateParsedAttrList &LateParsedAttrs) { + // member-declarator: + // declarator pure-specifier[opt] + // declarator brace-or-equal-initializer[opt] + // identifier[opt] ':' constant-expression + if (Tok.isNot(tok::colon)) + ParseDeclarator(DeclaratorInfo); - // Initialize the contextual keywords. - if (!Ident_final) { - Ident_final = &PP.getIdentifierTable().get("final"); - if (getLangOpts().MicrosoftExt) - Ident_sealed = &PP.getIdentifierTable().get("sealed"); - Ident_override = &PP.getIdentifierTable().get("override"); + if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) { + BitfieldSize = ParseConstantExpression(); + if (BitfieldSize.isInvalid()) + SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + } else + ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + + // If a simple-asm-expr is present, parse it. + if (Tok.is(tok::kw_asm)) { + SourceLocation Loc; + ExprResult AsmLabel(ParseSimpleAsm(&Loc)); + if (AsmLabel.isInvalid()) + SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + + DeclaratorInfo.setAsmLabel(AsmLabel.get()); + DeclaratorInfo.SetRangeEnd(Loc); } - return Tok.getIdentifierInfo() == Ident_final || - Tok.getIdentifierInfo() == Ident_sealed; + // If attributes exist after the declarator, but before an '{', parse them. + MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); + + // For compatibility with code written to older Clang, also accept a + // virt-specifier *after* the GNU attributes. + // FIXME: If we saw any attributes that are known to GCC followed by a + // virt-specifier, issue a GCC-compat warning. + if (BitfieldSize.isUnset() && VS.isUnset()) + ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); } /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. @@ -1962,6 +2010,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; } + // Turn on colon protection early, while parsing declspec, although there is + // nothing to protect there. It prevents from false errors if error recovery + // incorrectly determines where the declspec ends, as in the example: + // struct A { enum class B { C }; }; + // const int C = 4; + // struct D { A::B : C; }; + ColonProtectionRAIIObject X(*this); + // Access declarations. bool MalformedTypeSpec = false; if (!TemplateInfo.Kind && @@ -1993,17 +2049,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } // TODO: recover from mistakenly-qualified operator declarations. - if (ExpectAndConsume(tok::semi, - diag::err_expected_semi_after, - "access declaration", - tok::semi)) + if (ExpectAndConsume(tok::semi, diag::err_expected_after, + "access declaration")) { + SkipUntil(tok::semi); return; + } Actions.ActOnUsingDeclaration(getCurScope(), AS, /* HasUsingKeyword */ false, SourceLocation(), SS, Name, - /* AttrList */ 0, + /* AttrList */ nullptr, /* HasTypenameKeyword */ false, SourceLocation()); return; @@ -2036,10 +2092,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, TemplateInfo, TemplateDiags); } - // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it - // is a bitfield. - ColonProtectionRAIIObject X(*this); - ParsedAttributesWithRange attrs(AttrFactory); ParsedAttributesWithRange FnAttrs(AttrFactory); // Optional C++11 attribute-specifier @@ -2078,9 +2130,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DS.takeAttributesFrom(attrs); if (MalformedTypeSpec) DS.SetTypeSpecError(); + ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class, &CommonLateParsedAttrs); + // Turn off colon protection that was set for declspec. + X.restore(); + // If we had a free-standing type definition with a missing semicolon, we // may get this far before the problem becomes obvious. if (DS.hasTagDefinition() && @@ -2090,12 +2146,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; MultiTemplateParamsArg TemplateParams( - TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0, + TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() + : nullptr, TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0); - if (Tok.is(tok::semi)) { - ConsumeToken(); - + if (TryConsumeToken(tok::semi)) { if (DS.isFriendSpecified()) ProhibitAttributes(FnAttrs); @@ -2114,30 +2169,30 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation EqualLoc; bool HasInitializer = false; ExprResult Init; - if (Tok.isNot(tok::colon)) { - // Don't parse FOO:BAR as if it were a typo for FOO::BAR. - ColonProtectionRAIIObject X(*this); - // Parse the first declarator. - ParseDeclarator(DeclaratorInfo); - // Error parsing the declarator? - if (!DeclaratorInfo.hasName()) { - // If so, skip until the semi-colon or a }. - SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); - if (Tok.is(tok::semi)) - ConsumeToken(); - return; - } + SmallVector<Decl *, 8> DeclsInGroup; + ExprResult BitfieldSize; + bool ExpectSemi = true; - ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + // Parse the first declarator. + ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, + LateParsedAttrs); - // If attributes exist after the declarator, but before an '{', parse them. - MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); + // If this has neither a name nor a bit width, something has gone seriously + // wrong. Skip until the semi-colon or }. + if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) { + // If so, skip until the semi-colon or a }. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + TryConsumeToken(tok::semi); + return; + } - // MSVC permits pure specifier on inline functions declared at class scope. + // Check for a member function definition. + if (BitfieldSize.isUnset()) { + // MSVC permits pure specifier on inline functions defined at class scope. // Hence check for =0 before checking for function definition. if (getLangOpts().MicrosoftExt && Tok.is(tok::equal) && - DeclaratorInfo.isFunctionDeclarator() && + DeclaratorInfo.isFunctionDeclarator() && NextToken().is(tok::numeric_constant)) { EqualLoc = ConsumeToken(); Init = ParseInitializer(); @@ -2183,8 +2238,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::r_brace); // Consume the optional ';' - if (Tok.is(tok::semi)) - ConsumeToken(); + TryConsumeToken(tok::semi); + return; } @@ -2222,40 +2277,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // member-declarator // member-declarator-list ',' member-declarator - SmallVector<Decl *, 8> DeclsInGroup; - ExprResult BitfieldSize; - bool ExpectSemi = true; - while (1) { - // member-declarator: - // declarator pure-specifier[opt] - // declarator brace-or-equal-initializer[opt] - // identifier[opt] ':' constant-expression - if (Tok.is(tok::colon)) { - ConsumeToken(); - BitfieldSize = ParseConstantExpression(); - if (BitfieldSize.isInvalid()) - SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - } - - // If a simple-asm-expr is present, parse it. - if (Tok.is(tok::kw_asm)) { - SourceLocation Loc; - ExprResult AsmLabel(ParseSimpleAsm(&Loc)); - if (AsmLabel.isInvalid()) - SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - - DeclaratorInfo.setAsmLabel(AsmLabel.release()); - DeclaratorInfo.SetRangeEnd(Loc); - } - - // If attributes exist after the declarator, parse them. - 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__. - ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); - InClassInitStyle HasInClassInit = ICIS_NoInit; if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) { if (BitfieldSize.get()) { @@ -2274,35 +2296,31 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // this call will *not* return the created decl; It will return null. // See Sema::ActOnCXXMemberDeclarator for details. - NamedDecl *ThisDecl = 0; + NamedDecl *ThisDecl = nullptr; if (DS.isFriendSpecified()) { - // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains + // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains // to a friend declaration, that declaration shall be a definition. // - // Diagnose attributes appear after friend member function declarator: - // foo [[]] (); + // Diagnose attributes that appear in a friend member function declarator: + // friend int foo [[]] (); SmallVector<SourceRange, 4> Ranges; DeclaratorInfo.getCXX11AttributeRanges(Ranges); - if (!Ranges.empty()) { - for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), - E = Ranges.end(); I != E; ++I) { - Diag((*I).getBegin(), diag::err_attributes_not_allowed) - << *I; - } - } + for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), + E = Ranges.end(); I != E; ++I) + Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I; - // TODO: handle initializers, bitfields, 'delete' + // TODO: handle initializers, VS, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); } else { ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, DeclaratorInfo, TemplateParams, - BitfieldSize.release(), + BitfieldSize.get(), VS, HasInClassInit); if (VarTemplateDecl *VT = - ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : 0) + ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr) // Re-direct this decl to refer to the templated decl so that we can // initialize it. ThisDecl = VT->getTemplatedDecl(); @@ -2372,12 +2390,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // 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)) + SourceLocation CommaLoc; + if (!TryConsumeToken(tok::comma, CommaLoc)) break; - // Consume the comma. - SourceLocation CommaLoc = ConsumeToken(); - if (Tok.isAtStartOfLine() && !MightBeDeclarator(Declarator::MemberContext)) { // This comma was followed by a line-break and something which can't be @@ -2397,11 +2413,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, HasInitializer = false; DeclaratorInfo.setCommaLoc(CommaLoc); - // Attributes are only allowed on the second declarator. + // GNU attributes are allowed before the second and subsequent declarator. MaybeParseGNUAttributes(DeclaratorInfo); - if (Tok.isNot(tok::colon)) - ParseDeclarator(DeclaratorInfo); + ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, + LateParsedAttrs); } if (ExpectSemi && @@ -2409,7 +2425,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Skip to end of block or statement. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); // If we stopped at a ';', eat it. - if (Tok.is(tok::semi)) ConsumeToken(); + TryConsumeToken(tok::semi); return; } @@ -2446,8 +2462,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, EnterExpressionEvaluationContext Context(Actions, Sema::PotentiallyEvaluated, D); - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); + if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::kw_delete)) { // In principle, an initializer of '= delete p;' is legal, but it will // never type-check. It's better to diagnose it as an ill-formed expression @@ -2456,13 +2471,13 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, // a top-level comma always ends the initializer expression. const Token &Next = NextToken(); if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) || - Next.is(tok::eof)) { + Next.is(tok::eof)) { if (IsFunction) Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) << 1 /* delete */; else Diag(ConsumeToken(), diag::err_deleted_non_function); - return ExprResult(); + return ExprError(); } } else if (Tok.is(tok::kw_default)) { if (IsFunction) @@ -2470,7 +2485,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, << 0 /* default */; else Diag(ConsumeToken(), diag::err_default_special_members); - return ExprResult(); + return ExprError(); } } @@ -2510,7 +2525,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, << /*ErrorType=*/6 << (isa<NamedDecl>(TagDecl) ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString() - : "<anonymous>"); + : "(anonymous)"); } break; } @@ -2601,7 +2616,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl) { // While we still have something to read, read the member-declarations. - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // Each iteration of this loop reads one member-declaration. if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) || @@ -2636,6 +2651,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) { + HandlePragmaMSPointersToMembers(); + continue; + } + + if (Tok.is(tok::annot_pragma_ms_pragma)) { + HandlePragmaMSPragma(); + continue; + } + // If we see a namespace here, a close brace was missing somewhere. if (Tok.is(tok::kw_namespace)) { DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); @@ -2653,18 +2678,14 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, MaybeParseGNUAttributes(AccessAttrs); SourceLocation EndLoc; - if (Tok.is(tok::colon)) { - EndLoc = Tok.getLocation(); - ConsumeToken(); - } else if (Tok.is(tok::semi)) { - EndLoc = Tok.getLocation(); - ConsumeToken(); - Diag(EndLoc, diag::err_expected_colon) - << FixItHint::CreateReplacement(EndLoc, ":"); + if (TryConsumeToken(tok::colon, EndLoc)) { + } else if (TryConsumeToken(tok::semi, EndLoc)) { + Diag(EndLoc, diag::err_expected) + << tok::colon << FixItHint::CreateReplacement(EndLoc, ":"); } else { EndLoc = ASLoc.getLocWithOffset(TokLength); - Diag(EndLoc, diag::err_expected_colon) - << FixItHint::CreateInsertion(EndLoc, ":"); + Diag(EndLoc, diag::err_expected) + << tok::colon << FixItHint::CreateInsertion(EndLoc, ":"); } // The Microsoft extension __interface does not permit non-public @@ -2810,7 +2831,8 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { << FixItHint::CreateInsertion(Loc, ", "); } else { // Skip over garbage, until we get to '{'. Don't eat the '{'. - Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma); + Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace + << tok::comma; SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); break; } @@ -2854,7 +2876,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { return true; } - IdentifierInfo *II = 0; + IdentifierInfo *II = nullptr; DeclSpec DS(AttrFactory); SourceLocation IdLoc = Tok.getLocation(); if (Tok.is(tok::annot_decltype)) { @@ -2878,12 +2900,11 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { return true; SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); + TryConsumeToken(tok::ellipsis, EllipsisLoc); return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy, DS, IdLoc, - InitList.take(), EllipsisLoc); + InitList.get(), EllipsisLoc); } else if(Tok.is(tok::l_paren)) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -2899,8 +2920,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { T.consumeClose(); SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); + TryConsumeToken(tok::ellipsis, EllipsisLoc); return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy, DS, IdLoc, @@ -2908,9 +2928,10 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { T.getCloseLocation(), EllipsisLoc); } - Diag(Tok, getLangOpts().CPlusPlus11 ? diag::err_expected_lparen_or_lbrace - : diag::err_expected_lparen); - return true; + if (getLangOpts().CPlusPlus11) + return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace; + else + return Diag(Tok, diag::err_expected) << tok::l_paren; } /// \brief Parse a C++ exception-specification if present (C++0x [except.spec]). @@ -3054,10 +3075,8 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( Exceptions.push_back(Res.get()); Ranges.push_back(Range); } - - if (Tok.is(tok::comma)) - ConsumeToken(); - else + + if (!TryConsumeToken(tok::comma)) break; } @@ -3153,7 +3172,7 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { Loc = ConsumeToken(); return II; } - return 0; + return nullptr; case tok::ampamp: // 'and' case tok::pipe: // 'bitor' @@ -3174,7 +3193,7 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { Loc = ConsumeToken(); return &PP.getIdentifierTable().get(Spelling); } - return 0; + return nullptr; } } @@ -3183,6 +3202,7 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, switch (AttributeList::getKind(AttrName, ScopeName, AttributeList::AS_CXX11)) { case AttributeList::AT_CarriesDependency: + case AttributeList::AT_Deprecated: case AttributeList::AT_FallThrough: case AttributeList::AT_CXX11NoReturn: { return true; @@ -3193,8 +3213,75 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, } } -/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently -/// only parses standard attributes. +/// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause. +/// +/// [C++11] attribute-argument-clause: +/// '(' balanced-token-seq ')' +/// +/// [C++11] balanced-token-seq: +/// balanced-token +/// balanced-token-seq balanced-token +/// +/// [C++11] balanced-token: +/// '(' balanced-token-seq ')' +/// '[' balanced-token-seq ']' +/// '{' balanced-token-seq '}' +/// any token but '(', ')', '[', ']', '{', or '}' +bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + SourceLocation *EndLoc, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc) { + assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); + SourceLocation LParenLoc = Tok.getLocation(); + + // If the attribute isn't known, we will not attempt to parse any + // arguments. + if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName, + getTargetInfo().getTriple(), getLangOpts())) { + // Eat the left paren, then skip to the ending right paren. + ConsumeParen(); + SkipUntil(tok::r_paren); + return false; + } + + if (ScopeName && ScopeName->getName() == "gnu") + // GNU-scoped attributes have some special cases to handle GNU-specific + // behaviors. + ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, + ScopeLoc, AttributeList::AS_CXX11, nullptr); + else { + unsigned NumArgs = + ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, AttributeList::AS_CXX11); + + const AttributeList *Attr = Attrs.getList(); + if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + // If the attribute is a standard or built-in attribute and we are + // parsing an argument list, we need to determine whether this attribute + // was allowed to have an argument list (such as [[deprecated]]), and how + // many arguments were parsed (so we can diagnose on [[deprecated()]]). + if (Attr->getMaxArgs() && !NumArgs) { + // The attribute was allowed to have arguments, but none were provided + // even though the attribute parsed successfully. This is an error. + // FIXME: This is a good place for a fixit which removes the parens. + Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; + return false; + } else if (!Attr->getMaxArgs()) { + // The attribute parsed successfully, but was not allowed to have any + // arguments. It doesn't matter whether any were provided -- the + // presence of the argument list (even if empty) is diagnosed. + Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) + << AttrName; + return false; + } + } + } + return true; +} + +/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. /// /// [C++11] attribute-specifier: /// '[' '[' attribute-list ']' ']' @@ -3218,19 +3305,6 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, /// /// [C++11] attribute-namespace: /// identifier -/// -/// [C++11] attribute-argument-clause: -/// '(' balanced-token-seq ')' -/// -/// [C++11] balanced-token-seq: -/// balanced-token -/// balanced-token-seq balanced-token -/// -/// [C++11] balanced-token: -/// '(' balanced-token-seq ')' -/// '[' balanced-token-seq ']' -/// '{' balanced-token-seq '}' -/// any token but '(', ')', '[', ']', '{', or '}' void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, SourceLocation *endLoc) { if (Tok.is(tok::kw_alignas)) { @@ -3251,13 +3325,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, while (Tok.isNot(tok::r_square)) { // attribute not present - if (Tok.is(tok::comma)) { - ConsumeToken(); + if (TryConsumeToken(tok::comma)) continue; - } SourceLocation ScopeLoc, AttrLoc; - IdentifierInfo *ScopeName = 0, *AttrName = 0; + IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr; AttrName = TryParseCXX11AttributeIdentifier(AttrLoc); if (!AttrName) @@ -3265,64 +3337,47 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, break; // scoped attribute - if (Tok.is(tok::coloncolon)) { - ConsumeToken(); - + if (TryConsumeToken(tok::coloncolon)) { ScopeName = AttrName; ScopeLoc = AttrLoc; AttrName = TryParseCXX11AttributeIdentifier(AttrLoc); if (!AttrName) { - Diag(Tok.getLocation(), diag::err_expected_ident); + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch); continue; } } - bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName); + bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName); bool AttrParsed = false; if (StandardAttr && !SeenAttrs.insert(std::make_pair(AttrName, AttrLoc)).second) Diag(AttrLoc, diag::err_cxx11_attribute_repeated) - << AttrName << SourceRange(SeenAttrs[AttrName]); + << AttrName << SourceRange(SeenAttrs[AttrName]); // Parse attribute arguments - if (Tok.is(tok::l_paren)) { - if (ScopeName && ScopeName->getName() == "gnu") { - ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc, - ScopeName, ScopeLoc, AttributeList::AS_CXX11); - AttrParsed = true; - } else { - if (StandardAttr) - Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments) - << AttrName->getName(); - - // FIXME: handle other formats of c++11 attribute arguments - ConsumeParen(); - SkipUntil(tok::r_paren); - } - } + if (Tok.is(tok::l_paren)) + AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc, + ScopeName, ScopeLoc); if (!AttrParsed) attrs.addNew(AttrName, SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), - ScopeName, ScopeLoc, 0, 0, AttributeList::AS_CXX11); - - if (Tok.is(tok::ellipsis)) { - ConsumeToken(); + ScopeName, ScopeLoc, nullptr, 0, AttributeList::AS_CXX11); + if (TryConsumeToken(tok::ellipsis)) Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) << AttrName->getName(); - } } - if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare)) + if (ExpectAndConsume(tok::r_square)) SkipUntil(tok::r_square); if (endLoc) *endLoc = Tok.getLocation(); - if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare)) + if (ExpectAndConsume(tok::r_square)) SkipUntil(tok::r_square); } @@ -3346,13 +3401,23 @@ void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs, } void Parser::DiagnoseAndSkipCXX11Attributes() { - if (!isCXX11AttributeSpecifier()) - return; - // Start and end location of an attribute or an attribute list. SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc = SkipCXX11Attributes(); + + if (EndLoc.isValid()) { + SourceRange Range(StartLoc, EndLoc); + Diag(StartLoc, diag::err_attributes_not_allowed) + << Range; + } +} + +SourceLocation Parser::SkipCXX11Attributes() { SourceLocation EndLoc; + if (!isCXX11AttributeSpecifier()) + return EndLoc; + do { if (Tok.is(tok::l_square)) { BalancedDelimiterTracker T(*this, tok::l_square); @@ -3369,11 +3434,7 @@ void Parser::DiagnoseAndSkipCXX11Attributes() { } } while (isCXX11AttributeSpecifier()); - if (EndLoc.isValid()) { - SourceRange Range(StartLoc, EndLoc); - Diag(StartLoc, diag::err_attributes_not_allowed) - << Range; - } + return EndLoc; } /// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr] @@ -3393,7 +3454,7 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, ConsumeBracket(); SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch); if (endLoc) *endLoc = Tok.getLocation(); - ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); + ExpectAndConsume(tok::r_square); } } @@ -3405,7 +3466,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return; } @@ -3424,7 +3485,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, return; } - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); @@ -3446,13 +3507,13 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, if (Tok.is(tok::colon)) Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); else - Diag(Tok, diag::err_expected_colon); + Diag(Tok, diag::err_expected) << tok::colon; ConsumeToken(); continue; } // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS, 0); + ParseCXXClassMemberDeclaration(CurAS, nullptr); } Braces.consumeClose(); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index 45f1b1d..0e4dfb9 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -23,6 +23,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" @@ -147,7 +148,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { if (!LHS.isInvalid()) LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__, - LHS.take()); + LHS.get()); return ParseRHSOfBinaryExpression(LHS, prec::Comma); } @@ -260,19 +261,16 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { TernaryMiddle = ParseExpression(); if (TernaryMiddle.isInvalid()) { LHS = ExprError(); - TernaryMiddle = 0; + TernaryMiddle = nullptr; } } else { // Special case handling of "X ? Y : Z" where Y is empty: // logical-OR-expression '?' ':' conditional-expression [GNU] - TernaryMiddle = 0; + TernaryMiddle = nullptr; Diag(Tok, diag::ext_gnu_conditional_expr); } - if (Tok.is(tok::colon)) { - // Eat the colon. - ColonLoc = ConsumeToken(); - } else { + if (!TryConsumeToken(tok::colon, ColonLoc)) { // 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, @@ -294,10 +292,10 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { } } } - - Diag(Tok, diag::err_expected_colon) - << FixItHint::CreateInsertion(FILoc, FIText); - Diag(OpToken, diag::note_matching) << "?"; + + Diag(Tok, diag::err_expected) + << tok::colon << FixItHint::CreateInsertion(FILoc, FIText); + Diag(OpToken, diag::note_matching) << tok::question; ColonLoc = Tok.getLocation(); } } @@ -394,11 +392,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { Actions.getExprRange(RHS.get()).getEnd())); LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(), - OpToken.getKind(), LHS.take(), RHS.take()); + OpToken.getKind(), LHS.get(), RHS.get()); } else LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc, - LHS.take(), TernaryMiddle.take(), - RHS.take()); + LHS.get(), TernaryMiddle.get(), + RHS.get()); } } } @@ -430,14 +428,15 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { WantTypeSpecifiers = AllowTypes; } - virtual bool ValidateCandidate(const TypoCorrection &candidate) { + bool ValidateCandidate(const TypoCorrection &candidate) override { NamedDecl *ND = candidate.getCorrectionDecl(); if (!ND) return candidate.isKeyword(); if (isa<TypeDecl>(ND)) return WantTypeSpecifiers; - return AllowNonTypes; + return AllowNonTypes && + CorrectionCandidateCallback::ValidateCandidate(candidate); } private: @@ -639,18 +638,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // If this expression is limited to being a unary-expression, the parent can // not start a cast expression. ParenParseOption ParenExprType = - (isUnaryExpression && !getLangOpts().CPlusPlus)? CompoundLiteral : CastExpr; + (isUnaryExpression && !getLangOpts().CPlusPlus) ? CompoundLiteral + : CastExpr; ParsedType CastTy; SourceLocation RParenLoc; - - { - // The inside of the parens don't need to be a colon protected scope, and - // isn't immediately a message send. - ColonProtectionRAIIObject X(*this, false); - - Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/, - isTypeCast == IsTypeCast, CastTy, RParenLoc); - } + Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/, + isTypeCast == IsTypeCast, CastTy, RParenLoc); switch (ParenExprType) { case SimpleExpr: break; // Nothing else to do. @@ -690,7 +683,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); case tok::annot_primary_expr: - assert(Res.get() == 0 && "Stray primary-expression annotation?"); + assert(Res.get() == nullptr && "Stray primary-expression annotation?"); Res = getExprAnnotation(Tok); ConsumeToken(); break; @@ -715,48 +708,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // If this identifier was reverted from a token ID, and the next token // is a parenthesis, this is likely to be a use of a type trait. Check // those tokens. - if (Next.is(tok::l_paren) && - Tok.is(tok::identifier) && - Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) { - IdentifierInfo *II = Tok.getIdentifierInfo(); - // Build up the mapping of revertable type traits, for future use. - if (RevertableTypeTraits.empty()) { -#define RTT_JOIN(X,Y) X##Y -#define REVERTABLE_TYPE_TRAIT(Name) \ - RevertableTypeTraits[PP.getIdentifierInfo(#Name)] \ - = RTT_JOIN(tok::kw_,Name) - - REVERTABLE_TYPE_TRAIT(__is_arithmetic); - REVERTABLE_TYPE_TRAIT(__is_convertible); - REVERTABLE_TYPE_TRAIT(__is_empty); - REVERTABLE_TYPE_TRAIT(__is_floating_point); - REVERTABLE_TYPE_TRAIT(__is_function); - REVERTABLE_TYPE_TRAIT(__is_fundamental); - REVERTABLE_TYPE_TRAIT(__is_integral); - REVERTABLE_TYPE_TRAIT(__is_member_function_pointer); - REVERTABLE_TYPE_TRAIT(__is_member_pointer); - REVERTABLE_TYPE_TRAIT(__is_pod); - REVERTABLE_TYPE_TRAIT(__is_pointer); - REVERTABLE_TYPE_TRAIT(__is_same); - REVERTABLE_TYPE_TRAIT(__is_scalar); - REVERTABLE_TYPE_TRAIT(__is_signed); - REVERTABLE_TYPE_TRAIT(__is_unsigned); - REVERTABLE_TYPE_TRAIT(__is_void); -#undef REVERTABLE_TYPE_TRAIT -#undef RTT_JOIN - } - - // If we find that this is in fact the name of a type trait, - // update the token kind in place and parse again to treat it as - // the appropriate kind of type trait. - llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind>::iterator Known - = RevertableTypeTraits.find(II); - if (Known != RevertableTypeTraits.end()) { - Tok.setKind(Known->second); - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); - } - } + if (Next.is(tok::l_paren) && Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier() && + TryIdentKeywordUpgrade()) + return ParseCastExpression(isUnaryExpression, isAddressOfOperand, + NotCastExpr, isTypeCast); if (Next.is(tok::coloncolon) || (!ColonIsSacred && Next.is(tok::colon)) || @@ -806,8 +762,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, ((Tok.is(tok::identifier) && (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) || Tok.is(tok::code_completion))) { - Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(), - 0); + Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(), + nullptr); break; } @@ -828,19 +784,20 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, DeclSpec DS(AttrFactory); DS.SetRangeStart(ILoc); DS.SetRangeEnd(ILoc); - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; - DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ); + DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ, + Actions.getASTContext().getPrintingPolicy()); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) break; - + Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), - Ty.get(), 0); + Ty.get(), nullptr); break; } } @@ -857,6 +814,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, SourceLocation TemplateKWLoc; CastExpressionIdValidator Validator(isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); + Validator.IsAddressOfOperand = isAddressOfOperand; Name.setIdentifier(&II, ILoc); Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), @@ -873,6 +831,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2] case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU] case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS] + case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS] case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS] case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU] Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); @@ -904,7 +863,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // ++ cast-expression // -- cast-expression SourceLocation SavedLoc = ConsumeToken(); - Res = ParseCastExpression(!getLangOpts().CPlusPlus); + // One special case is implicitly handled here: if the preceding tokens are + // an ambiguous cast expression, such as "(T())++", then we recurse to + // determine whether the '++' is prefix or postfix. + Res = ParseCastExpression(!getLangOpts().CPlusPlus, + /*isAddressOfOperand*/false, NotCastExpr, + NotTypeCast); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return Res; @@ -955,9 +919,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::ampamp: { // unary-expression: '&&' identifier SourceLocation AmpAmpLoc = ConsumeToken(); if (Tok.isNot(tok::identifier)) - return ExprError(Diag(Tok, diag::err_expected_ident)); + return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); - if (getCurScope()->getFnParent() == 0) + if (getCurScope()->getFnParent() == nullptr) return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn)); Diag(AmpAmpLoc, diag::ext_gnu_address_of_label); @@ -992,10 +956,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, DS.SetRangeStart(Tok.getLocation()); DS.SetRangeEnd(Tok.getLastLoc()); - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(), - PrevSpec, DiagID, Type); + PrevSpec, DiagID, Type, + Actions.getASTContext().getPrintingPolicy()); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); @@ -1004,7 +969,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, ConsumeToken(); Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), - Ty.get(), 0); + Ty.get(), nullptr); break; } // Fall through @@ -1028,15 +993,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_void: case tok::kw_typename: case tok::kw_typeof: - case tok::kw___vector: - case tok::kw_image1d_t: - case tok::kw_image1d_array_t: - case tok::kw_image1d_buffer_t: - case tok::kw_image2d_t: - case tok::kw_image2d_array_t: - case tok::kw_image3d_t: - case tok::kw_sampler_t: - case tok::kw_event_t: { + case tok::kw___vector: { if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); return ExprError(); @@ -1164,69 +1121,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (!Result.isInvalid()) Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), - Result.take(), T.getCloseLocation()); + Result.get(), T.getCloseLocation()); return Result; } - case tok::kw___is_abstract: // [GNU] unary-type-trait - case tok::kw___is_class: - case tok::kw___is_empty: - case tok::kw___is_enum: - case tok::kw___is_interface_class: - case tok::kw___is_literal: - case tok::kw___is_arithmetic: - case tok::kw___is_integral: - case tok::kw___is_floating_point: - case tok::kw___is_complete_type: - case tok::kw___is_void: - case tok::kw___is_array: - case tok::kw___is_function: - case tok::kw___is_reference: - case tok::kw___is_lvalue_reference: - case tok::kw___is_rvalue_reference: - case tok::kw___is_fundamental: - case tok::kw___is_object: - case tok::kw___is_scalar: - case tok::kw___is_compound: - case tok::kw___is_pointer: - case tok::kw___is_member_object_pointer: - case tok::kw___is_member_function_pointer: - case tok::kw___is_member_pointer: - case tok::kw___is_const: - case tok::kw___is_volatile: - case tok::kw___is_standard_layout: - case tok::kw___is_signed: - case tok::kw___is_unsigned: - case tok::kw___is_literal_type: - case tok::kw___is_pod: - case tok::kw___is_polymorphic: - case tok::kw___is_trivial: - case tok::kw___is_trivially_copyable: - case tok::kw___is_union: - case tok::kw___is_final: - case tok::kw___is_sealed: - case tok::kw___has_trivial_constructor: - case tok::kw___has_trivial_move_constructor: - case tok::kw___has_trivial_copy: - case tok::kw___has_trivial_assign: - case tok::kw___has_trivial_move_assign: - case tok::kw___has_trivial_destructor: - case tok::kw___has_nothrow_assign: - case tok::kw___has_nothrow_move_assign: - case tok::kw___has_nothrow_copy: - case tok::kw___has_nothrow_constructor: - case tok::kw___has_virtual_destructor: - return ParseUnaryTypeTrait(); - - case tok::kw___builtin_types_compatible_p: - case tok::kw___is_base_of: - case tok::kw___is_same: - case tok::kw___is_convertible: - case tok::kw___is_convertible_to: - case tok::kw___is_trivially_assignable: - return ParseBinaryTypeTrait(); - - case tok::kw___is_trivially_constructible: +#define TYPE_TRAIT(N,Spelling,K) \ + case tok::kw_##Spelling: +#include "clang/Basic/TokenKinds.def" return ParseTypeTrait(); case tok::kw___array_rank: @@ -1358,8 +1259,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { SourceLocation RLoc = Tok.getLocation(); if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) { - LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.take(), Loc, - Idx.take(), RLoc); + LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, + Idx.get(), RLoc); } else LHS = ExprError(); @@ -1373,8 +1274,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // '(' argument-expression-list[opt] ')' tok::TokenKind OpKind = Tok.getKind(); InMessageExpressionRAIIObject InMessage(*this, false); - - Expr *ExecConfig = 0; + + Expr *ExecConfig = nullptr; BalancedDelimiterTracker PT(*this, tok::l_paren); @@ -1387,21 +1288,20 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = ExprError(); } - SourceLocation CloseLoc = Tok.getLocation(); - if (Tok.is(tok::greatergreatergreater)) { - ConsumeToken(); + SourceLocation CloseLoc; + if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) { } else if (LHS.isInvalid()) { SkipUntil(tok::greatergreatergreater, StopAtSemi); } else { // There was an error closing the brackets - Diag(Tok, diag::err_expected_ggg); - Diag(OpenLoc, diag::note_matching) << "<<<"; + Diag(Tok, diag::err_expected) << tok::greatergreatergreater; + Diag(OpenLoc, diag::note_matching) << tok::lesslessless; SkipUntil(tok::greatergreatergreater, StopAtSemi); LHS = ExprError(); } if (!LHS.isInvalid()) { - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, "")) + if (ExpectAndConsume(tok::l_paren)) LHS = ExprError(); else Loc = PrevTokLocation; @@ -1450,7 +1350,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); - LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc, + LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc, ArgExprs, Tok.getLocation(), ExecConfig); PT.consumeClose(); @@ -1469,14 +1369,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { ParsedType ObjectType; bool MayBePseudoDestructor = false; if (getLangOpts().CPlusPlus && !LHS.isInvalid()) { - Expr *Base = LHS.take(); + Expr *Base = LHS.get(); const Type* BaseType = Base->getType().getTypePtrOrNull(); if (BaseType && Tok.is(tok::l_paren) && (BaseType->isFunctionType() || BaseType->isSpecificPlaceholderType(BuiltinType::BoundMember))) { Diag(OpLoc, diag::err_function_is_not_record) - << (OpKind == tok::arrow) << Base->getSourceRange() - << FixItHint::CreateRemoval(OpLoc); + << OpKind << Base->getSourceRange() + << FixItHint::CreateRemoval(OpLoc); return ParsePostfixExpressionSuffix(Base); } @@ -1503,7 +1403,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } if (MayBePseudoDestructor && !LHS.isInvalid()) { - LHS = ParseCXXPseudoDestructor(LHS.take(), OpLoc, OpKind, SS, + LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS, ObjectType); break; } @@ -1537,9 +1437,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = ExprError(); if (!LHS.isInvalid()) - LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc, + LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, OpKind, SS, TemplateKWLoc, Name, - CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : 0, + CurParsedObjCImpl ? CurParsedObjCImpl->Dcl + : nullptr, Tok.is(tok::l_paren)); break; } @@ -1547,7 +1448,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { case tok::minusminus: // postfix-expression: postfix-expression '--' if (!LHS.isInvalid()) { LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(), - Tok.getKind(), LHS.take()); + Tok.getKind(), LHS.get()); } ConsumeToken(); break; @@ -1597,8 +1498,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, // pathenthesis around type name. if (OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) { - bool isAmbiguousTypeId; - if (isTypeIdInParens(isAmbiguousTypeId)) { + if (isTypeIdUnambiguously()) { DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); @@ -1617,7 +1517,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, isCastExpr = false; if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) { - Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo(); + Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo() + << tok::l_paren; return ExprError(); } @@ -1681,7 +1582,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) { SourceLocation EllipsisLoc = ConsumeToken(); SourceLocation LParenLoc, RParenLoc; - IdentifierInfo *Name = 0; + IdentifierInfo *Name = nullptr; SourceLocation NameLoc; if (Tok.is(tok::l_paren)) { BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1759,7 +1660,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), ExprKind, /*isType=*/false, - Operand.release(), + Operand.get(), CastRange); return Operand; } @@ -1789,8 +1690,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { // All of these start with an open paren. if (Tok.isNot(tok::l_paren)) - return ExprError(Diag(Tok, diag::err_expected_lparen_after_id) - << BuiltinII); + return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII + << tok::l_paren); BalancedDelimiterTracker PT(*this, tok::l_paren); PT.consumeOpen(); @@ -1802,20 +1703,22 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { case tok::kw___builtin_va_arg: { ExprResult Expr(ParseAssignmentExpression()); - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); Expr = ExprError(); + } TypeResult Ty = ParseTypeName(); if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_rparen); + Diag(Tok, diag::err_expected) << tok::r_paren; Expr = ExprError(); } if (Expr.isInvalid() || Ty.isInvalid()) Res = ExprError(); else - Res = Actions.ActOnVAArg(StartLoc, Expr.take(), Ty.get(), ConsumeParen()); + Res = Actions.ActOnVAArg(StartLoc, Expr.get(), Ty.get(), ConsumeParen()); break; } case tok::kw___builtin_offsetof: { @@ -1826,12 +1729,14 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { return ExprError(); } - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); + } // We must have at least one identifier here. if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -1853,7 +1758,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { Comps.back().LocStart = ConsumeToken(); if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -1875,7 +1780,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { SkipUntil(tok::r_paren, StopAtSemi); return Res; } - Comps.back().U.E = Res.release(); + Comps.back().U.E = Res.get(); ST.consumeClose(); Comps.back().LocEnd = ST.getCloseLocation(); @@ -1902,16 +1807,20 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { SkipUntil(tok::r_paren, StopAtSemi); return Cond; } - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); + } ExprResult Expr1(ParseAssignmentExpression()); if (Expr1.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return Expr1; } - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren)) + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); + } ExprResult Expr2(ParseAssignmentExpression()); if (Expr2.isInvalid()) { @@ -1919,11 +1828,11 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { return Expr2; } if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_rparen); + Diag(Tok, diag::err_expected) << tok::r_paren; return ExprError(); } - Res = Actions.ActOnChooseExpr(StartLoc, Cond.take(), Expr1.take(), - Expr2.take(), ConsumeParen()); + Res = Actions.ActOnChooseExpr(StartLoc, Cond.get(), Expr1.get(), + Expr2.get(), ConsumeParen()); break; } case tok::kw___builtin_astype: { @@ -1933,11 +1842,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } - - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", - tok::r_paren)) + + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); - + } + // Second argument is the type to bitcast to. TypeResult DestTy = ParseTypeName(); if (DestTy.isInvalid()) @@ -1945,12 +1855,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { // Attempt to consume the r-paren. if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_rparen); + Diag(Tok, diag::err_expected) << tok::r_paren; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } - Res = Actions.ActOnAsTypeExpr(Expr.take(), DestTy.get(), StartLoc, + Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc, ConsumeParen()); break; } @@ -1961,11 +1871,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } - - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", - tok::r_paren)) + + if (ExpectAndConsume(tok::comma)) { + SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); - + } + // Second argument is the type to bitcast to. TypeResult DestTy = ParseTypeName(); if (DestTy.isInvalid()) @@ -1973,12 +1884,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { // Attempt to consume the r-paren. if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_rparen); + Diag(Tok, diag::err_expected) << tok::r_paren; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } - Res = Actions.ActOnConvertVectorExpr(Expr.take(), DestTy.get(), StartLoc, + Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc, ConsumeParen()); break; } @@ -1989,7 +1900,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { // These can be followed by postfix-expr pieces because they are // primary-expressions. - return ParsePostfixExpressionSuffix(Res.take()); + return ParsePostfixExpressionSuffix(Res.get()); } /// ParseParenExpression - This parses the unit that starts with a '(' token, @@ -2018,6 +1929,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, bool isTypeCast, ParsedType &CastTy, SourceLocation &RParenLoc) { assert(Tok.is(tok::l_paren) && "Not a paren expr!"); + ColonProtectionRAIIObject ColonProtection(*this, false); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) return ExprError(); @@ -2042,7 +1954,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Tok.is(tok::kw___bridge_retained) || Tok.is(tok::kw___bridge_retain))); if (BridgeCast && !getLangOpts().ObjCAutoRefCount) { - if (Tok.isNot(tok::kw___bridge)) { + if (!TryConsumeToken(tok::kw___bridge)) { StringRef BridgeCastName = Tok.getName(); SourceLocation BridgeKeywordLoc = ConsumeToken(); if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc)) @@ -2050,8 +1962,6 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, << BridgeCastName << FixItHint::CreateReplacement(BridgeKeywordLoc, ""); } - else - ConsumeToken(); // consume __bridge BridgeCast = false; } @@ -2066,7 +1976,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // If the substmt parsed correctly, build the AST node. if (!Stmt.isInvalid()) { - Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation()); + Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation()); } else { Actions.ActOnStmtExprError(); } @@ -2095,6 +2005,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, TypeResult Ty = ParseTypeName(); T.consumeClose(); + ColonProtection.restore(); RParenLoc = T.getCloseLocation(); ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false); @@ -2115,7 +2026,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // if stopIfCastExpr is false, we need to determine the context past the // parens, so we defer to ParseCXXAmbiguousParenExpression for that. if (isAmbiguousTypeId && !stopIfCastExpr) { - ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T); + ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T, + ColonProtection); RParenLoc = T.getCloseLocation(); return res; } @@ -2139,10 +2051,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, } Result = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), - Ty.get(), 0); + Ty.get(), nullptr); } else { // Match the ')'. T.consumeClose(); + ColonProtection.restore(); RParenLoc = T.getCloseLocation(); if (Tok.is(tok::l_brace)) { ExprType = CompoundLiteral; @@ -2171,7 +2084,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, CastTy = Ty.get(); return ExprResult(); } - + // Reject the cast of super idiom in ObjC. if (Tok.is(tok::identifier) && getLangOpts().ObjC1 && Tok.getIdentifierInfo() == Ident_super && @@ -2190,7 +2103,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, if (!Result.isInvalid()) { Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, DeclaratorInfo, CastTy, - RParenLoc, Result.take()); + RParenLoc, Result.get()); } return Result; } @@ -2218,7 +2131,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Don't build a paren expression unless we actually match a ')'. if (!Result.isInvalid() && Tok.is(tok::r_paren)) - Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take()); + Result = + Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.get()); } // Match the ')'. @@ -2249,7 +2163,7 @@ Parser::ParseCompoundLiteralExpression(ParsedType Ty, Diag(LParenLoc, diag::ext_c99_compound_literal); ExprResult Result = ParseInitializer(); if (!Result.isInvalid() && Ty) - return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.take()); + return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get()); return Result; } @@ -2274,8 +2188,9 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) { } while (isTokenStringLiteral()); // Pass the set of string tokens, ready for concatenation, to the actions. - return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size(), - AllowUserDefinedLiteral ? getCurScope() : 0); + return Actions.ActOnStringLiteral(StringToks, + AllowUserDefinedLiteral ? getCurScope() + : nullptr); } /// ParseGenericSelectionExpression - Parse a C11 generic-selection @@ -2299,7 +2214,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { Diag(KeyLoc, diag::ext_c11_generic_selection); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return ExprError(); ExprResult ControllingExpr; @@ -2314,7 +2229,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { } } - if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "")) { + if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2322,7 +2237,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { SourceLocation DefaultLoc; TypeVector Types; ExprVector Exprs; - while (1) { + do { ParsedType Ty; if (Tok.is(tok::kw_default)) { // C11 6.5.1.1p2 "A generic selection shall have no more than one default @@ -2342,11 +2257,11 @@ ExprResult Parser::ParseGenericSelectionExpression() { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } - Ty = TR.release(); + Ty = TR.get(); } Types.push_back(Ty); - if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "")) { + if (ExpectAndConsume(tok::colon)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2358,12 +2273,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } - Exprs.push_back(ER.release()); - - if (Tok.isNot(tok::comma)) - break; - ConsumeToken(); - } + Exprs.push_back(ER.get()); + } while (TryConsumeToken(tok::comma)); T.consumeClose(); if (T.getCloseLocation().isInvalid()) @@ -2371,7 +2282,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, T.getCloseLocation(), - ControllingExpr.release(), + ControllingExpr.get(), Types, Exprs); } @@ -2403,6 +2314,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, Expr *Data, ArrayRef<Expr *> Args), Expr *Data) { + bool SawError = false; while (1) { if (Tok.is(tok::code_completion)) { if (Completer) @@ -2422,13 +2334,15 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, if (Tok.is(tok::ellipsis)) Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken()); - if (Expr.isInvalid()) - return true; - - Exprs.push_back(Expr.release()); + if (Expr.isInvalid()) { + SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch); + SawError = true; + } else { + Exprs.push_back(Expr.get()); + } if (Tok.isNot(tok::comma)) - return false; + return SawError; // Move to the next argument, remember where the comma was. CommaLocs.push_back(ConsumeToken()); } @@ -2450,7 +2364,7 @@ Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs, if (Expr.isInvalid()) return true; - Exprs.push_back(Expr.release()); + Exprs.push_back(Expr.get()); if (Tok.isNot(tok::comma)) return false; @@ -2531,7 +2445,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { // SetIdentifier sets the source range end, but in this case we're past // that location. SourceLocation Tmp = ParamInfo.getSourceRange().getEnd(); - ParamInfo.SetIdentifier(0, CaretLoc); + ParamInfo.SetIdentifier(nullptr, CaretLoc); ParamInfo.SetRangeEnd(Tmp); if (ParamInfo.isInvalidType()) { // If there was an error parsing the arguments, they may have @@ -2554,7 +2468,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true, /*IsAmbiguous=*/false, /*RParenLoc=*/NoLoc, - /*ArgInfo=*/0, + /*ArgInfo=*/nullptr, /*NumArgs=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, @@ -2566,10 +2480,10 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*MutableLoc=*/NoLoc, EST_None, /*ESpecLoc=*/NoLoc, - /*Exceptions=*/0, - /*ExceptionRanges=*/0, + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, - /*NoexceptExpr=*/0, + /*NoexceptExpr=*/nullptr, CaretLoc, CaretLoc, ParamInfo), attrs, CaretLoc); @@ -2592,7 +2506,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { StmtResult Stmt(ParseCompoundStatementBody()); BlockScope.Exit(); if (!Stmt.isInvalid()) - Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope()); + Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope()); else Actions.ActOnBlockError(CaretLoc, getCurScope()); return Result; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 5fe47fc..83121a8 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -10,12 +10,13 @@ // This file implements the Expression parsing implementation for C++. // //===----------------------------------------------------------------------===// -#include "clang/AST/DeclTemplate.h" -#include "clang/Parse/Parser.h" +#include "clang/AST/ASTContext.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -26,7 +27,9 @@ using namespace clang; static int SelectDigraphErrorMessage(tok::TokenKind Kind) { switch (Kind) { - case tok::kw_template: return 0; + // template name + case tok::unknown: return 0; + // casts case tok::kw_const_cast: return 1; case tok::kw_dynamic_cast: return 2; case tok::kw_reinterpret_cast: return 3; @@ -93,7 +96,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, Template, MemberOfUnknownSpecialization)) return; - FixDigraph(*this, PP, Next, SecondToken, tok::kw_template, + FixDigraph(*this, PP, Next, SecondToken, tok::unknown, /*AtDigraph*/false); } @@ -204,7 +207,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, } if (LastII) - *LastII = 0; + *LastII = nullptr; bool HasScopeSpecifier = false; @@ -233,12 +236,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, DeclSpec DS(AttrFactory); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation EndLoc = ParseDecltypeSpecifier(DS); - if (Tok.isNot(tok::coloncolon)) { + + SourceLocation CCLoc; + if (!TryConsumeToken(tok::coloncolon, CCLoc)) { AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc); return false; } - - SourceLocation CCLoc = ConsumeToken(); + if (Actions.ActOnCXXNestedNameSpecifierDecltype(SS, DS, CCLoc)) SS.SetInvalid(SourceRange(DeclLoc, CCLoc)); @@ -287,19 +291,23 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, TentativeParsingAction TPA(*this); SourceLocation TemplateKWLoc = ConsumeToken(); - + UnqualifiedId TemplateName; if (Tok.is(tok::identifier)) { // Consume the identifier. TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); } else if (Tok.is(tok::kw_operator)) { - if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, + // We don't need to actually parse the unqualified-id in this case, + // because a simple-template-id cannot start with 'operator', but + // go ahead and parse it anyway for consistency with the case where + // we already annotated the template-id. + if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, TemplateName)) { TPA.Commit(); break; } - + if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId && TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) { Diag(TemplateName.getSourceRange().getBegin(), @@ -341,10 +349,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) { // We have // - // simple-template-id '::' + // template-id '::' // - // So we need to check whether the simple-template-id is of the - // right kind (it should name a type or be dependent), and then + // So we need to check whether the template-id is a simple-template-id of + // the right kind (it should name a type or be dependent), and then // convert it into a type within the nested-name-specifier. TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) { @@ -357,15 +365,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Consume the template-id token. ConsumeToken(); - + assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); HasScopeSpecifier = true; - + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - + if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, TemplateId->TemplateKWLoc, @@ -385,7 +393,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, continue; } - // The rest of the nested-name-specifier possibilities start with // tok::identifier. if (Tok.isNot(tok::identifier)) @@ -410,9 +417,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // error, but they probably meant something else strange so don't // recover like this. PP.LookAhead(1).is(tok::identifier)) { - Diag(Next, diag::err_unexected_colon_in_nested_name_spec) + Diag(Next, diag::err_unexpected_colon_in_nested_name_spec) << FixItHint::CreateReplacement(Next.getLocation(), "::"); - // Recover as if the user wrote '::'. Next.setKind(tok::coloncolon); } @@ -426,23 +432,52 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (ColonIsSacred) { + const Token &Next2 = GetLookAheadToken(2); + if (Next2.is(tok::kw_private) || Next2.is(tok::kw_protected) || + Next2.is(tok::kw_public) || Next2.is(tok::kw_virtual)) { + Diag(Next2, diag::err_unexpected_token_in_nested_name_spec) + << Next2.getName() + << FixItHint::CreateReplacement(Next.getLocation(), ":"); + Token ColonColon; + PP.Lex(ColonColon); + ColonColon.setKind(tok::colon); + PP.EnterToken(ColonColon); + break; + } + } + if (LastII) *LastII = &II; // We have an identifier followed by a '::'. Lookup this name // as the name in a nested-name-specifier. + Token Identifier = Tok; SourceLocation IdLoc = ConsumeToken(); assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) && "NextToken() not working properly!"); + Token ColonColon = Tok; SourceLocation CCLoc = ConsumeToken(); CheckForLParenAfterColonColon(); - HasScopeSpecifier = true; + bool IsCorrectedToColon = false; + bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr; if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc, - ObjectType, EnteringContext, SS)) + ObjectType, EnteringContext, SS, + false, CorrectionFlagPtr)) { + // Identifier is not recognized as a nested name, but we can have + // mistyped '::' instead of ':'. + if (CorrectionFlagPtr && IsCorrectedToColon) { + ColonColon.setKind(tok::colon); + PP.EnterToken(Tok); + PP.EnterToken(ColonColon); + Tok = Identifier; + break; + } SS.SetInvalid(SourceRange(IdLoc, CCLoc)); - + } + HasScopeSpecifier = true; continue; } @@ -732,7 +767,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, !Intro.Captures.empty())) { Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, /*AfterAmpersand=*/false); - ConsumeCodeCompletionToken(); + cutOffParsing(); break; } @@ -749,7 +784,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, else Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, /*AfterAmpersand=*/false); - ConsumeCodeCompletionToken(); + cutOffParsing(); break; } @@ -758,7 +793,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // Parse capture. LambdaCaptureKind Kind = LCK_ByCopy; SourceLocation Loc; - IdentifierInfo* Id = 0; + IdentifierInfo *Id = nullptr; SourceLocation EllipsisLoc; ExprResult Init; @@ -773,7 +808,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, /*AfterAmpersand=*/true); - ConsumeCodeCompletionToken(); + cutOffParsing(); break; } } @@ -814,8 +849,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // to save the necessary state, and restore it later. EnterExpressionEvaluationContext EC(Actions, Sema::PotentiallyEvaluated); - if (Tok.is(tok::equal)) - ConsumeToken(); + TryConsumeToken(tok::equal); if (!SkippedInits) Init = ParseInitializer(); @@ -830,8 +864,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // [..., x = expr // // We need to find the end of the following expression in order to - // determine whether this is an Obj-C message send's receiver, or a - // lambda init-capture. + // determine whether this is an Obj-C message send's receiver, a + // C99 designator, or a lambda init-capture. // // Parse the expression to find where it ends, and annotate it back // onto the tokens. We would have parsed this expression the same way @@ -864,8 +898,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, ConsumeToken(); } } - } else if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); + } else + TryConsumeToken(tok::ellipsis, EllipsisLoc); } // If this is an init capture, process the initialization expression // right away. For lambda init-captures such as the following: @@ -988,7 +1022,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( ParsedAttributes Attr(AttrFactory); SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; SourceLocation EllipsisLoc; - if (Tok.isNot(tok::r_paren)) { Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth); @@ -1002,12 +1035,14 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SourceLocation RParenLoc = T.getCloseLocation(); DeclEndLoc = RParenLoc; + // GNU-style attributes must be parsed before the mutable specifier to be + // compatible with GCC. + MaybeParseGNUAttributes(Attr, &DeclEndLoc); + // Parse 'mutable'[opt]. SourceLocation MutableLoc; - if (Tok.is(tok::kw_mutable)) { - MutableLoc = ConsumeToken(); + if (TryConsumeToken(tok::kw_mutable, MutableLoc)) DeclEndLoc = MutableLoc; - } // Parse exception-specification[opt]. ExceptionSpecificationType ESpecType = EST_None; @@ -1057,26 +1092,45 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DynamicExceptionRanges.data(), DynamicExceptions.size(), NoexceptExpr.isUsable() ? - NoexceptExpr.get() : 0, + NoexceptExpr.get() : nullptr, LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); - } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow)) { - // It's common to forget that one needs '()' before 'mutable' or the - // result type. Deal with this. + } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) || + Tok.is(tok::kw___attribute) || + (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { + // It's common to forget that one needs '()' before 'mutable', an attribute + // specifier, or the result type. Deal with this. + unsigned TokKind = 0; + switch (Tok.getKind()) { + case tok::kw_mutable: TokKind = 0; break; + case tok::arrow: TokKind = 1; break; + case tok::kw___attribute: + case tok::l_square: TokKind = 2; break; + default: llvm_unreachable("Unknown token kind"); + } + Diag(Tok, diag::err_lambda_missing_parens) - << Tok.is(tok::arrow) + << TokKind << FixItHint::CreateInsertion(Tok.getLocation(), "() "); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation DeclEndLoc = DeclLoc; - + + // GNU-style attributes must be parsed before the mutable specifier to be + // compatible with GCC. + ParsedAttributes Attr(AttrFactory); + MaybeParseGNUAttributes(Attr, &DeclEndLoc); + // Parse 'mutable', if it's there. SourceLocation MutableLoc; if (Tok.is(tok::kw_mutable)) { MutableLoc = ConsumeToken(); DeclEndLoc = MutableLoc; } - + + // Parse attribute-specifier[opt]. + MaybeParseCXX11Attributes(Attr, &DeclEndLoc); + // Parse the return type, if there is one. TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { @@ -1086,12 +1140,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DeclEndLoc = Range.getEnd(); } - ParsedAttributes Attr(AttrFactory); SourceLocation NoLoc; D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, /*isAmbiguous=*/false, /*LParenLoc=*/NoLoc, - /*Params=*/0, + /*Params=*/nullptr, /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, @@ -1103,10 +1156,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( MutableLoc, EST_None, /*ESpecLoc=*/NoLoc, - /*Exceptions=*/0, - /*ExceptionRanges=*/0, + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, - /*NoexceptExpr=*/0, + /*NoexceptExpr=*/nullptr, DeclLoc, DeclEndLoc, D, TrailingReturnType), Attr, DeclEndLoc); @@ -1131,7 +1184,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( BodyScope.Exit(); if (!Stmt.isInvalid()) - return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.take(), getCurScope()); + return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope()); Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); return ExprError(); @@ -1148,7 +1201,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /// ExprResult Parser::ParseCXXCasts() { tok::TokenKind Kind = Tok.getKind(); - const char *CastName = 0; // For error messages + const char *CastName = nullptr; // For error messages switch (Kind) { default: llvm_unreachable("Unknown C++ cast!"); @@ -1182,8 +1235,8 @@ ExprResult Parser::ParseCXXCasts() { SourceLocation RAngleBracketLoc = Tok.getLocation(); - if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) - return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); + if (ExpectAndConsume(tok::greater)) + return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less); SourceLocation LParenLoc, RParenLoc; BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1200,7 +1253,7 @@ ExprResult Parser::ParseCXXCasts() { Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, LAngleBracketLoc, DeclaratorInfo, RAngleBracketLoc, - T.getOpenLocation(), Result.take(), + T.getOpenLocation(), Result.get(), T.getCloseLocation()); return Result; @@ -1266,7 +1319,7 @@ ExprResult Parser::ParseCXXTypeid() { return ExprError(); Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, - Result.release(), RParenLoc); + Result.get(), RParenLoc); } } @@ -1314,7 +1367,7 @@ ExprResult Parser::ParseCXXUuidof() { Result = Actions.ActOnCXXUuidof(OpLoc, T.getOpenLocation(), /*isType=*/false, - Result.release(), T.getCloseLocation()); + Result.get(), T.getCloseLocation()); } } @@ -1364,7 +1417,7 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail"); CCLoc = ConsumeToken(); } else { - FirstTypeName.setIdentifier(0, SourceLocation()); + FirstTypeName.setIdentifier(nullptr, SourceLocation()); } // Parse the tilde. @@ -1436,12 +1489,12 @@ ExprResult Parser::ParseThrowExpression() { case tok::r_brace: case tok::colon: case tok::comma: - return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, 0); + return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, nullptr); default: ExprResult Expr(ParseAssignmentExpression()); if (Expr.isInvalid()) return Expr; - return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, Expr.take()); + return Actions.ActOnCXXThrow(getCurScope(), ThrowLoc, Expr.get()); } } @@ -1481,7 +1534,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { ExprResult Init = ParseBraceInitializer(); if (Init.isInvalid()) return Init; - Expr *InitList = Init.take(); + Expr *InitList = Init.get(); return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(), MultiExprArg(&InitList, 1), SourceLocation()); @@ -1555,7 +1608,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, // Parse the expression. ExprOut = ParseExpression(); // expression - DeclOut = 0; + DeclOut = nullptr; if (ExprOut.isInvalid()) return true; @@ -1583,7 +1636,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, SkipUntil(tok::semi, StopAtSemi); return true; } - DeclaratorInfo.setAsmLabel(AsmLabel.release()); + DeclaratorInfo.setAsmLabel(AsmLabel.get()); DeclaratorInfo.SetRangeEnd(Loc); } @@ -1623,7 +1676,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, } if (!InitExpr.isInvalid()) - Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization, + Actions.AddInitializerToDecl(DeclOut, InitExpr.get(), !CopyInitialization, DS.containsPlaceholderType()); else Actions.ActOnInitializerError(DeclOut); @@ -1667,6 +1720,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { const char *PrevSpec; unsigned DiagID; SourceLocation Loc = Tok.getLocation(); + const clang::PrintingPolicy &Policy = + Actions.getASTContext().getPrintingPolicy(); switch (Tok.getKind()) { case tok::identifier: // foo::bar @@ -1679,7 +1734,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::annot_typename: { if (getTypeAnnotation(Tok)) DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, - getTypeAnnotation(Tok)); + getTypeAnnotation(Tok), Policy); else DS.SetTypeSpecError(); @@ -1693,19 +1748,19 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { if (Tok.is(tok::less) && getLangOpts().ObjC1) ParseObjCProtocolQualifiers(DS); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Policy); return; } // builtin types case tok::kw_short: - DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID); + DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_long: - DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID); + DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID, Policy); break; case tok::kw___int64: - DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID); + DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_signed: DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); @@ -1714,47 +1769,47 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID); break; case tok::kw_void: - DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_char: - DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_int: - DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID, Policy); break; case tok::kw___int128: - DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_half: - DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_float: - DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_double: - DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_wchar_t: - DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_char16_t: - DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_char32_t: - DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID, Policy); break; case tok::kw_bool: - DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID); + DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID, Policy); break; case tok::annot_decltype: case tok::kw_decltype: DS.SetRangeEnd(ParseDecltypeSpecifier(DS)); - return DS.Finish(Diags, PP); + return DS.Finish(Diags, PP, Policy); // GNU typeof support. case tok::kw_typeof: ParseTypeofSpecifier(DS); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Policy); return; } if (Tok.is(tok::annot_typename)) @@ -1762,7 +1817,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { else DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Policy); } /// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ @@ -1778,7 +1833,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { /// bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier); - DS.Finish(Diags, PP); + DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy()); return false; } @@ -1935,12 +1990,13 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds); + // FIXME: Store name for literal operator too. if (Id.getKind() == UnqualifiedId::IK_Identifier) { TemplateId->Name = Id.Identifier; TemplateId->Operator = OO_None; TemplateId->TemplateNameLoc = Id.StartLocation; } else { - TemplateId->Name = 0; + TemplateId->Name = nullptr; TemplateId->Operator = Id.OperatorFunctionId.Operator; TemplateId->TemplateNameLoc = Id.StartLocation; } @@ -2139,13 +2195,13 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, TokLocs.push_back(ConsumeStringToken()); } - StringLiteralParser Literal(Toks.data(), Toks.size(), PP); + StringLiteralParser Literal(Toks, PP); if (Literal.hadError) return true; // Grab the literal operator's suffix, which will be either the next token // or a ud-suffix from the string literal. - IdentifierInfo *II = 0; + IdentifierInfo *II = nullptr; SourceLocation SuffixLoc; if (!Literal.getUDSuffix().empty()) { II = &PP.getIdentifierTable().get(Literal.getUDSuffix()); @@ -2158,7 +2214,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, SuffixLoc = ConsumeToken(); TokLocs.push_back(SuffixLoc); } else { - Diag(Tok.getLocation(), diag::err_expected_ident); + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; return true; } @@ -2183,9 +2239,10 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, } Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc); - return false; + + return Actions.checkLiteralOperatorId(SS, Result); } - + // Parse a conversion-function-id. // // conversion-function-id: [C++ 12.3.2] @@ -2205,8 +2262,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Parse the conversion-declarator, which is merely a sequence of // ptr-operators. Declarator D(DS, Declarator::ConversionIdContext); - ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); - + ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr); + // Finish up the type. TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D); if (Ty.isInvalid()) @@ -2362,10 +2419,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) && (TemplateSpecified || Tok.is(tok::less))) return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, - 0, SourceLocation(), + nullptr, SourceLocation(), EnteringContext, ObjectType, Result, TemplateSpecified); - + return false; } @@ -2560,7 +2617,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, PlacementArgs, PlacementRParen, - TypeIdParens, DeclaratorInfo, Initializer.take()); + TypeIdParens, DeclaratorInfo, Initializer.get()); } /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be @@ -2598,7 +2655,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.release(), + Size.get(), T.getOpenLocation(), T.getCloseLocation()), Attrs, T.getCloseLocation()); @@ -2675,82 +2732,20 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { if (Operand.isInvalid()) return Operand; - return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.take()); -} - -static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { - switch(kind) { - default: llvm_unreachable("Not a known unary type trait."); - case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; - case tok::kw___has_nothrow_move_assign: return UTT_HasNothrowMoveAssign; - case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; - case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; - case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; - case tok::kw___has_trivial_move_assign: return UTT_HasTrivialMoveAssign; - case tok::kw___has_trivial_constructor: - return UTT_HasTrivialDefaultConstructor; - case tok::kw___has_trivial_move_constructor: - return UTT_HasTrivialMoveConstructor; - case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; - case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; - case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; - case tok::kw___is_abstract: return UTT_IsAbstract; - case tok::kw___is_arithmetic: return UTT_IsArithmetic; - case tok::kw___is_array: return UTT_IsArray; - case tok::kw___is_class: return UTT_IsClass; - case tok::kw___is_complete_type: return UTT_IsCompleteType; - case tok::kw___is_compound: return UTT_IsCompound; - case tok::kw___is_const: return UTT_IsConst; - case tok::kw___is_empty: return UTT_IsEmpty; - case tok::kw___is_enum: return UTT_IsEnum; - case tok::kw___is_final: return UTT_IsFinal; - case tok::kw___is_floating_point: return UTT_IsFloatingPoint; - case tok::kw___is_function: return UTT_IsFunction; - case tok::kw___is_fundamental: return UTT_IsFundamental; - case tok::kw___is_integral: return UTT_IsIntegral; - case tok::kw___is_interface_class: return UTT_IsInterfaceClass; - case tok::kw___is_lvalue_reference: return UTT_IsLvalueReference; - case tok::kw___is_member_function_pointer: return UTT_IsMemberFunctionPointer; - case tok::kw___is_member_object_pointer: return UTT_IsMemberObjectPointer; - case tok::kw___is_member_pointer: return UTT_IsMemberPointer; - case tok::kw___is_object: return UTT_IsObject; - case tok::kw___is_literal: return UTT_IsLiteral; - case tok::kw___is_literal_type: return UTT_IsLiteral; - case tok::kw___is_pod: return UTT_IsPOD; - case tok::kw___is_pointer: return UTT_IsPointer; - case tok::kw___is_polymorphic: return UTT_IsPolymorphic; - case tok::kw___is_reference: return UTT_IsReference; - case tok::kw___is_rvalue_reference: return UTT_IsRvalueReference; - case tok::kw___is_scalar: return UTT_IsScalar; - case tok::kw___is_sealed: return UTT_IsSealed; - case tok::kw___is_signed: return UTT_IsSigned; - case tok::kw___is_standard_layout: return UTT_IsStandardLayout; - case tok::kw___is_trivial: return UTT_IsTrivial; - case tok::kw___is_trivially_copyable: return UTT_IsTriviallyCopyable; - case tok::kw___is_union: return UTT_IsUnion; - case tok::kw___is_unsigned: return UTT_IsUnsigned; - case tok::kw___is_void: return UTT_IsVoid; - case tok::kw___is_volatile: return UTT_IsVolatile; - } -} - -static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { - switch(kind) { - default: llvm_unreachable("Not a known binary type trait"); - case tok::kw___is_base_of: return BTT_IsBaseOf; - case tok::kw___is_convertible: return BTT_IsConvertible; - case tok::kw___is_same: return BTT_IsSame; - case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible; - case tok::kw___is_convertible_to: return BTT_IsConvertibleTo; - case tok::kw___is_trivially_assignable: return BTT_IsTriviallyAssignable; - } + return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.get()); } static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) { switch (kind) { default: llvm_unreachable("Not a known type trait"); - case tok::kw___is_trivially_constructible: - return TT_IsTriviallyConstructible; +#define TYPE_TRAIT_1(Spelling, Name, Key) \ +case tok::kw_ ## Spelling: return UTT_ ## Name; +#define TYPE_TRAIT_2(Spelling, Name, Key) \ +case tok::kw_ ## Spelling: return BTT_ ## Name; +#include "clang/Basic/TokenKinds.def" +#define TYPE_TRAIT_N(Spelling, Name, Key) \ + case tok::kw_ ## Spelling: return TT_ ## Name; +#include "clang/Basic/TokenKinds.def" } } @@ -2770,87 +2765,33 @@ static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) { } } -/// ParseUnaryTypeTrait - Parse the built-in unary type-trait -/// pseudo-functions that allow implementation of the TR1/C++0x type traits -/// templates. -/// -/// primary-expression: -/// [GNU] unary-type-trait '(' type-id ')' -/// -ExprResult Parser::ParseUnaryTypeTrait() { - UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind()); - SourceLocation Loc = ConsumeToken(); - - 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 - // there will be cryptic errors about mismatched parentheses and missing - // specifiers. - TypeResult Ty = ParseTypeName(); - - T.consumeClose(); - - if (Ty.isInvalid()) - return ExprError(); - - return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), T.getCloseLocation()); -} - -/// ParseBinaryTypeTrait - Parse the built-in binary type-trait -/// pseudo-functions that allow implementation of the TR1/C++0x type traits -/// templates. -/// -/// primary-expression: -/// [GNU] binary-type-trait '(' type-id ',' type-id ')' -/// -ExprResult Parser::ParseBinaryTypeTrait() { - BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind()); - SourceLocation Loc = ConsumeToken(); - - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) - return ExprError(); - - TypeResult LhsTy = ParseTypeName(); - if (LhsTy.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return ExprError(); - } - - if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { - SkipUntil(tok::r_paren, StopAtSemi); - return ExprError(); - } - - TypeResult RhsTy = ParseTypeName(); - if (RhsTy.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return ExprError(); +static unsigned TypeTraitArity(tok::TokenKind kind) { + switch (kind) { + default: llvm_unreachable("Not a known type trait"); +#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N; +#include "clang/Basic/TokenKinds.def" } - - T.consumeClose(); - - return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), - T.getCloseLocation()); } /// \brief Parse the built-in type-trait pseudo-functions that allow /// implementation of the TR1/C++11 type traits templates. /// /// primary-expression: +/// unary-type-trait '(' type-id ')' +/// binary-type-trait '(' type-id ',' type-id ')' /// type-trait '(' type-id-seq ')' /// /// type-id-seq: /// type-id ...[opt] type-id-seq[opt] /// ExprResult Parser::ParseTypeTrait() { - TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind()); + tok::TokenKind Kind = Tok.getKind(); + unsigned Arity = TypeTraitArity(Kind); + SourceLocation Loc = ConsumeToken(); BalancedDelimiterTracker Parens(*this, tok::l_paren); - if (Parens.expectAndConsume(diag::err_expected_lparen)) + if (Parens.expectAndConsume()) return ExprError(); SmallVector<ParsedType, 2> Args; @@ -2873,19 +2814,26 @@ ExprResult Parser::ParseTypeTrait() { // Add this type to the list of arguments. Args.push_back(Ty.get()); - - if (Tok.is(tok::comma)) { - ConsumeToken(); - continue; - } - - break; - } while (true); - + } while (TryConsumeToken(tok::comma)); + if (Parens.consumeClose()) return ExprError(); - - return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation()); + + SourceLocation EndLoc = Parens.getCloseLocation(); + + if (Arity && Args.size() != Arity) { + Diag(EndLoc, diag::err_type_trait_arity) + << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc); + return ExprError(); + } + + if (!Arity && Args.empty()) { + Diag(EndLoc, diag::err_type_trait_arity) + << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc); + return ExprError(); + } + + return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc); } /// ParseArrayTypeTrait - Parse the built-in array type-trait @@ -2900,7 +2848,7 @@ ExprResult Parser::ParseArrayTypeTrait() { SourceLocation Loc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return ExprError(); TypeResult Ty = ParseTypeName(); @@ -2913,11 +2861,11 @@ ExprResult Parser::ParseArrayTypeTrait() { switch (ATT) { case ATT_ArrayRank: { T.consumeClose(); - return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), NULL, + return Actions.ActOnArrayTypeTrait(ATT, Loc, Ty.get(), nullptr, T.getCloseLocation()); } case ATT_ArrayExtent: { - if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { + if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2943,7 +2891,7 @@ ExprResult Parser::ParseExpressionTrait() { SourceLocation Loc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return ExprError(); ExprResult Expr = ParseExpression(); @@ -2961,7 +2909,8 @@ ExprResult Parser::ParseExpressionTrait() { ExprResult Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ParsedType &CastTy, - BalancedDelimiterTracker &Tracker) { + BalancedDelimiterTracker &Tracker, + ColonProtectionRAIIObject &ColonProt) { assert(getLangOpts().CPlusPlus && "Should only be called for C++!"); assert(ExprType == CastExpr && "Compound literals are not ambiguous!"); assert(isTypeIdInParens() && "Not a type-id!"); @@ -3003,13 +2952,13 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, ParseAs = CompoundLiteral; } else { bool NotCastExpr; - // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) { NotCastExpr = true; } else { // Try parsing the cast-expression that may follow. // If it is not a cast-expression, NotCastExpr will be true and no token // will be consumed. + ColonProt.restore(); Result = ParseCastExpression(false/*isUnaryExpression*/, false/*isAddressofOperand*/, NotCastExpr, @@ -3035,17 +2984,24 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (ParseAs >= CompoundLiteral) { // Parse the type declarator. DeclSpec DS(AttrFactory); - ParseSpecifierQualifierList(DS); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); - ParseDeclarator(DeclaratorInfo); + { + ColonProtectionRAIIObject InnerColonProtection(*this); + ParseSpecifierQualifierList(DS); + ParseDeclarator(DeclaratorInfo); + } // Match the ')'. Tracker.consumeClose(); + ColonProt.restore(); if (ParseAs == CompoundLiteral) { ExprType = CompoundLiteral; - TypeResult Ty = ParseTypeName(); - return ParseCompoundLiteralExpression(Ty.get(), + if (DeclaratorInfo.isInvalidType()) + return ExprError(); + + TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); + return ParseCompoundLiteralExpression(Ty.get(), Tracker.getOpenLocation(), Tracker.getCloseLocation()); } @@ -3060,7 +3016,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (!Result.isInvalid()) Result = Actions.ActOnCastExpr(getCurScope(), Tracker.getOpenLocation(), DeclaratorInfo, CastTy, - Tracker.getCloseLocation(), Result.take()); + Tracker.getCloseLocation(), Result.get()); return Result; } @@ -3071,7 +3027,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, Result = ParseExpression(); if (!Result.isInvalid() && Tok.is(tok::r_paren)) Result = Actions.ActOnParenExpr(Tracker.getOpenLocation(), - Tok.getLocation(), Result.take()); + Tok.getLocation(), Result.get()); // Match the ')'. if (Result.isInvalid()) { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp index 37f74bb..8536420 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp @@ -66,47 +66,29 @@ bool Parser::MayBeDesignationStart() { } // Parse up to (at most) the token after the closing ']' to determine - // whether this is a C99 designator or a lambda. + // whether this is a C99 designator or a lambda. TentativeParsingAction Tentative(*this); - ConsumeBracket(); - while (true) { - switch (Tok.getKind()) { - case tok::equal: - case tok::amp: - case tok::identifier: - case tok::kw_this: - // These tokens can occur in a capture list or a constant-expression. - // Keep looking. - ConsumeToken(); - continue; - - case tok::comma: - // Since a comma cannot occur in a constant-expression, this must - // be a lambda. - Tentative.Revert(); - return false; - - case tok::r_square: { - // Once we hit the closing square bracket, we look at the next - // token. If it's an '=', this is a designator. Otherwise, it's a - // lambda expression. This decision favors lambdas over the older - // GNU designator syntax, which allows one to omit the '=', but is - // consistent with GCC. - ConsumeBracket(); - tok::TokenKind Kind = Tok.getKind(); - Tentative.Revert(); - return Kind == tok::equal; - } - - default: - // Anything else cannot occur in a lambda capture list, so it - // must be a designator. - Tentative.Revert(); - return true; - } + + LambdaIntroducer Intro; + bool SkippedInits = false; + Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits)); + + if (DiagID) { + // If this can't be a lambda capture list, it's a designator. + Tentative.Revert(); + return true; } - - return true; + + // Once we hit the closing square bracket, we look at the next + // token. If it's an '=', this is a designator. Otherwise, it's a + // lambda expression. This decision favors lambdas over the older + // GNU designator syntax, which allows one to omit the '=', but is + // consistent with GCC. + tok::TokenKind Kind = Tok.getKind(); + // FIXME: If we didn't skip any inits, parse the lambda from here + // rather than throwing away then reparsing the LambdaIntroducer. + Tentative.Revert(); + return Kind == tok::equal; } static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, @@ -237,7 +219,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, ConsumeToken(), ParsedType(), - 0); + nullptr); } // Parse the receiver, which is either a type or an expression. @@ -255,7 +237,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, SourceLocation(), ParsedType::getFromOpaquePtr(TypeOrExpr), - 0); + nullptr); } // If the receiver was an expression, we still don't know @@ -282,7 +264,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, ConsumeToken(), ParsedType(), - 0); + nullptr); ConsumeToken(); // the identifier if (!ReceiverType) { SkipUntil(tok::r_square, StopAtSemi); @@ -292,7 +274,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, SourceLocation(), ReceiverType, - 0); + nullptr); case Sema::ObjCInstanceMessage: // Fall through; we'll just parse the expression and @@ -327,12 +309,12 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, SourceLocation(), ParsedType(), - Idx.take()); + Idx.get()); } // If this is a normal array designator, remember it. if (Tok.isNot(tok::ellipsis)) { - Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc)); + Desig.AddDesignator(Designator::getArray(Idx.get(), StartLoc)); } else { // Handle the gnu array range extension. Diag(Tok, diag::ext_gnu_array_range); @@ -343,8 +325,8 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { SkipUntil(tok::r_square, StopAtSemi); return RHS; } - Desig.AddDesignator(Designator::getArrayRange(Idx.release(), - RHS.release(), + Desig.AddDesignator(Designator::getArrayRange(Idx.get(), + RHS.get(), StartLoc, EllipsisLoc)); } @@ -444,7 +426,7 @@ ExprResult Parser::ParseBraceInitializer() { // If we couldn't parse the subelement, bail out. if (!SubElt.isInvalid()) { - InitExprs.push_back(SubElt.release()); + InitExprs.push_back(SubElt.get()); } else { InitExprsOk = false; @@ -493,7 +475,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return false; } @@ -512,7 +494,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, return false; } - while (Tok.isNot(tok::eof)) { + while (!isEofOrEom()) { trailingComma = false; // If we know that this cannot be a designation, just parse the nested // initializer directly. @@ -527,7 +509,7 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, // If we couldn't parse the subelement, bail out. if (!SubElt.isInvalid()) - InitExprs.push_back(SubElt.release()); + InitExprs.push_back(SubElt.get()); else InitExprsOk = false; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp index 86f38cf..7fe72ec 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -51,8 +51,8 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { cutOffParsing(); return DeclGroupPtrTy(); } - - Decl *SingleDecl = 0; + + Decl *SingleDecl = nullptr; switch (Tok.getObjCKeywordID()) { case tok::objc_class: return ParseObjCAtClassDeclaration(AtLoc); @@ -81,13 +81,13 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { case tok::objc_import: if (getLangOpts().Modules) return ParseModuleImport(AtLoc); - - // Fall through - + Diag(AtLoc, diag::err_atimport); + SkipUntil(tok::semi); + return Actions.ConvertDeclToDeclGroup(nullptr); default: Diag(AtLoc, diag::err_unexpected_at); SkipUntil(tok::semi); - SingleDecl = 0; + SingleDecl = nullptr; break; } return Actions.ConvertDeclToDeclGroup(SingleDecl); @@ -107,23 +107,21 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { while (1) { MaybeSkipAttributes(tok::objc_class); if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::semi); - return Actions.ConvertDeclToDeclGroup(0); + return Actions.ConvertDeclToDeclGroup(nullptr); } ClassNames.push_back(Tok.getIdentifierInfo()); ClassLocs.push_back(Tok.getLocation()); ConsumeToken(); - if (Tok.isNot(tok::comma)) + if (!TryConsumeToken(tok::comma)) break; - - ConsumeToken(); } // Consume the ';'. - if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class")) - return Actions.ConvertDeclToDeclGroup(0); + if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class")) + return Actions.ConvertDeclToDeclGroup(nullptr); return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(), ClassLocs.data(), @@ -189,14 +187,15 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceDecl(getCurScope()); cutOffParsing(); - return 0; + return nullptr; } MaybeSkipAttributes(tok::objc_interface); if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); // missing class or category name. - return 0; + Diag(Tok, diag::err_expected) + << tok::identifier; // missing class or category name. + return nullptr; } // We have a class or category name - consume it. @@ -209,11 +208,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, T.consumeOpen(); SourceLocation categoryLoc; - IdentifierInfo *categoryId = 0; + IdentifierInfo *categoryId = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc); cutOffParsing(); - return 0; + return nullptr; } // For ObjC2, the category name is optional (not an error). @@ -222,14 +221,15 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, categoryLoc = ConsumeToken(); } else if (!getLangOpts().ObjC2) { - Diag(Tok, diag::err_expected_ident); // missing category name. - return 0; + Diag(Tok, diag::err_expected) + << tok::identifier; // missing category name. + return nullptr; } T.consumeClose(); if (T.getCloseLocation().isInvalid()) - return 0; - + return nullptr; + if (!attrs.empty()) { // categories don't support attributes. Diag(nameLoc, diag::err_objc_no_attributes_on_category); attrs.clear(); @@ -242,7 +242,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, if (Tok.is(tok::less) && ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, LAngleLoc, EndProtoLoc)) - return 0; + return nullptr; Decl *CategoryType = Actions.ActOnStartCategoryInterface(AtLoc, @@ -260,7 +260,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, return CategoryType; } // Parse a class interface. - IdentifierInfo *superClassId = 0; + IdentifierInfo *superClassId = nullptr; SourceLocation superClassLoc; if (Tok.is(tok::colon)) { // a super class is specified. @@ -270,12 +270,13 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc); cutOffParsing(); - return 0; + return nullptr; } if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); // missing super class name. - return 0; + Diag(Tok, diag::err_expected) + << tok::identifier; // missing super class name. + return nullptr; } superClassId = Tok.getIdentifierInfo(); superClassLoc = ConsumeToken(); @@ -287,7 +288,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, if (Tok.is(tok::less) && ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, LAngleLoc, EndProtoLoc)) - return 0; + return nullptr; if (Tok.isNot(tok::less)) Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc); @@ -328,8 +329,8 @@ public: MethodImplKind(MethodImplKind) { } - void invoke(ParsingFieldDeclarator &FD) { - if (FD.D.getIdentifier() == 0) { + void invoke(ParsingFieldDeclarator &FD) override { + if (FD.D.getIdentifier() == nullptr) { P.Diag(AtLoc, diag::err_objc_property_requires_field_name) << FD.D.getSourceRange(); return; @@ -423,7 +424,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, } // If we got to the end of the file, exit the loop. - if (Tok.is(tok::eof)) + if (isEofOrEom()) break; // Code completion within an Objective-C interface. @@ -576,7 +577,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { const IdentifierInfo *II = Tok.getIdentifierInfo(); // If this is not an identifier at all, bail out early. - if (II == 0) { + if (!II) { T.consumeClose(); return; } @@ -610,8 +611,10 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter : diag::err_objc_expected_equal_for_getter; - if (ExpectAndConsume(tok::equal, DiagID, "", tok::r_paren)) + if (ExpectAndConsume(tok::equal, DiagID)) { + SkipUntil(tok::r_paren, StopAtSemi); return; + } if (Tok.is(tok::code_completion)) { if (IsSetter) @@ -636,10 +639,11 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter); DS.setSetterName(SelIdent); - if (ExpectAndConsume(tok::colon, - diag::err_expected_colon_after_setter_name, "", - tok::r_paren)) + if (ExpectAndConsume(tok::colon, + diag::err_expected_colon_after_setter_name)) { + SkipUntil(tok::r_paren, StopAtSemi); return; + } } else { DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter); DS.setGetterName(SelIdent); @@ -694,7 +698,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { switch (Tok.getKind()) { default: - return 0; + return nullptr; case tok::ampamp: case tok::ampequal: case tok::amp: @@ -713,7 +717,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { SelectorLoc = ConsumeToken(); return II; } - return 0; + return nullptr; } case tok::identifier: @@ -841,7 +845,7 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, } DS.setObjCDeclQualifier(Qual); ConsumeToken(); - II = 0; + II = nullptr; break; } @@ -862,7 +866,7 @@ static void takeDeclAttributes(ParsedAttributes &attrs, // 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); + cur->setNext(nullptr); attrs.add(cur); } } @@ -893,7 +897,8 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, ParsedAttributes *paramAttrs) { assert(context == Declarator::ObjCParameterContext || context == Declarator::ObjCResultContext); - assert((paramAttrs != 0) == (context == Declarator::ObjCParameterContext)); + assert((paramAttrs != nullptr) == + (context == Declarator::ObjCParameterContext)); assert(Tok.is(tok::l_paren) && "expected ("); @@ -990,14 +995,15 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, /*ReturnType=*/ ParsedType()); cutOffParsing(); - return 0; + return nullptr; } // Parse the return type if present. ParsedType ReturnType; ObjCDeclSpec DSRet; if (Tok.is(tok::l_paren)) - ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, 0); + ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, + nullptr); // If attributes exist before the method, parse them. ParsedAttributes methodAttrs(AttrFactory); @@ -1008,7 +1014,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, ReturnType); cutOffParsing(); - return 0; + return nullptr; } // Now parse the selector. @@ -1021,7 +1027,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, << SourceRange(mLoc, Tok.getLocation()); // Skip until we get a ; or @. SkipUntil(tok::at, StopAtSemi | StopBeforeMatch); - return 0; + return nullptr; } SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; @@ -1034,7 +1040,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Decl *Result = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, - selLoc, Sel, 0, + selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs.getList(), MethodImplKind, false, MethodDefinition); @@ -1054,11 +1060,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Sema::ObjCArgInfo ArgInfo; // Each iteration parses a single keyword argument. - if (Tok.isNot(tok::colon)) { - Diag(Tok, diag::err_expected_colon); + if (ExpectAndConsume(tok::colon)) break; - } - ConsumeToken(); // Eat the ':'. ArgInfo.Type = ParsedType(); if (Tok.is(tok::l_paren)) // Parse the argument type if present. @@ -1068,7 +1071,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist before the argument name, parse them. // Regardless, collect all the attributes we've parsed so far. - ArgInfo.ArgAttrs = 0; + ArgInfo.ArgAttrs = nullptr; if (getLangOpts().ObjC2) { MaybeParseGNUAttributes(paramAttrs); ArgInfo.ArgAttrs = paramAttrs.getList(); @@ -1082,11 +1085,12 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, /*AtParameterName=*/true, ReturnType, KeyIdents); cutOffParsing(); - return 0; + return nullptr; } if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); // missing argument name. + Diag(Tok, diag::err_expected) + << tok::identifier; // missing argument name. break; } @@ -1108,7 +1112,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, /*AtParameterName=*/false, ReturnType, KeyIdents); cutOffParsing(); - return 0; + return nullptr; } // Check for another keyword selector. @@ -1150,7 +1154,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, ParmDecl.getIdentifierLoc(), Param, - 0)); + nullptr)); } // FIXME: Add support for optional parameter list... @@ -1159,8 +1163,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, MaybeParseGNUAttributes(methodAttrs); if (KeyIdents.size() == 0) - return 0; - + return nullptr; + Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); Decl *Result @@ -1198,7 +1202,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, } if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::greater, StopAtSemi); return true; } @@ -1207,9 +1211,8 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, ProtocolLocs.push_back(Tok.getLocation()); ConsumeToken(); - if (Tok.isNot(tok::comma)) + if (!TryConsumeToken(tok::comma)) break; - ConsumeToken(); } // Consume the '>'. @@ -1254,7 +1257,7 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio // for code rewriting tools that need to be aware of the empty list. Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, - T.getOpenLocation(), T.getCloseLocation(), 0); + T.getOpenLocation(), T.getCloseLocation(), nullptr); } /// objc-class-instance-variables: @@ -1289,7 +1292,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, 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)) { + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // Each iteration of this loop reads one objc-instance-variable-decl. // Check for extraneous top-level semicolon. @@ -1299,9 +1302,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } // Set the default visibility to private. - if (Tok.is(tok::at)) { // parse objc-visibility-spec - ConsumeToken(); // eat the @ sign - + if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCAtVisibility(getCurScope()); return cutOffParsing(); @@ -1349,7 +1350,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) { } - void invoke(ParsingFieldDeclarator &FD) { + void invoke(ParsingFieldDeclarator &FD) override { P.Actions.ActOnObjCContainerStartDefinition(IDecl); // Install the declarator into the interface decl. Decl *Field @@ -1412,16 +1413,15 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, MaybeSkipAttributes(tok::objc_protocol); if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); // missing protocol name. + Diag(Tok, diag::err_expected) << tok::identifier; // missing protocol name. return DeclGroupPtrTy(); } // Save the protocol name, then consume it. IdentifierInfo *protocolName = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); - if (Tok.is(tok::semi)) { // forward declaration of one protocol. + if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. IdentifierLocPair ProtoInfo(protocolName, nameLoc); - ConsumeToken(); return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1, attrs.getList()); } @@ -1436,7 +1436,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, while (1) { ConsumeToken(); // the ',' if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::semi); return DeclGroupPtrTy(); } @@ -1448,7 +1448,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, break; } // Consume the ';'. - if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol")) + if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) return DeclGroupPtrTy(); return Actions.ActOnForwardProtocolDeclaration(AtLoc, @@ -1505,19 +1505,20 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { MaybeSkipAttributes(tok::objc_implementation); if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); // missing class or category name. + Diag(Tok, diag::err_expected) + << tok::identifier; // missing class or category name. return DeclGroupPtrTy(); } // We have a class or category name - consume it. IdentifierInfo *nameId = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); // consume class or category name - Decl *ObjCImpDecl = 0; + Decl *ObjCImpDecl = nullptr; if (Tok.is(tok::l_paren)) { // we have a category implementation. ConsumeParen(); SourceLocation categoryLoc, rparenLoc; - IdentifierInfo *categoryId = 0; + IdentifierInfo *categoryId = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc); @@ -1529,11 +1530,12 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { categoryId = Tok.getIdentifierInfo(); categoryLoc = ConsumeToken(); } else { - Diag(Tok, diag::err_expected_ident); // missing category name. + Diag(Tok, diag::err_expected) + << tok::identifier; // missing category name. return DeclGroupPtrTy(); } if (Tok.isNot(tok::r_paren)) { - Diag(Tok, diag::err_expected_rparen); + Diag(Tok, diag::err_expected) << tok::r_paren; SkipUntil(tok::r_paren); // don't stop at ';' return DeclGroupPtrTy(); } @@ -1551,12 +1553,12 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { } else { // We have a class implementation SourceLocation superClassLoc; - IdentifierInfo *superClassId = 0; - if (Tok.is(tok::colon)) { + IdentifierInfo *superClassId = nullptr; + if (TryConsumeToken(tok::colon)) { // We have a super class - ConsumeToken(); if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); // missing super class name. + Diag(Tok, diag::err_expected) + << tok::identifier; // missing super class name. return DeclGroupPtrTy(); } superClassId = Tok.getIdentifierInfo(); @@ -1582,7 +1584,7 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { { ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl); - while (!ObjCImplParsing.isFinished() && Tok.isNot(tok::eof)) { + while (!ObjCImplParsing.isFinished() && !isEofOrEom()) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); @@ -1612,14 +1614,14 @@ Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { if (!Finished) { finish(P.Tok.getLocation()); - if (P.Tok.is(tok::eof)) { + if (P.isEofOrEom()) { P.Diag(P.Tok, diag::err_objc_missing_end) << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n"); P.Diag(Dcl->getLocStart(), diag::note_objc_container_start) << Sema::OCK_Implementation; } } - P.CurParsedObjCImpl = 0; + P.CurParsedObjCImpl = nullptr; assert(LateParsedObjCMethods.empty()); } @@ -1655,19 +1657,18 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias"); ConsumeToken(); // consume compatibility_alias if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); - return 0; + Diag(Tok, diag::err_expected) << tok::identifier; + return nullptr; } IdentifierInfo *aliasId = Tok.getIdentifierInfo(); SourceLocation aliasLoc = ConsumeToken(); // consume alias-name if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); - return 0; + Diag(Tok, diag::err_expected) << tok::identifier; + return nullptr; } IdentifierInfo *classId = Tok.getIdentifierInfo(); SourceLocation classLoc = ConsumeToken(); // consume class-name; - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - "@compatibility_alias"); + ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias"); return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc, classId, classLoc); } @@ -1692,31 +1693,29 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); cutOffParsing(); - return 0; + return nullptr; } if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_synthesized_property_name); SkipUntil(tok::semi); - return 0; + return nullptr; } - - IdentifierInfo *propertyIvar = 0; + + IdentifierInfo *propertyIvar = nullptr; IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name SourceLocation propertyIvarLoc; - if (Tok.is(tok::equal)) { + if (TryConsumeToken(tok::equal)) { // property '=' ivar-name - ConsumeToken(); // consume '=' - if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); cutOffParsing(); - return 0; + return nullptr; } if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; break; } propertyIvar = Tok.getIdentifierInfo(); @@ -1728,8 +1727,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { break; ConsumeToken(); // consume ',' } - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@synthesize"); - return 0; + ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize"); + return nullptr; } /// property-dynamic: @@ -1747,26 +1746,26 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); cutOffParsing(); - return 0; + return nullptr; } if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::semi); - return 0; + return nullptr; } IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, - propertyId, 0, SourceLocation()); + propertyId, nullptr, SourceLocation()); if (Tok.isNot(tok::comma)) break; ConsumeToken(); // consume ',' } - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@dynamic"); - return 0; + ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic"); + return nullptr; } /// objc-throw-statement: @@ -1783,8 +1782,8 @@ StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { } } // consume ';' - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw"); - return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope()); + ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw"); + return Actions.ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope()); } /// objc-synchronized-statement: @@ -1806,7 +1805,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { ConsumeParen(); // ')' } else { if (!operand.isInvalid()) - Diag(Tok, diag::err_expected_rparen); + Diag(Tok, diag::err_expected) << tok::r_paren; // Skip forward until we see a left brace, but don't consume it. SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); @@ -1815,13 +1814,13 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { // Require a compound statement. if (Tok.isNot(tok::l_brace)) { if (!operand.isInvalid()) - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return StmtError(); } // Check the @synchronized operand now. if (!operand.isInvalid()) - operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.take()); + operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get()); // Parse the compound statement within a new scope. ParseScope bodyScope(this, Scope::DeclScope); @@ -1855,7 +1854,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ConsumeToken(); // consume try if (Tok.isNot(tok::l_brace)) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return StmtError(); } StmtVector CatchStmts; @@ -1877,7 +1876,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { SourceLocation AtCatchFinallyLoc = ConsumeToken(); if (Tok.isObjCAtKeyword(tok::objc_catch)) { - Decl *FirstPart = 0; + Decl *FirstPart = nullptr; ConsumeToken(); // consume catch if (Tok.is(tok::l_paren)) { ConsumeParen(); @@ -1905,16 +1904,16 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { if (Tok.is(tok::l_brace)) CatchBody = ParseCompoundStatementBody(); else - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; if (CatchBody.isInvalid()) CatchBody = Actions.ActOnNullStmt(Tok.getLocation()); StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc, FirstPart, - CatchBody.take()); + CatchBody.get()); if (!Catch.isInvalid()) - CatchStmts.push_back(Catch.release()); + CatchStmts.push_back(Catch.get()); } else { Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after) @@ -1931,11 +1930,11 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { if (Tok.is(tok::l_brace)) FinallyBody = ParseCompoundStatementBody(); else - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; if (FinallyBody.isInvalid()) FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, - FinallyBody.take()); + FinallyBody.get()); catch_or_finally_seen = true; break; } @@ -1945,9 +1944,9 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { return StmtError(); } - return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.take(), + return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(), CatchStmts, - FinallyStmt.take()); + FinallyStmt.get()); } /// objc-autoreleasepool-statement: @@ -1957,7 +1956,7 @@ StmtResult Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { ConsumeToken(); // consume autoreleasepool if (Tok.isNot(tok::l_brace)) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return StmtError(); } // Enter a scope to hold everything within the compound stmt. Compound @@ -1970,7 +1969,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { if (AutoreleasePoolBody.isInvalid()) AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation()); return Actions.ActOnObjCAutoreleasePoolStmt(atLoc, - AutoreleasePoolBody.take()); + AutoreleasePoolBody.get()); } /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them @@ -2036,13 +2035,13 @@ Decl *Parser::ParseObjCMethodDefinition() { // If we didn't find the '{', bail out. if (Tok.isNot(tok::l_brace)) - return 0; + return nullptr; } if (!MDecl) { ConsumeBrace(); SkipUntil(tok::r_brace); - return 0; + return nullptr; } // Allow the rest of sema to find private method decl implementations. @@ -2100,7 +2099,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { SourceLocation OpLoc = ConsumeToken(); if (!Tok.is(tok::numeric_constant)) { - const char *Symbol = 0; + const char *Symbol = nullptr; switch (Kind) { case tok::minus: Symbol = "-"; break; case tok::plus: Symbol = "+"; break; @@ -2117,12 +2116,12 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { } ConsumeToken(); // Consume the literal token. - Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.take()); + Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get()); if (Lit.isInvalid()) return Lit; return ParsePostfixExpressionSuffix( - Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); + Actions.BuildObjCNumericLiteral(AtLoc, Lit.get())); } case tok::string_literal: // primary-expression: string-literal @@ -2155,7 +2154,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc)); default: - if (Tok.getIdentifierInfo() == 0) + if (Tok.getIdentifierInfo() == nullptr) return ExprError(Diag(AtLoc, diag::err_unexpected_at)); switch (Tok.getIdentifierInfo()->getObjCKeywordID()) { @@ -2166,13 +2165,13 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { case tok::objc_selector: return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc)); default: { - const char *str = 0; + const char *str = nullptr; if (GetLookAheadToken(1).is(tok::l_brace)) { char ch = Tok.getIdentifierInfo()->getNameStart()[0]; str = ch == 't' ? "try" : (ch == 'f' ? "finally" - : (ch == 'a' ? "autoreleasepool" : 0)); + : (ch == 'a' ? "autoreleasepool" : nullptr)); } if (str) { SourceLocation kwLoc = Tok.getLocation(); @@ -2223,7 +2222,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { return true; IsExpr = true; - TypeOrExpr = Receiver.take(); + TypeOrExpr = Receiver.get(); return false; } @@ -2249,14 +2248,14 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { // instance method. ExprResult Receiver = ParseCXXTypeConstructExpression(DS); if (!Receiver.isInvalid()) - Receiver = ParsePostfixExpressionSuffix(Receiver.take()); + Receiver = ParsePostfixExpressionSuffix(Receiver.get()); if (!Receiver.isInvalid()) - Receiver = ParseRHSOfBinaryExpression(Receiver.take(), prec::Comma); + Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma); if (Receiver.isInvalid()) return true; IsExpr = true; - TypeOrExpr = Receiver.take(); + TypeOrExpr = Receiver.get(); return false; } @@ -2345,11 +2344,11 @@ ExprResult Parser::ParseObjCMessageExpression() { if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope()) return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), - ParsedType(), 0); + ParsedType(), nullptr); // Parse the receiver, which is either a type or an expression. bool IsExpr; - void *TypeOrExpr = NULL; + void *TypeOrExpr = nullptr; if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { SkipUntil(tok::r_square, StopAtSemi); return ExprError(); @@ -2362,7 +2361,7 @@ ExprResult Parser::ParseObjCMessageExpression() { return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), ParsedType::getFromOpaquePtr(TypeOrExpr), - 0); + nullptr); } if (Tok.is(tok::identifier)) { @@ -2375,7 +2374,7 @@ ExprResult Parser::ParseObjCMessageExpression() { ReceiverType)) { case Sema::ObjCSuperMessage: return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), - ParsedType(), 0); + ParsedType(), nullptr); case Sema::ObjCClassMessage: if (!ReceiverType) { @@ -2386,8 +2385,8 @@ ExprResult Parser::ParseObjCMessageExpression() { ConsumeToken(); // the type name return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), - ReceiverType, 0); - + ReceiverType, nullptr); + case Sema::ObjCInstanceMessage: // Fall through to parse an expression. break; @@ -2402,7 +2401,7 @@ ExprResult Parser::ParseObjCMessageExpression() { } return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), - ParsedType(), Res.take()); + ParsedType(), Res.get()); } /// \brief Parse the remainder of an Objective-C message following the @@ -2478,8 +2477,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, KeyIdents.push_back(selIdent); KeyLocs.push_back(Loc); - if (Tok.isNot(tok::colon)) { - Diag(Tok, diag::err_expected_colon); + if (ExpectAndConsume(tok::colon)) { // We must manually skip to a ']', otherwise the expression skipper will // stop at the ']' when it skips to the ';'. We want it to skip beyond // the enclosing expression. @@ -2487,7 +2485,6 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, return ExprError(); } - ConsumeToken(); // Eat the ':'. /// Parse the expression after ':' if (Tok.is(tok::code_completion)) { @@ -2525,7 +2522,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, } // We have a valid expression. - KeyExprs.push_back(Res.release()); + KeyExprs.push_back(Res.get()); // Code completion after each argument. if (Tok.is(tok::code_completion)) { @@ -2569,10 +2566,10 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, } // We have a valid expression. - KeyExprs.push_back(Res.release()); + KeyExprs.push_back(Res.get()); } } else if (!selIdent) { - Diag(Tok, diag::err_expected_ident); // missing selector name. + Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name. // We must manually skip to a ']', otherwise the expression skipper will // stop at the ']' when it skips to the ';'. We want it to skip beyond @@ -2582,10 +2579,8 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, } if (Tok.isNot(tok::r_square)) { - if (Tok.is(tok::identifier)) - Diag(Tok, diag::err_expected_colon); - else - Diag(Tok, diag::err_expected_rsquare); + Diag(Tok, diag::err_expected) + << (Tok.is(tok::identifier) ? tok::colon : tok::r_square); // We must manually skip to a ']', otherwise the expression skipper will // stop at the ']' when it skips to the ';'. We want it to skip beyond // the enclosing expression. @@ -2622,7 +2617,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { SmallVector<SourceLocation, 4> AtLocs; ExprVector AtStrings; AtLocs.push_back(AtLoc); - AtStrings.push_back(Res.release()); + AtStrings.push_back(Res.get()); while (Tok.is(tok::at)) { AtLocs.push_back(ConsumeToken()); // eat the @. @@ -2635,7 +2630,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { if (Lit.isInvalid()) return Lit; - AtStrings.push_back(Lit.release()); + AtStrings.push_back(Lit.get()); } return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(), @@ -2662,7 +2657,7 @@ ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { return Lit; } ConsumeToken(); // Consume the literal token. - return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()); + return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()); } /// ParseObjCNumericLiteral - @@ -2676,7 +2671,7 @@ ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { return Lit; } ConsumeToken(); // Consume the literal token. - return Actions.BuildObjCNumericLiteral(AtLoc, Lit.take()); + return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()); } /// ParseObjCBoxedExpr - @@ -2699,9 +2694,9 @@ Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { // Wrap the sub-expression in a parenthesized expression, to distinguish // a boxed expression from a literal. SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation(); - ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.take()); + ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get()); return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), - ValueExpr.take()); + ValueExpr.get()); } ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { @@ -2725,12 +2720,13 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { if (Res.isInvalid()) return true; - ElementExprs.push_back(Res.release()); + ElementExprs.push_back(Res.get()); if (Tok.is(tok::comma)) ConsumeToken(); // Eat the ','. else if (Tok.isNot(tok::r_square)) - return ExprError(Diag(Tok, diag::err_expected_rsquare_or_comma)); + return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square + << tok::comma); } SourceLocation EndLoc = ConsumeBracket(); // location of ']' MultiExprArg Args(ElementExprs); @@ -2755,10 +2751,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { } } - if (Tok.is(tok::colon)) { - ConsumeToken(); - } else { - Diag(Tok, diag::err_expected_colon); + if (ExpectAndConsume(tok::colon)) { SkipUntil(tok::r_brace, StopAtSemi); return ExprError(); } @@ -2774,20 +2767,19 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { // Parse the ellipsis that designates this as a pack expansion. SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis) && getLangOpts().CPlusPlus) - EllipsisLoc = ConsumeToken(); - + if (getLangOpts().CPlusPlus) + TryConsumeToken(tok::ellipsis, EllipsisLoc); + // We have a valid expression. Collect it in a vector so we can // build the argument list. ObjCDictionaryElement Element = { KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None }; Elements.push_back(Element); - - if (Tok.is(tok::comma)) - ConsumeToken(); // Eat the ','. - else if (Tok.isNot(tok::r_brace)) - return ExprError(Diag(Tok, diag::err_expected_rbrace_or_comma)); + + if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) + return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace + << tok::comma); } SourceLocation EndLoc = ConsumeBrace(); @@ -2834,7 +2826,7 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { T.consumeOpen(); if (Tok.isNot(tok::identifier)) - return ExprError(Diag(Tok, diag::err_expected_ident)); + return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); IdentifierInfo *protocolId = Tok.getIdentifierInfo(); SourceLocation ProtoIdLoc = ConsumeToken(); @@ -2847,7 +2839,7 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { } /// objc-selector-expression -/// @selector '(' objc-keyword-selector ')' +/// @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')' ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { SourceLocation SelectorLoc = ConsumeToken(); @@ -2859,7 +2851,10 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - + bool HasOptionalParen = Tok.is(tok::l_paren); + if (HasOptionalParen) + ConsumeParen(); + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); cutOffParsing(); @@ -2869,20 +2864,20 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc); if (!SelIdent && // missing selector name. Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) - return ExprError(Diag(Tok, diag::err_expected_ident)); + return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); KeyIdents.push_back(SelIdent); + unsigned nColons = 0; if (Tok.isNot(tok::r_paren)) { while (1) { - if (Tok.is(tok::coloncolon)) { // Handle :: in C++. + if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++. ++nColons; - KeyIdents.push_back(0); - } else if (Tok.isNot(tok::colon)) - return ExprError(Diag(Tok, diag::err_expected_colon)); - + KeyIdents.push_back(nullptr); + } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'. + return ExprError(); ++nColons; - ConsumeToken(); // Eat the ':' or '::'. + if (Tok.is(tok::r_paren)) break; @@ -2900,11 +2895,14 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { break; } } + if (HasOptionalParen && Tok.is(tok::r_paren)) + ConsumeParen(); // ')' T.consumeClose(); Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, T.getOpenLocation(), - T.getCloseLocation()); + T.getCloseLocation(), + !HasOptionalParen); } void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { @@ -2931,7 +2929,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || Tok.is(tok::colon)) && "Inline objective-c method not starting with '{' or 'try' or ':'"); - // Enter a scope for the method or c-fucntion body. + // Enter a scope for the method or c-function body. ParseScope BodyScope(this, parseMethod ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope @@ -2944,11 +2942,11 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { else Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl); if (Tok.is(tok::kw_try)) - MCDecl = ParseFunctionTryBlock(MCDecl, BodyScope); + ParseFunctionTryBlock(MCDecl, BodyScope); else { if (Tok.is(tok::colon)) ParseConstructorInitializer(MCDecl); - MCDecl = ParseFunctionStatementBody(MCDecl, BodyScope); + ParseFunctionStatementBody(MCDecl, BodyScope); } if (Tok.getLocation() != OrigLoc) { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp index 89e4147..d1544e6 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp @@ -11,19 +11,43 @@ /// //===----------------------------------------------------------------------===// +#include "RAIIObjectsForParser.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/StmtOpenMP.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/PointerIntPair.h" -#include "RAIIObjectsForParser.h" using namespace clang; //===----------------------------------------------------------------------===// // OpenMP declarative directives. //===----------------------------------------------------------------------===// +static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { + auto Tok = P.getCurToken(); + auto DKind = + Tok.isAnnotation() + ? OMPD_unknown + : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + if (DKind == OMPD_parallel) { + Tok = P.getPreprocessor().LookAhead(0); + auto SDKind = + Tok.isAnnotation() + ? OMPD_unknown + : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + if (SDKind == OMPD_for) { + P.ConsumeToken(); + DKind = OMPD_parallel_for; + } else if (SDKind == OMPD_sections) { + P.ConsumeToken(); + DKind = OMPD_parallel_sections; + } + } + return DKind; +} + /// \brief Parsing of declarative OpenMP directives. /// /// threadprivate-directive: @@ -35,9 +59,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { SourceLocation Loc = ConsumeToken(); SmallVector<Expr *, 5> Identifiers; - OpenMPDirectiveKind DKind = Tok.isAnnotation() ? - OMPD_unknown : - getOpenMPDirectiveKind(PP.getSpelling(Tok)); + auto DKind = ParseOpenMPDirectiveKind(*this); switch (DKind) { case OMPD_threadprivate: @@ -47,23 +69,34 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(OMPD_threadprivate); + << getOpenMPDirectiveName(OMPD_threadprivate); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } // Skip the last annot_pragma_openmp_end. ConsumeToken(); - return Actions.ActOnOpenMPThreadprivateDirective(Loc, - Identifiers); + return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); } break; case OMPD_unknown: Diag(Tok, diag::err_omp_unknown_directive); break; case OMPD_parallel: + case OMPD_simd: case OMPD_task: - case NUM_OPENMP_DIRECTIVES: + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: + case OMPD_flush: + case OMPD_for: + case OMPD_sections: + case OMPD_section: + case OMPD_single: + case OMPD_master: + case OMPD_critical: + case OMPD_parallel_for: + case OMPD_parallel_sections: Diag(Tok, diag::err_omp_unexpected_directive) - << getOpenMPDirectiveName(DKind); + << getOpenMPDirectiveName(DKind); break; } SkipUntil(tok::annot_pragma_openmp_end); @@ -76,25 +109,29 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// annot_pragma_openmp 'threadprivate' simple-variable-list /// annot_pragma_openmp_end /// -/// parallel-directive: -/// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end +/// executable-directive: +/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | +/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | +/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | +/// 'barrier' | 'taskwait' | 'flush' {clause} annot_pragma_openmp_end /// -StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { +StmtResult +Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector<Expr *, 5> Identifiers; SmallVector<OMPClause *, 5> Clauses; - SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES> - FirstClauses(NUM_OPENMP_CLAUSES); - const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | - Scope::OpenMPDirectiveScope; + SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> + FirstClauses(OMPC_unknown + 1); + unsigned ScopeFlags = + Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; SourceLocation Loc = ConsumeToken(), EndLoc; - OpenMPDirectiveKind DKind = Tok.isAnnotation() ? - OMPD_unknown : - getOpenMPDirectiveKind(PP.getSpelling(Tok)); + auto DKind = ParseOpenMPDirectiveKind(*this); // Name of critical directive. DeclarationNameInfo DirName; StmtResult Directive = StmtError(); + bool HasAssociatedStatement = true; + bool FlushHasClause = false; switch (DKind) { case OMPD_threadprivate: @@ -104,27 +141,75 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(OMPD_threadprivate); + << getOpenMPDirectiveName(OMPD_threadprivate); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } DeclGroupPtrTy Res = - Actions.ActOnOpenMPThreadprivateDirective(Loc, - Identifiers); + Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); } SkipUntil(tok::annot_pragma_openmp_end); break; - case OMPD_parallel: { + case OMPD_flush: + if (PP.LookAhead(0).is(tok::l_paren)) { + FlushHasClause = true; + // Push copy of the current token back to stream to properly parse + // pseudo-clause OMPFlushClause. + PP.EnterToken(Tok); + } + case OMPD_taskyield: + case OMPD_barrier: + case OMPD_taskwait: + if (!StandAloneAllowed) { + Diag(Tok, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind); + } + HasAssociatedStatement = false; + // Fall through for further analysis. + case OMPD_parallel: + case OMPD_simd: + case OMPD_for: + case OMPD_sections: + case OMPD_single: + case OMPD_section: + case OMPD_master: + case OMPD_critical: + case OMPD_parallel_for: + case OMPD_parallel_sections: + case OMPD_task: { ConsumeToken(); + // Parse directive name of the 'critical' directive if any. + if (DKind == OMPD_critical) { + BalancedDelimiterTracker T(*this, tok::l_paren, + tok::annot_pragma_openmp_end); + if (!T.consumeOpen()) { + if (Tok.isAnyIdentifier()) { + DirName = + DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); + ConsumeAnyToken(); + } else { + Diag(Tok, diag::err_omp_expected_identifier_for_critical); + } + T.consumeClose(); + } + } - Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope()); + if (isOpenMPLoopDirective(DKind)) + ScopeFlags |= Scope::OpenMPLoopDirectiveScope; + if (isOpenMPSimdDirective(DKind)) + ScopeFlags |= Scope::OpenMPSimdDirectiveScope; + ParseScope OMPDirectiveScope(this, ScopeFlags); + Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); while (Tok.isNot(tok::annot_pragma_openmp_end)) { - OpenMPClauseKind CKind = Tok.isAnnotation() ? - OMPC_unknown : - getOpenMPClauseKind(PP.getSpelling(Tok)); - OMPClause *Clause = ParseOpenMPClause(DKind, CKind, - !FirstClauses[CKind].getInt()); + OpenMPClauseKind CKind = + Tok.isAnnotation() + ? OMPC_unknown + : FlushHasClause ? OMPC_flush + : getOpenMPClauseKind(PP.getSpelling(Tok)); + FlushHasClause = false; + OMPClause *Clause = + ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); FirstClauses[CKind].setInt(true); if (Clause) { FirstClauses[CKind].setPointer(Clause); @@ -142,11 +227,10 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { StmtResult AssociatedStmt; bool CreateDirective = true; - ParseScope OMPDirectiveScope(this, ScopeFlags); - { + if (HasAssociatedStatement) { // The body is a block scope like in Lambdas and Blocks. Sema::CompoundScopeRAII CompoundScope(Actions); - Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1); + Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); Actions.ActOnStartOfCompoundStmt(); // Parse statement AssociatedStmt = ParseStatement(); @@ -155,30 +239,23 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { Actions.ActOnCapturedRegionError(); CreateDirective = false; } else { - AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take()); + AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get()); CreateDirective = AssociatedStmt.isUsable(); } } if (CreateDirective) - Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses, - AssociatedStmt.take(), - Loc, EndLoc); + Directive = Actions.ActOnOpenMPExecutableDirective( + DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc); // Exit scope. Actions.EndOpenMPDSABlock(Directive.get()); OMPDirectiveScope.Exit(); - } break; + } case OMPD_unknown: Diag(Tok, diag::err_omp_unknown_directive); SkipUntil(tok::annot_pragma_openmp_end); break; - case OMPD_task: - case NUM_OPENMP_DIRECTIVES: - Diag(Tok, diag::err_omp_unexpected_directive) - << getOpenMPDirectiveName(DKind); - SkipUntil(tok::annot_pragma_openmp_end); - break; } return Directive; } @@ -225,14 +302,15 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); - Diag(PrevTok.getLocation(), diag::err_expected_ident) - << SourceRange(PrevTok.getLocation(), PrevTokLocation); + Diag(PrevTok.getLocation(), diag::err_expected) + << tok::identifier + << SourceRange(PrevTok.getLocation(), PrevTokLocation); } else { DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); - ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS, - NameInfo); + ExprResult Res = + Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo); if (Res.isUsable()) - VarList.push_back(Res.take()); + VarList.push_back(Res.get()); } // Consume ','. if (Tok.is(tok::comma)) { @@ -241,7 +319,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, } if (NoIdentIsFound) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; IsCorrect = false; } @@ -254,56 +332,159 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// \brief Parsing of OpenMP clauses. /// /// clause: -/// default-clause|private-clause|firstprivate-clause|shared-clause +/// if-clause | final-clause | num_threads-clause | safelen-clause | +/// default-clause | private-clause | firstprivate-clause | shared-clause +/// | linear-clause | aligned-clause | collapse-clause | +/// lastprivate-clause | reduction-clause | proc_bind-clause | +/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | +/// mergeable-clause | flush-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { - OMPClause *Clause = 0; + OMPClause *Clause = nullptr; bool ErrorFound = false; // Check if clause is allowed for the given directive. if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { - Diag(Tok, diag::err_omp_unexpected_clause) - << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); + Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) + << getOpenMPDirectiveName(DKind); ErrorFound = true; } switch (CKind) { + case OMPC_if: + case OMPC_final: + case OMPC_num_threads: + case OMPC_safelen: + case OMPC_collapse: + // OpenMP [2.5, Restrictions] + // At most one if clause can appear on the directive. + // At most one num_threads clause can appear on the directive. + // OpenMP [2.8.1, simd construct, Restrictions] + // Only one safelen clause can appear on a simd directive. + // Only one collapse clause can appear on a simd directive. + // OpenMP [2.11.1, task Construct, Restrictions] + // At most one if clause can appear on the directive. + // At most one final clause can appear on the directive. + if (!FirstClause) { + Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) + << getOpenMPClauseName(CKind); + } + + Clause = ParseOpenMPSingleExprClause(CKind); + break; case OMPC_default: - // OpenMP [2.9.3.1, Restrictions] - // Only a single default clause may be specified on a parallel or task - // directive. + case OMPC_proc_bind: + // OpenMP [2.14.3.1, Restrictions] + // Only a single default clause may be specified on a parallel, task or + // teams directive. + // OpenMP [2.5, parallel Construct, Restrictions] + // At most one proc_bind clause can appear on the directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) - << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) + << getOpenMPClauseName(CKind); } Clause = ParseOpenMPSimpleClause(CKind); break; + case OMPC_schedule: + // OpenMP [2.7.1, Restrictions, p. 3] + // Only one schedule clause can appear on a loop directive. + if (!FirstClause) { + Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) + << getOpenMPClauseName(CKind); + } + + Clause = ParseOpenMPSingleExprWithArgClause(CKind); + break; + case OMPC_ordered: + case OMPC_nowait: + case OMPC_untied: + case OMPC_mergeable: + // OpenMP [2.7.1, Restrictions, p. 9] + // Only one ordered clause can appear on a loop directive. + // OpenMP [2.7.1, Restrictions, C/C++, p. 4] + // Only one nowait clause can appear on a for directive. + if (!FirstClause) { + Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) + << getOpenMPClauseName(CKind); + } + + Clause = ParseOpenMPClause(CKind); + break; case OMPC_private: case OMPC_firstprivate: + case OMPC_lastprivate: case OMPC_shared: + case OMPC_reduction: + case OMPC_linear: + case OMPC_aligned: + case OMPC_copyin: + case OMPC_copyprivate: + case OMPC_flush: Clause = ParseOpenMPVarListClause(CKind); break; case OMPC_unknown: Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(DKind); + << getOpenMPDirectiveName(DKind); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); break; case OMPC_threadprivate: - case NUM_OPENMP_CLAUSES: - Diag(Tok, diag::err_omp_unexpected_clause) - << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); + Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) + << getOpenMPDirectiveName(DKind); SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); break; } - return ErrorFound ? 0 : Clause; + return ErrorFound ? nullptr : Clause; +} + +/// \brief Parsing of OpenMP clauses with single expressions like 'if', +/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or +/// 'thread_limit'. +/// +/// if-clause: +/// 'if' '(' expression ')' +/// +/// final-clause: +/// 'final' '(' expression ')' +/// +/// num_threads-clause: +/// 'num_threads' '(' expression ')' +/// +/// safelen-clause: +/// 'safelen' '(' expression ')' +/// +/// collapse-clause: +/// 'collapse' '(' expression ')' +/// +OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { + SourceLocation Loc = ConsumeToken(); + + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(Kind))) + return nullptr; + + ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); + ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); + + // Parse ')'. + T.consumeClose(); + + if (Val.isInvalid()) + return nullptr; + + return Actions.ActOnOpenMPSingleExprClause( + Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation()); } -/// \brief Parsing of simple OpenMP clauses like 'default'. +/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. /// /// default-clause: /// 'default' '(' 'none' | 'shared' ') /// +/// proc_bind-clause: +/// 'proc_bind' '(' 'master' | 'close' | 'spread' ') +/// OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); @@ -311,11 +492,10 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPClauseName(Kind))) - return 0; + return nullptr; - unsigned Type = Tok.isAnnotation() ? - unsigned(OMPC_DEFAULT_unknown) : - getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); + unsigned Type = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); SourceLocation TypeLoc = Tok.getLocation(); if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && Tok.isNot(tok::annot_pragma_openmp_end)) @@ -328,54 +508,221 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { Tok.getLocation()); } -/// \brief Parsing of OpenMP clause 'private', 'firstprivate', -/// 'shared', 'copyin', or 'reduction'. +/// \brief Parsing of OpenMP clauses like 'ordered'. +/// +/// ordered-clause: +/// 'ordered' +/// +/// nowait-clause: +/// 'nowait' +/// +/// untied-clause: +/// 'untied' +/// +/// mergeable-clause: +/// 'mergeable' +/// +OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { + SourceLocation Loc = Tok.getLocation(); + ConsumeAnyToken(); + + return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); +} + + +/// \brief Parsing of OpenMP clauses with single expressions and some additional +/// argument like 'schedule' or 'dist_schedule'. +/// +/// schedule-clause: +/// 'schedule' '(' kind [',' expression ] ')' +/// +OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { + SourceLocation Loc = ConsumeToken(); + SourceLocation CommaLoc; + // Parse '('. + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(Kind))) + return nullptr; + + ExprResult Val; + unsigned Type = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + SourceLocation KLoc = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + + if (Kind == OMPC_schedule && + (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic || + Type == OMPC_SCHEDULE_guided) && + Tok.is(tok::comma)) { + CommaLoc = ConsumeAnyToken(); + ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); + Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); + if (Val.isInvalid()) + return nullptr; + } + + // Parse ')'. + T.consumeClose(); + + return Actions.ActOnOpenMPSingleExprWithArgClause( + Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc, + T.getCloseLocation()); +} + +static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, + UnqualifiedId &ReductionId) { + SourceLocation TemplateKWLoc; + if (ReductionIdScopeSpec.isEmpty()) { + auto OOK = OO_None; + switch (P.getCurToken().getKind()) { + case tok::plus: + OOK = OO_Plus; + break; + case tok::minus: + OOK = OO_Minus; + break; + case tok::star: + OOK = OO_Star; + break; + case tok::amp: + OOK = OO_Amp; + break; + case tok::pipe: + OOK = OO_Pipe; + break; + case tok::caret: + OOK = OO_Caret; + break; + case tok::ampamp: + OOK = OO_AmpAmp; + break; + case tok::pipepipe: + OOK = OO_PipePipe; + break; + default: + break; + } + if (OOK != OO_None) { + SourceLocation OpLoc = P.ConsumeToken(); + SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; + ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); + return false; + } + } + return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, + /*AllowDestructorName*/ false, + /*AllowConstructorName*/ false, ParsedType(), + TemplateKWLoc, ReductionId); +} + +/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', +/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'. /// /// private-clause: /// 'private' '(' list ')' /// firstprivate-clause: /// 'firstprivate' '(' list ')' +/// lastprivate-clause: +/// 'lastprivate' '(' list ')' /// shared-clause: /// 'shared' '(' list ')' +/// linear-clause: +/// 'linear' '(' list [ ':' linear-step ] ')' +/// aligned-clause: +/// 'aligned' '(' list [ ':' alignment ] ')' +/// reduction-clause: +/// 'reduction' '(' reduction-identifier ':' list ')' +/// copyprivate-clause: +/// 'copyprivate' '(' list ')' +/// flush-clause: +/// 'flush' '(' list ')' /// OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); + SourceLocation ColonLoc = SourceLocation(); + // Optional scope specifier and unqualified id for reduction identifier. + CXXScopeSpec ReductionIdScopeSpec; + UnqualifiedId ReductionId; + bool InvalidReductionId = false; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPClauseName(Kind))) - return 0; + return nullptr; + + // Handle reduction-identifier for reduction clause. + if (Kind == OMPC_reduction) { + ColonProtectionRAIIObject ColonRAII(*this); + if (getLangOpts().CPlusPlus) { + ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false); + } + InvalidReductionId = + ParseReductionId(*this, ReductionIdScopeSpec, ReductionId); + if (InvalidReductionId) { + SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + } + if (Tok.is(tok::colon)) { + ColonLoc = ConsumeToken(); + } else { + Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; + } + } SmallVector<Expr *, 5> Vars; - bool IsComma = true; - while (IsComma || (Tok.isNot(tok::r_paren) && + bool IsComma = !InvalidReductionId; + const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); + while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { + ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); // Parse variable ExprResult VarExpr = ParseAssignmentExpression(); if (VarExpr.isUsable()) { - Vars.push_back(VarExpr.take()); + Vars.push_back(VarExpr.get()); } else { SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } // Skip ',' if any IsComma = Tok.is(tok::comma); - if (IsComma) { + if (IsComma) ConsumeToken(); - } else if (Tok.isNot(tok::r_paren) && - Tok.isNot(tok::annot_pragma_openmp_end)) { + else if (Tok.isNot(tok::r_paren) && + Tok.isNot(tok::annot_pragma_openmp_end) && + (!MayHaveTail || Tok.isNot(tok::colon))) Diag(Tok, diag::err_omp_expected_punc) - << 1 << getOpenMPClauseName(Kind); - } + << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) + : getOpenMPClauseName(Kind)) + << (Kind == OMPC_flush); + } + + // Parse ':' linear-step (or ':' alignment). + Expr *TailExpr = nullptr; + const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); + if (MustHaveTail) { + ColonLoc = Tok.getLocation(); + ConsumeToken(); + ExprResult Tail = ParseAssignmentExpression(); + if (Tail.isUsable()) + TailExpr = Tail.get(); + else + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); } // Parse ')'. T.consumeClose(); - if (Vars.empty()) - return 0; + if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId) + return nullptr; - return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen, - Tok.getLocation()); + return Actions.ActOnOpenMPVarListClause( + Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), + ReductionIdScopeSpec, + ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) + : DeclarationNameInfo()); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp index 8a374e0..d3777f3 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp @@ -11,14 +11,288 @@ // //===----------------------------------------------------------------------===// -#include "ParsePragma.h" +#include "RAIIObjectsForParser.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Sema/LoopHint.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; +namespace { + +struct PragmaAlignHandler : public PragmaHandler { + explicit PragmaAlignHandler() : PragmaHandler("align") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaGCCVisibilityHandler : public PragmaHandler { + explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaOptionsHandler : public PragmaHandler { + explicit PragmaOptionsHandler() : PragmaHandler("options") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaPackHandler : public PragmaHandler { + explicit PragmaPackHandler() : PragmaHandler("pack") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaMSStructHandler : public PragmaHandler { + explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaUnusedHandler : public PragmaHandler { + PragmaUnusedHandler() : PragmaHandler("unused") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaWeakHandler : public PragmaHandler { + explicit PragmaWeakHandler() : PragmaHandler("weak") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaRedefineExtnameHandler : public PragmaHandler { + explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaOpenCLExtensionHandler : public PragmaHandler { + PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + + +struct PragmaFPContractHandler : public PragmaHandler { + PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaNoOpenMPHandler : public PragmaHandler { + PragmaNoOpenMPHandler() : PragmaHandler("omp") { } + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaOpenMPHandler : public PragmaHandler { + PragmaOpenMPHandler() : PragmaHandler("omp") { } + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +/// PragmaCommentHandler - "\#pragma comment ...". +struct PragmaCommentHandler : public PragmaHandler { + PragmaCommentHandler(Sema &Actions) + : PragmaHandler("comment"), Actions(Actions) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +private: + Sema &Actions; +}; + +struct PragmaDetectMismatchHandler : public PragmaHandler { + PragmaDetectMismatchHandler(Sema &Actions) + : PragmaHandler("detect_mismatch"), Actions(Actions) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +private: + Sema &Actions; +}; + +struct PragmaMSPointersToMembers : public PragmaHandler { + explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaMSVtorDisp : public PragmaHandler { + explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaMSPragma : public PragmaHandler { + explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +/// PragmaOptimizeHandler - "\#pragma clang optimize on/off". +struct PragmaOptimizeHandler : public PragmaHandler { + PragmaOptimizeHandler(Sema &S) + : PragmaHandler("optimize"), Actions(S) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +private: + Sema &Actions; +}; + +struct PragmaLoopHintHandler : public PragmaHandler { + PragmaLoopHintHandler() : PragmaHandler("loop") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +struct PragmaUnrollHintHandler : public PragmaHandler { + PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + +} // end namespace + +void Parser::initializePragmaHandlers() { + AlignHandler.reset(new PragmaAlignHandler()); + PP.AddPragmaHandler(AlignHandler.get()); + + GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); + PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); + + OptionsHandler.reset(new PragmaOptionsHandler()); + PP.AddPragmaHandler(OptionsHandler.get()); + + PackHandler.reset(new PragmaPackHandler()); + PP.AddPragmaHandler(PackHandler.get()); + + MSStructHandler.reset(new PragmaMSStructHandler()); + PP.AddPragmaHandler(MSStructHandler.get()); + + UnusedHandler.reset(new PragmaUnusedHandler()); + PP.AddPragmaHandler(UnusedHandler.get()); + + WeakHandler.reset(new PragmaWeakHandler()); + PP.AddPragmaHandler(WeakHandler.get()); + + RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); + PP.AddPragmaHandler(RedefineExtnameHandler.get()); + + FPContractHandler.reset(new PragmaFPContractHandler()); + PP.AddPragmaHandler("STDC", FPContractHandler.get()); + + if (getLangOpts().OpenCL) { + OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); + PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); + + PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); + } + if (getLangOpts().OpenMP) + OpenMPHandler.reset(new PragmaOpenMPHandler()); + else + OpenMPHandler.reset(new PragmaNoOpenMPHandler()); + PP.AddPragmaHandler(OpenMPHandler.get()); + + if (getLangOpts().MicrosoftExt) { + MSCommentHandler.reset(new PragmaCommentHandler(Actions)); + PP.AddPragmaHandler(MSCommentHandler.get()); + MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions)); + PP.AddPragmaHandler(MSDetectMismatchHandler.get()); + MSPointersToMembers.reset(new PragmaMSPointersToMembers()); + PP.AddPragmaHandler(MSPointersToMembers.get()); + MSVtorDisp.reset(new PragmaMSVtorDisp()); + PP.AddPragmaHandler(MSVtorDisp.get()); + MSInitSeg.reset(new PragmaMSPragma("init_seg")); + PP.AddPragmaHandler(MSInitSeg.get()); + MSDataSeg.reset(new PragmaMSPragma("data_seg")); + PP.AddPragmaHandler(MSDataSeg.get()); + MSBSSSeg.reset(new PragmaMSPragma("bss_seg")); + PP.AddPragmaHandler(MSBSSSeg.get()); + MSConstSeg.reset(new PragmaMSPragma("const_seg")); + PP.AddPragmaHandler(MSConstSeg.get()); + MSCodeSeg.reset(new PragmaMSPragma("code_seg")); + PP.AddPragmaHandler(MSCodeSeg.get()); + MSSection.reset(new PragmaMSPragma("section")); + PP.AddPragmaHandler(MSSection.get()); + } + + OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); + PP.AddPragmaHandler("clang", OptimizeHandler.get()); + + LoopHintHandler.reset(new PragmaLoopHintHandler()); + PP.AddPragmaHandler("clang", LoopHintHandler.get()); + + UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll")); + PP.AddPragmaHandler(UnrollHintHandler.get()); +} + +void Parser::resetPragmaHandlers() { + // Remove the pragma handlers we installed. + PP.RemovePragmaHandler(AlignHandler.get()); + AlignHandler.reset(); + PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get()); + GCCVisibilityHandler.reset(); + PP.RemovePragmaHandler(OptionsHandler.get()); + OptionsHandler.reset(); + PP.RemovePragmaHandler(PackHandler.get()); + PackHandler.reset(); + PP.RemovePragmaHandler(MSStructHandler.get()); + MSStructHandler.reset(); + PP.RemovePragmaHandler(UnusedHandler.get()); + UnusedHandler.reset(); + PP.RemovePragmaHandler(WeakHandler.get()); + WeakHandler.reset(); + PP.RemovePragmaHandler(RedefineExtnameHandler.get()); + RedefineExtnameHandler.reset(); + + if (getLangOpts().OpenCL) { + PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); + OpenCLExtensionHandler.reset(); + PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); + } + PP.RemovePragmaHandler(OpenMPHandler.get()); + OpenMPHandler.reset(); + + if (getLangOpts().MicrosoftExt) { + PP.RemovePragmaHandler(MSCommentHandler.get()); + MSCommentHandler.reset(); + PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); + MSDetectMismatchHandler.reset(); + PP.RemovePragmaHandler(MSPointersToMembers.get()); + MSPointersToMembers.reset(); + PP.RemovePragmaHandler(MSVtorDisp.get()); + MSVtorDisp.reset(); + PP.RemovePragmaHandler(MSInitSeg.get()); + MSInitSeg.reset(); + PP.RemovePragmaHandler(MSDataSeg.get()); + MSDataSeg.reset(); + PP.RemovePragmaHandler(MSBSSSeg.get()); + MSBSSSeg.reset(); + PP.RemovePragmaHandler(MSConstSeg.get()); + MSConstSeg.reset(); + PP.RemovePragmaHandler(MSCodeSeg.get()); + MSCodeSeg.reset(); + PP.RemovePragmaHandler(MSSection.get()); + MSSection.reset(); + } + + PP.RemovePragmaHandler("STDC", FPContractHandler.get()); + FPContractHandler.reset(); + + PP.RemovePragmaHandler("clang", OptimizeHandler.get()); + OptimizeHandler.reset(); + + PP.RemovePragmaHandler("clang", LoopHintHandler.get()); + LoopHintHandler.reset(); + + PP.RemovePragmaHandler(UnrollHintHandler.get()); + UnrollHintHandler.reset(); +} + /// \brief Handle the annotation token produced for #pragma unused(...) /// /// Each annot_pragma_unused is followed by the argument token so e.g. @@ -130,7 +404,7 @@ StmtResult Parser::HandlePragmaCaptured() ConsumeToken(); if (Tok.isNot(tok::l_brace)) { - PP.Diag(Tok, diag::err_expected_lbrace); + PP.Diag(Tok, diag::err_expected) << tok::l_brace; return StmtError(); } @@ -180,7 +454,307 @@ void Parser::HandlePragmaOpenCLExtension() { } } +void Parser::HandlePragmaMSPointersToMembers() { + assert(Tok.is(tok::annot_pragma_ms_pointers_to_members)); + LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = + static_cast<LangOptions::PragmaMSPointersToMembersKind>( + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); + SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); +} + +void Parser::HandlePragmaMSVtorDisp() { + assert(Tok.is(tok::annot_pragma_ms_vtordisp)); + uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()); + Sema::PragmaVtorDispKind Kind = + static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF); + MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF); + SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode); +} +void Parser::HandlePragmaMSPragma() { + assert(Tok.is(tok::annot_pragma_ms_pragma)); + // Grab the tokens out of the annotation and enter them into the stream. + auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue(); + PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true); + SourceLocation PragmaLocation = ConsumeToken(); // The annotation token. + assert(Tok.isAnyIdentifier()); + StringRef PragmaName = Tok.getIdentifierInfo()->getName(); + PP.Lex(Tok); // pragma kind + + // Figure out which #pragma we're dealing with. The switch has no default + // because lex shouldn't emit the annotation token for unrecognized pragmas. + typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation); + PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName) + .Case("data_seg", &Parser::HandlePragmaMSSegment) + .Case("bss_seg", &Parser::HandlePragmaMSSegment) + .Case("const_seg", &Parser::HandlePragmaMSSegment) + .Case("code_seg", &Parser::HandlePragmaMSSegment) + .Case("section", &Parser::HandlePragmaMSSection) + .Case("init_seg", &Parser::HandlePragmaMSInitSeg); + + if (!(this->*Handler)(PragmaName, PragmaLocation)) { + // Pragma handling failed, and has been diagnosed. Slurp up the tokens + // until eof (really end of line) to prevent follow-on errors. + while (Tok.isNot(tok::eof)) + PP.Lex(Tok); + PP.Lex(Tok); + } +} + +bool Parser::HandlePragmaMSSection(StringRef PragmaName, + SourceLocation PragmaLocation) { + if (Tok.isNot(tok::l_paren)) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; + return false; + } + PP.Lex(Tok); // ( + // Parsing code for pragma section + if (Tok.isNot(tok::string_literal)) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name) + << PragmaName; + return false; + } + ExprResult StringResult = ParseStringLiteralExpression(); + if (StringResult.isInvalid()) + return false; // Already diagnosed. + StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get()); + if (SegmentName->getCharByteWidth() != 1) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) + << PragmaName; + return false; + } + int SectionFlags = 0; + while (Tok.is(tok::comma)) { + PP.Lex(Tok); // , + if (!Tok.isAnyIdentifier()) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren) + << PragmaName; + return false; + } + Sema::PragmaSectionFlag Flag = + llvm::StringSwitch<Sema::PragmaSectionFlag>( + Tok.getIdentifierInfo()->getName()) + .Case("read", Sema::PSF_Read) + .Case("write", Sema::PSF_Write) + .Case("execute", Sema::PSF_Execute) + .Case("shared", Sema::PSF_Invalid) + .Case("nopage", Sema::PSF_Invalid) + .Case("nocache", Sema::PSF_Invalid) + .Case("discard", Sema::PSF_Invalid) + .Case("remove", Sema::PSF_Invalid) + .Default(Sema::PSF_None); + if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) { + PP.Diag(PragmaLocation, Flag == Sema::PSF_None + ? diag::warn_pragma_invalid_specific_action + : diag::warn_pragma_unsupported_action) + << PragmaName << Tok.getIdentifierInfo()->getName(); + return false; + } + SectionFlags |= Flag; + PP.Lex(Tok); // Identifier + } + if (Tok.isNot(tok::r_paren)) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; + return false; + } + PP.Lex(Tok); // ) + if (Tok.isNot(tok::eof)) { + PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) + << PragmaName; + return false; + } + PP.Lex(Tok); // eof + Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName); + return true; +} + +bool Parser::HandlePragmaMSSegment(StringRef PragmaName, + SourceLocation PragmaLocation) { + if (Tok.isNot(tok::l_paren)) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName; + return false; + } + PP.Lex(Tok); // ( + Sema::PragmaMsStackAction Action = Sema::PSK_Reset; + StringRef SlotLabel; + if (Tok.isAnyIdentifier()) { + StringRef PushPop = Tok.getIdentifierInfo()->getName(); + if (PushPop == "push") + Action = Sema::PSK_Push; + else if (PushPop == "pop") + Action = Sema::PSK_Pop; + else { + PP.Diag(PragmaLocation, + diag::warn_pragma_expected_section_push_pop_or_name) + << PragmaName; + return false; + } + if (Action != Sema::PSK_Reset) { + PP.Lex(Tok); // push | pop + if (Tok.is(tok::comma)) { + PP.Lex(Tok); // , + // If we've got a comma, we either need a label or a string. + if (Tok.isAnyIdentifier()) { + SlotLabel = Tok.getIdentifierInfo()->getName(); + PP.Lex(Tok); // identifier + if (Tok.is(tok::comma)) + PP.Lex(Tok); + else if (Tok.isNot(tok::r_paren)) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) + << PragmaName; + return false; + } + } + } else if (Tok.isNot(tok::r_paren)) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName; + return false; + } + } + } + // Grab the string literal for our section name. + StringLiteral *SegmentName = nullptr; + if (Tok.isNot(tok::r_paren)) { + if (Tok.isNot(tok::string_literal)) { + unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ? + diag::warn_pragma_expected_section_name : + diag::warn_pragma_expected_section_label_or_name : + diag::warn_pragma_expected_section_push_pop_or_name; + PP.Diag(PragmaLocation, DiagID) << PragmaName; + return false; + } + ExprResult StringResult = ParseStringLiteralExpression(); + if (StringResult.isInvalid()) + return false; // Already diagnosed. + SegmentName = cast<StringLiteral>(StringResult.get()); + if (SegmentName->getCharByteWidth() != 1) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) + << PragmaName; + return false; + } + // Setting section "" has no effect + if (SegmentName->getLength()) + Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); + } + if (Tok.isNot(tok::r_paren)) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; + return false; + } + PP.Lex(Tok); // ) + if (Tok.isNot(tok::eof)) { + PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol) + << PragmaName; + return false; + } + PP.Lex(Tok); // eof + Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel, + SegmentName, PragmaName); + return true; +} + +// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} ) +bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, + SourceLocation PragmaLocation) { + if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) { + PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target); + return false; + } + + if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen, + PragmaName)) + return false; + + // Parse either the known section names or the string section name. + StringLiteral *SegmentName = nullptr; + if (Tok.isAnyIdentifier()) { + auto *II = Tok.getIdentifierInfo(); + StringRef Section = llvm::StringSwitch<StringRef>(II->getName()) + .Case("compiler", "\".CRT$XCC\"") + .Case("lib", "\".CRT$XCL\"") + .Case("user", "\".CRT$XCU\"") + .Default(""); + + if (!Section.empty()) { + // Pretend the user wrote the appropriate string literal here. + Token Toks[1]; + Toks[0].startToken(); + Toks[0].setKind(tok::string_literal); + Toks[0].setLocation(Tok.getLocation()); + Toks[0].setLiteralData(Section.data()); + Toks[0].setLength(Section.size()); + SegmentName = + cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get()); + PP.Lex(Tok); + } + } else if (Tok.is(tok::string_literal)) { + ExprResult StringResult = ParseStringLiteralExpression(); + if (StringResult.isInvalid()) + return false; + SegmentName = cast<StringLiteral>(StringResult.get()); + if (SegmentName->getCharByteWidth() != 1) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string) + << PragmaName; + return false; + } + // FIXME: Add support for the '[, func-name]' part of the pragma. + } + + if (!SegmentName) { + PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName; + return false; + } + + if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen, + PragmaName) || + ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol, + PragmaName)) + return false; + + Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName); + return true; +} + +struct PragmaLoopHintInfo { + Token PragmaName; + Token Option; + Token Value; + bool HasValue; +}; + +LoopHint Parser::HandlePragmaLoopHint() { + assert(Tok.is(tok::annot_pragma_loop_hint)); + PragmaLoopHintInfo *Info = + static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue()); + + LoopHint Hint; + Hint.PragmaNameLoc = + IdentifierLoc::create(Actions.Context, Info->PragmaName.getLocation(), + Info->PragmaName.getIdentifierInfo()); + Hint.OptionLoc = + IdentifierLoc::create(Actions.Context, Info->Option.getLocation(), + Info->Option.getIdentifierInfo()); + if (Info->HasValue) { + Hint.Range = + SourceRange(Info->Option.getLocation(), Info->Value.getLocation()); + Hint.ValueLoc = + IdentifierLoc::create(Actions.Context, Info->Value.getLocation(), + Info->Value.getIdentifierInfo()); + + // FIXME: We should allow non-type template parameters for the loop hint + // value. See bug report #19610 + if (Info->Value.is(tok::numeric_constant)) + Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get(); + else + Hint.ValueExpr = nullptr; + } else { + Hint.Range = SourceRange(Info->PragmaName.getLocation()); + Hint.ValueLoc = nullptr; + Hint.ValueExpr = nullptr; + } + + return Hint; +} // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' @@ -197,7 +771,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, const IdentifierInfo *VisType; if (PushPop && PushPop->isStr("pop")) { - VisType = 0; + VisType = nullptr; } else if (PushPop && PushPop->isStr("push")) { PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::l_paren)) { @@ -257,7 +831,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, } Sema::PragmaPackKind Kind = Sema::PPK_Default; - IdentifierInfo *Name = 0; + IdentifierInfo *Name = nullptr; Token Alignment; Alignment.startToken(); SourceLocation LParenLoc = Tok.getLocation(); @@ -283,7 +857,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, } else if (II->isStr("pop")) { Kind = Sema::PPK_Pop; } else { - PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action); + PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack"; return; } PP.Lex(Tok); @@ -530,7 +1104,7 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, } // Illegal token! - PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused"; return; } @@ -760,13 +1334,11 @@ void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstTok) { - if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored, - FirstTok.getLocation()) != - DiagnosticsEngine::Ignored) { + if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored, + FirstTok.getLocation())) { PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); - PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored, - diag::MAP_IGNORE, - SourceLocation()); + PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored, + diag::Severity::Ignored, SourceLocation()); } PP.DiscardUntilEndOfDirective(); } @@ -799,6 +1371,220 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); } +/// \brief Handle '#pragma pointers_to_members' +// The grammar for this pragma is as follows: +// +// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' +// +// #pragma pointers_to_members '(' 'best_case' ')' +// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')' +// #pragma pointers_to_members '(' inheritance-model ')' +void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + SourceLocation PointersToMembersLoc = Tok.getLocation(); + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen) + << "pointers_to_members"; + return; + } + PP.Lex(Tok); + const IdentifierInfo *Arg = Tok.getIdentifierInfo(); + if (!Arg) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) + << "pointers_to_members"; + return; + } + PP.Lex(Tok); + + LangOptions::PragmaMSPointersToMembersKind RepresentationMethod; + if (Arg->isStr("best_case")) { + RepresentationMethod = LangOptions::PPTMK_BestCase; + } else { + if (Arg->isStr("full_generality")) { + if (Tok.is(tok::comma)) { + PP.Lex(Tok); + + Arg = Tok.getIdentifierInfo(); + if (!Arg) { + PP.Diag(Tok.getLocation(), + diag::err_pragma_pointers_to_members_unknown_kind) + << Tok.getKind() << /*OnlyInheritanceModels*/ 0; + return; + } + PP.Lex(Tok); + } else if (Tok.is(tok::r_paren)) { + // #pragma pointers_to_members(full_generality) implicitly specifies + // virtual_inheritance. + Arg = nullptr; + RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance; + } else { + PP.Diag(Tok.getLocation(), diag::err_expected_punc) + << "full_generality"; + return; + } + } + + if (Arg) { + if (Arg->isStr("single_inheritance")) { + RepresentationMethod = + LangOptions::PPTMK_FullGeneralitySingleInheritance; + } else if (Arg->isStr("multiple_inheritance")) { + RepresentationMethod = + LangOptions::PPTMK_FullGeneralityMultipleInheritance; + } else if (Arg->isStr("virtual_inheritance")) { + RepresentationMethod = + LangOptions::PPTMK_FullGeneralityVirtualInheritance; + } else { + PP.Diag(Tok.getLocation(), + diag::err_pragma_pointers_to_members_unknown_kind) + << Arg << /*HasPointerDeclaration*/ 1; + return; + } + } + } + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) + << (Arg ? Arg->getName() : "full_generality"); + return; + } + + PP.Lex(Tok); + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "pointers_to_members"; + return; + } + + Token AnnotTok; + AnnotTok.startToken(); + AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); + AnnotTok.setLocation(PointersToMembersLoc); + AnnotTok.setAnnotationValue( + reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); + PP.EnterToken(AnnotTok); +} + +/// \brief Handle '#pragma vtordisp' +// The grammar for this pragma is as follows: +// +// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' ) +// +// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')' +// #pragma vtordisp '(' 'pop' ')' +// #pragma vtordisp '(' ')' +void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + SourceLocation VtorDispLoc = Tok.getLocation(); + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp"; + return; + } + PP.Lex(Tok); + + Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set; + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II) { + if (II->isStr("push")) { + // #pragma vtordisp(push, mode) + PP.Lex(Tok); + if (Tok.isNot(tok::comma)) { + PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp"; + return; + } + PP.Lex(Tok); + Kind = Sema::PVDK_Push; + // not push, could be on/off + } else if (II->isStr("pop")) { + // #pragma vtordisp(pop) + PP.Lex(Tok); + Kind = Sema::PVDK_Pop; + } + // not push or pop, could be on/off + } else { + if (Tok.is(tok::r_paren)) { + // #pragma vtordisp() + Kind = Sema::PVDK_Reset; + } + } + + + uint64_t Value = 0; + if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) { + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II && II->isStr("off")) { + PP.Lex(Tok); + Value = 0; + } else if (II && II->isStr("on")) { + PP.Lex(Tok); + Value = 1; + } else if (Tok.is(tok::numeric_constant) && + PP.parseSimpleIntegerLiteral(Tok, Value)) { + if (Value > 2) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer) + << 0 << 2 << "vtordisp"; + return; + } + } else { + PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) + << "vtordisp"; + return; + } + } + + // Finish the pragma: ')' $ + if (Tok.isNot(tok::r_paren)) { + PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp"; + return; + } + PP.Lex(Tok); + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "vtordisp"; + return; + } + + // Enter the annotation. + Token AnnotTok; + AnnotTok.startToken(); + AnnotTok.setKind(tok::annot_pragma_ms_vtordisp); + AnnotTok.setLocation(VtorDispLoc); + AnnotTok.setAnnotationValue(reinterpret_cast<void *>( + static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF)))); + PP.EnterToken(AnnotTok); +} + +/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting +/// an annotation token. +void PragmaMSPragma::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + Token EoF, AnnotTok; + EoF.startToken(); + EoF.setKind(tok::eof); + AnnotTok.startToken(); + AnnotTok.setKind(tok::annot_pragma_ms_pragma); + AnnotTok.setLocation(Tok.getLocation()); + SmallVector<Token, 8> TokenVector; + // Suck up all of the tokens before the eod. + for (; Tok.isNot(tok::eod); PP.Lex(Tok)) + TokenVector.push_back(Tok); + // Add a sentinal EoF token to the end of the list. + TokenVector.push_back(EoF); + // We must allocate this array with new because EnterTokenStream is going to + // delete it later. + Token *TokenArray = new Token[TokenVector.size()]; + std::copy(TokenVector.begin(), TokenVector.end(), TokenArray); + auto Value = new (PP.getPreprocessorAllocator()) + std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size())); + AnnotTok.setAnnotationValue(Value); + PP.EnterToken(AnnotTok); +} + /// \brief Handle the Microsoft \#pragma detect_mismatch extension. /// /// The syntax is: @@ -815,7 +1601,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, SourceLocation CommentLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::l_paren)) { - PP.Diag(CommentLoc, diag::err_expected_lparen); + PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren; return; } @@ -838,7 +1624,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, return; if (Tok.isNot(tok::r_paren)) { - PP.Diag(Tok.getLocation(), diag::err_expected_rparen); + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; return; } PP.Lex(Tok); // Eat the r_paren. @@ -929,3 +1715,251 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP, Actions.ActOnPragmaMSComment(Kind, ArgumentString); } + +// #pragma clang optimize off +// #pragma clang optimize on +void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstToken) { + Token Tok; + PP.Lex(Tok); + if (Tok.is(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) + << "clang optimize" + << "'on' or 'off'"; + return; + } + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) + << PP.getSpelling(Tok); + return; + } + const IdentifierInfo *II = Tok.getIdentifierInfo(); + // The only accepted values are 'on' or 'off'. + bool IsOn = false; + if (II->isStr("on")) { + IsOn = true; + } else if (!II->isStr("off")) { + PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument) + << PP.getSpelling(Tok); + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument) + << PP.getSpelling(Tok); + return; + } + + Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); +} + +/// \brief Parses loop or unroll pragma hint value and fills in Info. +static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName, + Token &Option, bool &ValueInParens, + PragmaLoopHintInfo &Info) { + ValueInParens = Tok.is(tok::l_paren); + if (ValueInParens) { + PP.Lex(Tok); + if (Tok.is(tok::r_paren)) { + // Nothing between the parentheses. + std::string PragmaString; + if (PragmaName.getIdentifierInfo()->getName() == "loop") { + PragmaString = "clang loop "; + PragmaString += Option.getIdentifierInfo()->getName(); + } else { + assert(PragmaName.getIdentifierInfo()->getName() == "unroll" && + "Unexpected pragma name"); + PragmaString = "unroll"; + } + PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) + << PragmaString << "a positive integer value"; + return true; + } + } + + // FIXME: Value should be stored and parsed as a constant expression. + Token Value = Tok; + + if (ValueInParens) { + PP.Lex(Tok); + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; + return true; + } + } + + Info.PragmaName = PragmaName; + Info.Option = Option; + Info.Value = Value; + Info.HasValue = true; + return false; +} + +/// \brief Handle the \#pragma clang loop directive. +/// #pragma clang 'loop' loop-hints +/// +/// loop-hints: +/// loop-hint loop-hints[opt] +/// +/// loop-hint: +/// 'vectorize' '(' loop-hint-keyword ')' +/// 'interleave' '(' loop-hint-keyword ')' +/// 'unroll' '(' loop-hint-keyword ')' +/// 'vectorize_width' '(' loop-hint-value ')' +/// 'interleave_count' '(' loop-hint-value ')' +/// 'unroll_count' '(' loop-hint-value ')' +/// +/// loop-hint-keyword: +/// 'enable' +/// 'disable' +/// +/// loop-hint-value: +/// constant-expression +/// +/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to +/// try vectorizing the instructions of the loop it precedes. Specifying +/// interleave(enable) or interleave_count(_value_) instructs llvm to try +/// interleaving multiple iterations of the loop it precedes. The width of the +/// vector instructions is specified by vectorize_width() and the number of +/// interleaved loop iterations is specified by interleave_count(). Specifying a +/// value of 1 effectively disables vectorization/interleaving, even if it is +/// possible and profitable, and 0 is invalid. The loop vectorizer currently +/// only works on inner loops. +/// +/// The unroll and unroll_count directives control the concatenation +/// unroller. Specifying unroll(enable) instructs llvm to try to +/// unroll the loop completely, and unroll(disable) disables unrolling +/// for the loop. Specifying unroll_count(_value_) instructs llvm to +/// try to unroll the loop the number of times indicated by the value. +/// If unroll(enable) and unroll_count are both specified only +/// unroll_count takes effect. +void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + // Incoming token is "loop" from "#pragma clang loop". + Token PragmaName = Tok; + SmallVector<Token, 1> TokenList; + + // Lex the optimization option and verify it is an identifier. + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) + << /*MissingOption=*/true << ""; + return; + } + + while (Tok.is(tok::identifier)) { + Token Option = Tok; + IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); + + bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName()) + .Case("vectorize", true) + .Case("interleave", true) + .Case("unroll", true) + .Case("vectorize_width", true) + .Case("interleave_count", true) + .Case("unroll_count", true) + .Default(false); + if (!OptionValid) { + PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) + << /*MissingOption=*/false << OptionInfo; + return; + } + + auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; + PP.Lex(Tok); + bool ValueInParens; + if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info)) + return; + + if (!ValueInParens) { + PP.Diag(Info->Value.getLocation(), diag::err_expected) << tok::l_paren; + return; + } + + // Generate the loop hint token. + Token LoopHintTok; + LoopHintTok.startToken(); + LoopHintTok.setKind(tok::annot_pragma_loop_hint); + LoopHintTok.setLocation(PragmaName.getLocation()); + LoopHintTok.setAnnotationValue(static_cast<void *>(Info)); + TokenList.push_back(LoopHintTok); + + // Get next optimization option. + PP.Lex(Tok); + } + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "clang loop"; + return; + } + + Token *TokenArray = new Token[TokenList.size()]; + std::copy(TokenList.begin(), TokenList.end(), TokenArray); + + PP.EnterTokenStream(TokenArray, TokenList.size(), + /*DisableMacroExpansion=*/false, + /*OwnsTokens=*/true); +} + +/// \brief Handle the loop unroll optimization pragmas. +/// #pragma unroll +/// #pragma unroll unroll-hint-value +/// #pragma unroll '(' unroll-hint-value ')' +/// +/// unroll-hint-value: +/// constant-expression +/// +/// Loop unrolling hints are specified with '#pragma unroll'. '#pragma unroll' +/// can take a numeric argument optionally contained in parentheses. With no +/// argument the directive instructs llvm to try to unroll the loop +/// completely. A positive integer argument can be specified to indicate the +/// number of times the loop should be unrolled. To maximize compatibility with +/// other compilers the unroll count argument can be specified with or without +/// parentheses. +void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + // Incoming token is "unroll" of "#pragma unroll". + Token PragmaName = Tok; + PP.Lex(Tok); + auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; + if (Tok.is(tok::eod)) { + // Unroll pragma without an argument. + Info->PragmaName = PragmaName; + Info->Option = PragmaName; + Info->HasValue = false; + } else { + // Unroll pragma with an argument: "#pragma unroll N" or + // "#pragma unroll(N)". + bool ValueInParens; + if (ParseLoopHintValue(PP, Tok, PragmaName, PragmaName, ValueInParens, + *Info)) + return; + + // In CUDA, the argument to '#pragma unroll' should not be contained in + // parentheses. + if (PP.getLangOpts().CUDA && ValueInParens) + PP.Diag(Info->Value.getLocation(), + diag::warn_pragma_unroll_cuda_value_in_parens); + + PP.Lex(Tok); + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "unroll"; + return; + } + } + + // Generate the hint token. + Token *TokenArray = new Token[1]; + TokenArray[0].startToken(); + TokenArray[0].setKind(tok::annot_pragma_loop_hint); + TokenArray[0].setLocation(PragmaName.getLocation()); + TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); + PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false, + /*OwnsTokens=*/true); +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h deleted file mode 100644 index b41450f..0000000 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.h +++ /dev/null @@ -1,139 +0,0 @@ -//===---- ParserPragmas.h - Language specific pragmas -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines #pragma handlers for language specific pragmas. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_PARSE_PARSEPRAGMA_H -#define LLVM_CLANG_PARSE_PARSEPRAGMA_H - -#include "clang/Lex/Pragma.h" - -namespace clang { - class Sema; - class Parser; - -class PragmaAlignHandler : public PragmaHandler { -public: - explicit PragmaAlignHandler() : PragmaHandler("align") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaGCCVisibilityHandler : public PragmaHandler { -public: - explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaOptionsHandler : public PragmaHandler { -public: - explicit PragmaOptionsHandler() : PragmaHandler("options") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaPackHandler : public PragmaHandler { -public: - explicit PragmaPackHandler() : PragmaHandler("pack") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaMSStructHandler : public PragmaHandler { -public: - explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaUnusedHandler : public PragmaHandler { -public: - PragmaUnusedHandler() : PragmaHandler("unused") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaWeakHandler : public PragmaHandler { -public: - explicit PragmaWeakHandler() : PragmaHandler("weak") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaRedefineExtnameHandler : public PragmaHandler { -public: - explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {} - - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaOpenCLExtensionHandler : public PragmaHandler { -public: - PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {} - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - - -class PragmaFPContractHandler : public PragmaHandler { -public: - PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {} - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaNoOpenMPHandler : public PragmaHandler { -public: - PragmaNoOpenMPHandler() : PragmaHandler("omp") { } - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -class PragmaOpenMPHandler : public PragmaHandler { -public: - PragmaOpenMPHandler() : PragmaHandler("omp") { } - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -}; - -/// PragmaCommentHandler - "\#pragma comment ...". -class PragmaCommentHandler : public PragmaHandler { -public: - PragmaCommentHandler(Sema &Actions) - : PragmaHandler("comment"), Actions(Actions) {} - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -private: - Sema &Actions; -}; - -class PragmaDetectMismatchHandler : public PragmaHandler { -public: - PragmaDetectMismatchHandler(Sema &Actions) - : PragmaHandler("detect_mismatch"), Actions(Actions) {} - virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, - Token &FirstToken); -private: - Sema &Actions; -}; - -} // end namespace clang - -#endif diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index d1f2138..ec0ca6b 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -15,25 +15,14 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" +#include "clang/Basic/Attributes.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/LoopHint.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -112,7 +101,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs, 0, /*MightBeObjCMessageSend*/ true); + MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true); StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts, OnlyStatement, TrailingElseLoc, Attrs); @@ -142,7 +131,7 @@ public: WantCXXNamedCasts = false; } - virtual bool ValidateCandidate(const TypoCorrection &candidate) { + bool ValidateCandidate(const TypoCorrection &candidate) override { if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>()) return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD); if (NextToken.is(tok::equal)) @@ -162,7 +151,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, bool OnlyStatement, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { - const char *SemiError = 0; + const char *SemiError = nullptr; StmtResult Res; // Cases in this switch statement should fall through if the parser expects @@ -284,6 +273,14 @@ Retry: break; } + case tok::kw___if_exists: + case tok::kw___if_not_exists: + ProhibitAttributes(Attrs); + ParseMicrosoftIfExistsStatement(Stmts); + // An __if_exists block is like a compound statement, but it doesn't create + // a new scope. + return StmtEmpty(); + case tok::kw_try: // C++ 15: try-block return ParseCXXTryBlock(); @@ -291,6 +288,11 @@ Retry: ProhibitAttributes(Attrs); // TODO: is it correct? return ParseSEHTryBlock(); + case tok::kw___leave: + Res = ParseSEHLeaveStatement(); + SemiError = "__leave"; + break; + case tok::annot_pragma_vis: ProhibitAttributes(Attrs); HandlePragmaVisibility(); @@ -343,14 +345,25 @@ Retry: case tok::annot_pragma_openmp: ProhibitAttributes(Attrs); - return ParseOpenMPDeclarativeOrExecutableDirective(); + return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement); + + case tok::annot_pragma_ms_pointers_to_members: + ProhibitAttributes(Attrs); + HandlePragmaMSPointersToMembers(); + return StmtEmpty(); + case tok::annot_pragma_ms_pragma: + ProhibitAttributes(Attrs); + HandlePragmaMSPragma(); + return StmtEmpty(); + + case tok::annot_pragma_loop_hint: + ProhibitAttributes(Attrs); + return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs); } // If we reached this code, the statement must end in a semicolon. - if (Tok.is(tok::semi)) { - ConsumeToken(); - } else if (!Res.isInvalid()) { + if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) { // If the result was valid, then we do want to diagnose this. Use // ExpectAndConsume to emit the diagnostic, even though we know it won't // succeed. @@ -411,10 +424,27 @@ StmtResult Parser::ParseSEHTryBlock() { /// seh-finally-block /// StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { - if(Tok.isNot(tok::l_brace)) - return StmtError(Diag(Tok,diag::err_expected_lbrace)); + if (Tok.isNot(tok::l_brace)) + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); + + int SEHTryIndex, SEHTryParentIndex; + StmtResult TryBlock; + { + assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); + + // Enter a scope to hold everything within the compound stmt. Compound + // statements can always hold declarations. + ParseScope CompoundScope(this, Scope::DeclScope | Scope::SEHTryScope); + SEHTryIndex = getCurScope()->getSEHTryIndex(); + SEHTryParentIndex = getCurScope()->getSEHTryParentIndex(); + + // Parse the statements in the body. + TryBlock = ParseCompoundStatementBody(); + } + + //StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, + // Scope::DeclScope | Scope::SEHTryScope)); - StmtResult TryBlock(ParseCompoundStatement()); if(TryBlock.isInvalid()) return TryBlock; @@ -435,8 +465,10 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { return Actions.ActOnSEHTryBlock(false /* IsCXXTry */, TryLoc, - TryBlock.take(), - Handler.take()); + TryBlock.get(), + Handler.get(), + SEHTryIndex, + SEHTryParentIndex); } /// ParseSEHExceptBlock - Handle __except @@ -449,7 +481,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { raii2(Ident___exception_code, false), raii3(Ident_GetExceptionCode, false); - if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen)) + if (ExpectAndConsume(tok::l_paren)) return StmtError(); ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope); @@ -470,7 +502,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { if(FilterExpr.isInvalid()) return StmtError(); - if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen)) + if (ExpectAndConsume(tok::r_paren)) return StmtError(); StmtResult Block(ParseCompoundStatement()); @@ -478,7 +510,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { if(Block.isInvalid()) return Block; - return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.take(), Block.take()); + return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.get(), Block.get()); } /// ParseSEHFinallyBlock - Handle __finally @@ -495,7 +527,17 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) { if(Block.isInvalid()) return Block; - return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.take()); + return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.get()); +} + +/// Handle __leave +/// +/// seh-leave-statement: +/// '__leave' ';' +/// +StmtResult Parser::ParseSEHLeaveStatement() { + SourceLocation LeaveLoc = ConsumeToken(); // eat the '__leave'. + return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope()); } /// ParseLabeledStatement - We have an identifier and a ':' after it. @@ -538,12 +580,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { // can't handle GNU attributes), so only call it in the one case where // GNU attributes are allowed. SubStmt = ParseStatementOrDeclarationAfterAttributes( - Stmts, /*OnlyStmts*/ true, 0, TempAttrs); + Stmts, /*OnlyStmts*/ true, nullptr, TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) SubStmt = Actions.ProcessStmtAttributes( SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); } else { - Diag(Tok, diag::err_expected_semi_after) << "__attribute__"; + Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi; } } @@ -595,13 +637,14 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { // 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. - Stmt *DeepestParsedCaseStmt = 0; + Stmt *DeepestParsedCaseStmt = nullptr; // While we have case statements, eat and stack them. SourceLocation ColonLoc; do { SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() : ConsumeToken(); // eat the 'case'. + ColonLoc = SourceLocation(); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCase(getCurScope()); @@ -614,41 +657,52 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { /// expression. ColonProtectionRAIIObject ColonProtection(*this); - ExprResult LHS(MissingCase ? Expr : ParseConstantExpression()); - MissingCase = false; - if (LHS.isInvalid()) { - SkipUntil(tok::colon, StopAtSemi); - return StmtError(); + ExprResult LHS; + if (!MissingCase) { + LHS = ParseConstantExpression(); + if (LHS.isInvalid()) { + // If constant-expression is parsed unsuccessfully, recover by skipping + // current case statement (moving to the colon that ends it). + if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) { + TryConsumeToken(tok::colon, ColonLoc); + continue; + } + return StmtError(); + } + } else { + LHS = Expr; + MissingCase = false; } // GNU case range extension. SourceLocation DotDotDotLoc; ExprResult RHS; - if (Tok.is(tok::ellipsis)) { - Diag(Tok, diag::ext_gnu_case_range); - DotDotDotLoc = ConsumeToken(); - + if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) { + Diag(DotDotDotLoc, diag::ext_gnu_case_range); RHS = ParseConstantExpression(); if (RHS.isInvalid()) { - SkipUntil(tok::colon, StopAtSemi); + if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) { + TryConsumeToken(tok::colon, ColonLoc); + continue; + } return StmtError(); } } ColonProtection.restore(); - if (Tok.is(tok::colon)) { - ColonLoc = ConsumeToken(); - - // Treat "case blah;" as a typo for "case blah:". - } else if (Tok.is(tok::semi)) { - ColonLoc = ConsumeToken(); - Diag(ColonLoc, diag::err_expected_colon_after) << "'case'" - << FixItHint::CreateReplacement(ColonLoc, ":"); + if (TryConsumeToken(tok::colon, ColonLoc)) { + } else if (TryConsumeToken(tok::semi, ColonLoc) || + TryConsumeToken(tok::coloncolon, ColonLoc)) { + // Treat "case blah;" or "case blah::" as a typo for "case blah:". + Diag(ColonLoc, diag::err_expected_after) + << "'case'" << tok::colon + << FixItHint::CreateReplacement(ColonLoc, ":"); } else { SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation); - Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'" - << FixItHint::CreateInsertion(ExpectedLoc, ":"); + Diag(ExpectedLoc, diag::err_expected_after) + << "'case'" << tok::colon + << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } @@ -676,8 +730,6 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { // Handle all case statements. } while (Tok.is(tok::kw_case)); - assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!"); - // If we found a non-case statement, start by parsing it. StmtResult SubStmt; @@ -685,19 +737,23 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { SubStmt = ParseStatement(); } else { // Nicely diagnose the common error "switch (X) { case 4: }", which is - // not valid. - SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); - Diag(AfterColonLoc, diag::err_label_end_of_compound_statement) - << FixItHint::CreateInsertion(AfterColonLoc, " ;"); - SubStmt = true; + // not valid. If ColonLoc doesn't point to a valid text location, there was + // another parsing error, so avoid producing extra diagnostics. + if (ColonLoc.isValid()) { + SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); + Diag(AfterColonLoc, diag::err_label_end_of_compound_statement) + << FixItHint::CreateInsertion(AfterColonLoc, " ;"); + } + SubStmt = StmtError(); } - // Broken sub-stmt shouldn't prevent forming the case statement properly. - if (SubStmt.isInvalid()) - SubStmt = Actions.ActOnNullStmt(SourceLocation()); - // Install the body into the most deeply-nested case. - Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); + if (DeepestParsedCaseStmt) { + // Broken sub-stmt shouldn't prevent forming the case statement properly. + if (SubStmt.isInvalid()) + SubStmt = Actions.ActOnNullStmt(SourceLocation()); + Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); + } // Return the top level parsed statement tree. return TopLevelCase; @@ -713,18 +769,17 @@ StmtResult Parser::ParseDefaultStatement() { SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'. SourceLocation ColonLoc; - if (Tok.is(tok::colon)) { - ColonLoc = ConsumeToken(); - - // Treat "default;" as a typo for "default:". - } else if (Tok.is(tok::semi)) { - ColonLoc = ConsumeToken(); - Diag(ColonLoc, diag::err_expected_colon_after) << "'default'" - << FixItHint::CreateReplacement(ColonLoc, ":"); + if (TryConsumeToken(tok::colon, ColonLoc)) { + } else if (TryConsumeToken(tok::semi, ColonLoc)) { + // Treat "default;" as a typo for "default:". + Diag(ColonLoc, diag::err_expected_after) + << "'default'" << tok::colon + << FixItHint::CreateReplacement(ColonLoc, ":"); } else { SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation); - Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'" - << FixItHint::CreateInsertion(ExpectedLoc, ":"); + Diag(ExpectedLoc, diag::err_expected_after) + << "'default'" << tok::colon + << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } @@ -767,7 +822,6 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { /// declaration /// [GNU] '__extension__' declaration /// statement -/// [OMP] openmp-directive [TODO] /// /// [GNU] label-declarations: /// [GNU] label-declaration @@ -776,10 +830,6 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { /// [GNU] label-declaration: /// [GNU] '__label__' identifier-list ';' /// -/// [OMP] openmp-directive: [TODO] -/// [OMP] barrier-directive -/// [OMP] flush-directive -/// StmtResult Parser::ParseCompoundStatement(bool isStmtExpr, unsigned ScopeFlags) { assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); @@ -826,6 +876,12 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); break; + case tok::annot_pragma_ms_pointers_to_members: + HandlePragmaMSPointersToMembers(); + break; + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + break; default: checkForPragmas = false; break; @@ -867,7 +923,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { SmallVector<Decl *, 8> DeclsInGroup; while (1) { if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; break; } @@ -875,9 +931,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { SourceLocation IdLoc = ConsumeToken(); DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc)); - if (!Tok.is(tok::comma)) + if (!TryConsumeToken(tok::comma)) break; - ConsumeToken(); } DeclSpec DS(AttrFactory); @@ -887,21 +942,15 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ExpectAndConsumeSemi(diag::err_expected_semi_declaration); if (R.isUsable()) - Stmts.push_back(R.release()); + Stmts.push_back(R.get()); } - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { if (Tok.is(tok::annot_pragma_unused)) { HandlePragmaUnused(); continue; } - if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) || - Tok.is(tok::kw___if_not_exists))) { - ParseMicrosoftIfExistsStatement(Stmts); - continue; - } - StmtResult R; if (Tok.isNot(tok::kw___extension__)) { R = ParseStatementOrDeclaration(Stmts, false); @@ -915,7 +964,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ConsumeToken(); ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs, 0, /*MightBeObjCMessageSend*/ true); + MaybeParseCXX11Attributes(attrs, nullptr, + /*MightBeObjCMessageSend*/ true); // If this is the start of a declaration, parse it as such. if (isDeclarationStatement()) { @@ -946,7 +996,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { } if (R.isUsable()) - Stmts.push_back(R.release()); + Stmts.push_back(R.get()); } SourceLocation CloseLoc = Tok.getLocation(); @@ -983,7 +1033,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); else { ExprResult = ParseExpression(); - DeclResult = 0; + DeclResult = nullptr; // If required, convert to a boolean value. if (!ExprResult.isInvalid() && ConvertToBoolean) @@ -1053,7 +1103,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // Parse the condition. ExprResult CondExp; - Decl *CondVar = 0; + Decl *CondVar = nullptr; if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) return StmtError(); @@ -1077,8 +1127,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // would have to notify ParseStatement not to create a new scope. It's // simpler to let it create a new scope. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the 'then' stmt. SourceLocation ThenStmtLoc = Tok.getLocation(); @@ -1110,8 +1159,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // The substatement in a selection-statement (each substatement, in the else // form of the if statement) implicitly defines a local scope. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); ElseStmt = ParseStatement(); @@ -1131,8 +1179,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // make turn the invalid one into a null stmt to avoid dropping the other // part. If both are invalid, return error. if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) || - (ThenStmt.isInvalid() && ElseStmt.get() == 0) || - (ThenStmt.get() == 0 && ElseStmt.isInvalid())) { + (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) || + (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) { // Both invalid, or one is invalid and other is non-present: return error. return StmtError(); } @@ -1175,14 +1223,14 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { // while, for, and switch statements are local to the if, while, for, or // switch statement (including the controlled statement). // - unsigned ScopeFlags = Scope::BreakScope | Scope::SwitchScope; + unsigned ScopeFlags = Scope::SwitchScope; if (C99orCXX) ScopeFlags |= Scope::DeclScope | Scope::ControlScope; ParseScope SwitchScope(this, ScopeFlags); // Parse the condition. ExprResult Cond; - Decl *CondVar = 0; + Decl *CondVar = nullptr; if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false)) return StmtError(); @@ -1213,8 +1261,13 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { // See comments in ParseIfStatement for why we create a scope for the // condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + getCurScope()->AddFlags(Scope::BreakScope); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); + + // We have incremented the mangling number for the SwitchScope and the + // InnerScope, which is one too many. + if (C99orCXX) + getCurScope()->decrementMSLocalManglingNumber(); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1223,15 +1276,6 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { InnerScope.Exit(); SwitchScope.Exit(); - if (Body.isInvalid()) { - // FIXME: Remove the case statement list from the Switch statement. - - // Put the synthesized null statement on the same line as the end of switch - // condition. - SourceLocation SynthesizedNullStmtLocation = Cond.get()->getLocEnd(); - Body = Actions.ActOnNullStmt(SynthesizedNullStmtLocation); - } - return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get()); } @@ -1274,13 +1318,13 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { // Parse the condition. ExprResult Cond; - Decl *CondVar = 0; + Decl *CondVar = nullptr; if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) return StmtError(); FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); - // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if + // C99 6.8.5p5 - In C99, the body of the while 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. // @@ -1291,8 +1335,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { // See comments in ParseIfStatement for why we create a scope for the // condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1325,7 +1368,7 @@ StmtResult Parser::ParseDoStatement() { ParseScope DoScope(this, ScopeFlags); - // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if + // C99 6.8.5p5 - In C99, the body of the do 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. // @@ -1333,9 +1376,8 @@ StmtResult Parser::ParseDoStatement() { // The substatement in an iteration-statement implicitly defines a local scope // which is entered and exited each time through the loop. // - ParseScope InnerScope(this, Scope::DeclScope, - (getLangOpts().C99 || getLangOpts().CPlusPlus) && - Tok.isNot(tok::l_brace)); + bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement()); @@ -1346,7 +1388,7 @@ StmtResult Parser::ParseDoStatement() { if (Tok.isNot(tok::kw_while)) { if (!Body.isInvalid()) { Diag(Tok, diag::err_expected_while); - Diag(DoLoc, diag::note_matching) << "do"; + Diag(DoLoc, diag::note_matching) << "'do'"; SkipUntil(tok::semi, StopBeforeMatch); } return StmtError(); @@ -1377,6 +1419,25 @@ StmtResult Parser::ParseDoStatement() { Cond.get(), T.getCloseLocation()); } +bool Parser::isForRangeIdentifier() { + assert(Tok.is(tok::identifier)); + + const Token &Next = NextToken(); + if (Next.is(tok::colon)) + return true; + + if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) { + TentativeParsingAction PA(*this); + ConsumeToken(); + SkipCXX11Attributes(); + bool Result = Tok.is(tok::colon); + PA.Revert(); + return Result; + } + + return false; +} + /// ParseForStatement /// for-statement: [C99 6.8.5.3] /// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement @@ -1424,12 +1485,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Names declared in the for-init-statement are in the same declarative-region // as those declared in the condition. // - unsigned ScopeFlags; + unsigned ScopeFlags = 0; if (C99orCXXorObjC) - ScopeFlags = Scope::BreakScope | Scope::ContinueScope | - Scope::DeclScope | Scope::ControlScope; - else - ScopeFlags = Scope::BreakScope | Scope::ContinueScope; + ScopeFlags = Scope::DeclScope | Scope::ControlScope; ParseScope ForScope(this, ScopeFlags); @@ -1445,7 +1503,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ExprResult Collection; ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); - Decl *SecondVar = 0; + Decl *SecondVar = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), @@ -1463,6 +1521,29 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ProhibitAttributes(attrs); // no first part, eat the ';'. ConsumeToken(); + } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) && + isForRangeIdentifier()) { + ProhibitAttributes(attrs); + IdentifierInfo *Name = Tok.getIdentifierInfo(); + SourceLocation Loc = ConsumeToken(); + MaybeParseCXX11Attributes(attrs); + + ForRangeInit.ColonLoc = ConsumeToken(); + if (Tok.is(tok::l_brace)) + ForRangeInit.RangeExpr = ParseBraceInitializer(); + else + ForRangeInit.RangeExpr = ParseExpression(); + + Diag(Loc, getLangOpts().CPlusPlus1z + ? diag::warn_cxx1y_compat_for_range_identifier + : diag::ext_for_range_identifier) + << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus1z) + ? FixItHint::CreateInsertion(Loc, "auto &&") + : FixItHint()); + + FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, + attrs, attrs.Range.getEnd()); + ForRange = true; } else if (isForInitDeclaration()) { // for (int X = 4; // Parse declaration, which eats the ';'. if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? @@ -1474,12 +1555,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; StmtVector Stmts; - DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, - DeclEnd, attrs, false, - MightBeForRangeStmt ? - &ForRangeInit : 0); + DeclGroupPtrTy DG = ParseSimpleDeclaration( + Stmts, Declarator::ForContext, DeclEnd, attrs, false, + MightBeForRangeStmt ? &ForRangeInit : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - if (ForRangeInit.ParsedForRangeDecl()) { Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_for_range : diag::ext_for_range); @@ -1544,6 +1623,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { } } } + + // Parse the second part of the for specifier. + getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); if (!ForEach && !ForRange) { assert(!SecondPart.get() && "Shouldn't have a second expression yet."); // Parse the second part of the for specifier. @@ -1582,7 +1664,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ExprResult Third = ParseExpression(); // FIXME: The C++11 standard doesn't actually say that this is a // discarded-value expression, but it clearly should be. - ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.take()); + ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get()); } } // Match the ')'. @@ -1595,7 +1677,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { StmtResult ForEachStmt; if (ForRange) { - ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.take(), + ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.get(), ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), T.getCloseLocation(), @@ -1606,12 +1688,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // statement immediately in order to close over temporaries correctly. } else if (ForEach) { ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc, - FirstPart.take(), - Collection.take(), + FirstPart.get(), + Collection.get(), T.getCloseLocation()); } - // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if + // C99 6.8.5p5 - In C99, the body of the for 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. // @@ -1622,8 +1704,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // See comments in ParseIfStatement for why we create a scope for // for-init-statement/condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXXorObjC && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC, + Tok.is(tok::l_brace)); + + // The body of the for loop has the same local mangling number as the + // for-init-statement. + // It will only be incremented if the body contains other things that would + // normally increment the mangling number (like a compound statement). + if (C99orCXXorObjC) + getCurScope()->decrementMSLocalManglingNumber(); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1638,15 +1727,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); if (ForEach) - return Actions.FinishObjCForCollectionStmt(ForEachStmt.take(), - Body.take()); + return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), + Body.get()); if (ForRange) - return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); + return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); - return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.take(), + return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), SecondPart, SecondVar, ThirdPart, - T.getCloseLocation(), Body.take()); + T.getCloseLocation(), Body.get()); } /// ParseGotoStatement @@ -1675,9 +1764,9 @@ StmtResult Parser::ParseGotoStatement() { SkipUntil(tok::semi, StopBeforeMatch); return StmtError(); } - Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take()); + Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.get()); } else { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; return StmtError(); } @@ -1730,713 +1819,40 @@ StmtResult Parser::ParseReturnStatement() { << R.get()->getSourceRange(); } else R = ParseExpression(); - if (R.isInvalid()) { // Skip to the semicolon, but don't consume it. - SkipUntil(tok::semi, StopBeforeMatch); + if (R.isInvalid()) { + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); return StmtError(); } } - return Actions.ActOnReturnStmt(ReturnLoc, R.take()); -} - -namespace { - class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback { - Parser &TheParser; - SourceLocation AsmLoc; - StringRef AsmString; - - /// The tokens we streamed into AsmString and handed off to MC. - ArrayRef<Token> AsmToks; - - /// The offset of each token in AsmToks within AsmString. - ArrayRef<unsigned> AsmTokOffsets; - - public: - ClangAsmParserCallback(Parser &P, SourceLocation Loc, - StringRef AsmString, - ArrayRef<Token> Toks, - ArrayRef<unsigned> Offsets) - : TheParser(P), AsmLoc(Loc), AsmString(AsmString), - AsmToks(Toks), AsmTokOffsets(Offsets) { - assert(AsmToks.size() == AsmTokOffsets.size()); - } - - void *LookupInlineAsmIdentifier(StringRef &LineBuf, - InlineAsmIdentifierInfo &Info, - bool IsUnevaluatedContext) { - // Collect the desired tokens. - SmallVector<Token, 16> LineToks; - const Token *FirstOrigToken = 0; - findTokensForString(LineBuf, LineToks, FirstOrigToken); - - unsigned NumConsumedToks; - ExprResult Result = - TheParser.ParseMSAsmIdentifier(LineToks, NumConsumedToks, &Info, - IsUnevaluatedContext); - - // If we consumed the entire line, tell MC that. - // Also do this if we consumed nothing as a way of reporting failure. - if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) { - // By not modifying LineBuf, we're implicitly consuming it all. - - // Otherwise, consume up to the original tokens. - } else { - assert(FirstOrigToken && "not using original tokens?"); - - // Since we're using original tokens, apply that offset. - assert(FirstOrigToken[NumConsumedToks].getLocation() - == LineToks[NumConsumedToks].getLocation()); - unsigned FirstIndex = FirstOrigToken - AsmToks.begin(); - unsigned LastIndex = FirstIndex + NumConsumedToks - 1; - - // The total length we've consumed is the relative offset - // of the last token we consumed plus its length. - unsigned TotalOffset = (AsmTokOffsets[LastIndex] - + AsmToks[LastIndex].getLength() - - AsmTokOffsets[FirstIndex]); - LineBuf = LineBuf.substr(0, TotalOffset); - } - - // Initialize the "decl" with the lookup result. - Info.OpDecl = static_cast<void*>(Result.take()); - return Info.OpDecl; - } - - bool LookupInlineAsmField(StringRef Base, StringRef Member, - unsigned &Offset) { - return TheParser.getActions().LookupInlineAsmField(Base, Member, - Offset, AsmLoc); - } - - static void DiagHandlerCallback(const llvm::SMDiagnostic &D, - void *Context) { - ((ClangAsmParserCallback*) Context)->handleDiagnostic(D); - } - - private: - /// Collect the appropriate tokens for the given string. - void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks, - const Token *&FirstOrigToken) const { - // For now, assert that the string we're working with is a substring - // of what we gave to MC. This lets us use the original tokens. - assert(!std::less<const char*>()(Str.begin(), AsmString.begin()) && - !std::less<const char*>()(AsmString.end(), Str.end())); - - // Try to find a token whose offset matches the first token. - unsigned FirstCharOffset = Str.begin() - AsmString.begin(); - const unsigned *FirstTokOffset - = std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), - FirstCharOffset); - - // For now, assert that the start of the string exactly - // corresponds to the start of a token. - assert(*FirstTokOffset == FirstCharOffset); - - // Use all the original tokens for this line. (We assume the - // end of the line corresponds cleanly to a token break.) - unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin(); - FirstOrigToken = &AsmToks[FirstTokIndex]; - unsigned LastCharOffset = Str.end() - AsmString.begin(); - for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) { - if (AsmTokOffsets[i] >= LastCharOffset) break; - TempToks.push_back(AsmToks[i]); - } - } - - void handleDiagnostic(const llvm::SMDiagnostic &D) { - // Compute an offset into the inline asm buffer. - // FIXME: This isn't right if .macro is involved (but hopefully, no - // real-world code does that). - const llvm::SourceMgr &LSM = *D.getSourceMgr(); - const llvm::MemoryBuffer *LBuf = - LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); - - // Figure out which token that offset points into. - const unsigned *TokOffsetPtr = - std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset); - unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin(); - unsigned TokOffset = *TokOffsetPtr; - - // If we come up with an answer which seems sane, use it; otherwise, - // just point at the __asm keyword. - // FIXME: Assert the answer is sane once we handle .macro correctly. - SourceLocation Loc = AsmLoc; - if (TokIndex < AsmToks.size()) { - const Token &Tok = AsmToks[TokIndex]; - Loc = Tok.getLocation(); - Loc = Loc.getLocWithOffset(Offset - TokOffset); - } - TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) - << D.getMessage(); - } - }; -} - -/// Parse an identifier in an MS-style inline assembly block. -/// -/// \param CastInfo - a void* so that we don't have to teach Parser.h -/// about the actual type. -ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, - unsigned &NumLineToksConsumed, - void *CastInfo, - bool IsUnevaluatedContext) { - llvm::InlineAsmIdentifierInfo &Info = - *(llvm::InlineAsmIdentifierInfo *) CastInfo; - - // Push a fake token on the end so that we don't overrun the token - // stream. We use ';' because it expression-parsing should never - // overrun it. - const tok::TokenKind EndOfStream = tok::semi; - Token EndOfStreamTok; - EndOfStreamTok.startToken(); - EndOfStreamTok.setKind(EndOfStream); - LineToks.push_back(EndOfStreamTok); - - // Also copy the current token over. - LineToks.push_back(Tok); - - PP.EnterTokenStream(LineToks.begin(), - LineToks.size(), - /*disable macros*/ true, - /*owns tokens*/ false); - - // Clear the current token and advance to the first token in LineToks. - ConsumeAnyToken(); - - // Parse an optional scope-specifier if we're in C++. - CXXScopeSpec SS; - if (getLangOpts().CPlusPlus) { - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); - } - - // Require an identifier here. - SourceLocation TemplateKWLoc; - UnqualifiedId Id; - bool Invalid = ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/false, - /*AllowConstructorName=*/false, - /*ObjectType=*/ ParsedType(), - TemplateKWLoc, - Id); - - // If we've run into the poison token we inserted before, or there - // was a parsing error, then claim the entire line. - if (Invalid || Tok.is(EndOfStream)) { - NumLineToksConsumed = LineToks.size() - 2; - - // Otherwise, claim up to the start of the next token. - } else { - // Figure out how many tokens we are into LineToks. - unsigned LineIndex = 0; - while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { - LineIndex++; - assert(LineIndex < LineToks.size() - 2); // we added two extra tokens - } - - NumLineToksConsumed = LineIndex; - } - - // Finally, restore the old parsing state by consuming all the - // tokens we staged before, implicitly killing off the - // token-lexer we pushed. - for (unsigned n = LineToks.size() - 2 - NumLineToksConsumed; n != 0; --n) { - ConsumeAnyToken(); - } - ConsumeToken(EndOfStream); - - // Leave LineToks in its original state. - LineToks.pop_back(); - LineToks.pop_back(); - - // Perform the lookup. - return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, - IsUnevaluatedContext); + return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope()); } -/// Turn a sequence of our tokens back into a string that we can hand -/// to the MC asm parser. -static bool buildMSAsmString(Preprocessor &PP, - SourceLocation AsmLoc, - ArrayRef<Token> AsmToks, - SmallVectorImpl<unsigned> &TokOffsets, - SmallString<512> &Asm) { - assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); - - // Is this the start of a new assembly statement? - bool isNewStatement = true; - - for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { - const Token &Tok = AsmToks[i]; - - // Start each new statement with a newline and a tab. - if (!isNewStatement && - (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) { - Asm += "\n\t"; - isNewStatement = true; - } - - // Preserve the existence of leading whitespace except at the - // start of a statement. - if (!isNewStatement && Tok.hasLeadingSpace()) - Asm += ' '; +StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, + SourceLocation *TrailingElseLoc, + ParsedAttributesWithRange &Attrs) { + // Create temporary attribute list. + ParsedAttributesWithRange TempAttrs(AttrFactory); - // Remember the offset of this token. - TokOffsets.push_back(Asm.size()); - - // Don't actually write '__asm' into the assembly stream. - if (Tok.is(tok::kw_asm)) { - // Complain about __asm at the end of the stream. - if (i + 1 == e) { - PP.Diag(AsmLoc, diag::err_asm_empty); - return true; - } - - continue; - } - - // Append the spelling of the token. - SmallString<32> SpellingBuffer; - bool SpellingInvalid = false; - Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid); - assert(!SpellingInvalid && "spelling was invalid after correct parse?"); - - // We are no longer at the start of a statement. - isNewStatement = false; - } - - // Ensure that the buffer is null-terminated. - Asm.push_back('\0'); - Asm.pop_back(); - - assert(TokOffsets.size() == AsmToks.size()); - return false; -} - -/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, -/// this routine is called to collect the tokens for an MS asm statement. -/// -/// [MS] ms-asm-statement: -/// 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] ms-asm-instruction-block -/// ms-asm-line -/// ms-asm-line '\n' ms-asm-instruction-block -/// -StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { - SourceManager &SrcMgr = PP.getSourceManager(); - SourceLocation EndLoc = AsmLoc; - SmallVector<Token, 4> AsmToks; - - 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(); - do { - // If we hit EOF, we're done, period. - if (Tok.is(tok::eof)) - 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; - } - } - if (!InAsmComment && InBraces && Tok.is(tok::r_brace) && - BraceCount == (savedBraceCount + 1)) { - // Consume the closing brace, and finish - EndLoc = ConsumeBrace(); - break; - } - - // Consume the next token; make sure we don't modify the brace count etc. - // if we are in a comment. - EndLoc = TokLoc; - if (InAsmComment) - PP.Lex(Tok); - else { - AsmToks.push_back(Tok); - ConsumeAnyToken(); - } - TokLoc = Tok.getLocation(); - ++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(); - } - - // Okay, prepare to use MC to parse the assembly. - SmallVector<StringRef, 4> ConstraintRefs; - SmallVector<Expr*, 4> Exprs; - SmallVector<StringRef, 4> ClobberRefs; - - // We need an actual supported target. - llvm::Triple TheTriple = Actions.Context.getTargetInfo().getTriple(); - llvm::Triple::ArchType ArchTy = TheTriple.getArch(); - const std::string &TT = TheTriple.getTriple(); - const llvm::Target *TheTarget = 0; - bool UnsupportedArch = (ArchTy != llvm::Triple::x86 && - ArchTy != llvm::Triple::x86_64); - if (UnsupportedArch) { - Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); - } else { - std::string Error; - TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error); - if (!TheTarget) - Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error; - } - - // If we don't support assembly, or the assembly is empty, we don't - // need to instantiate the AsmParser, etc. - if (!TheTarget || AsmToks.empty()) { - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, StringRef(), - /*NumOutputs*/ 0, /*NumInputs*/ 0, - ConstraintRefs, ClobberRefs, Exprs, EndLoc); - } - - // Expand the tokens into a string buffer. - SmallString<512> AsmString; - SmallVector<unsigned, 8> TokOffsets; - if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString)) - return StmtError(); - - OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); - OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); - // Get the instruction descriptor. - const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); - OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); - OwningPtr<llvm::MCSubtargetInfo> - STI(TheTarget->createMCSubtargetInfo(TT, "", "")); - - llvm::SourceMgr TempSrcMgr; - llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); - llvm::MemoryBuffer *Buffer = - llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); - - // Tell SrcMgr about this buffer, which is what the parser will pick up. - TempSrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); - - OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); - OwningPtr<llvm::MCAsmParser> - Parser(createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI)); - OwningPtr<llvm::MCTargetAsmParser> - TargetParser(TheTarget->createMCAsmParser(*STI, *Parser, *MII)); - - llvm::MCInstPrinter *IP = - TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); - - // Change to the Intel dialect. - Parser->setAssemblerDialect(1); - Parser->setTargetParser(*TargetParser.get()); - Parser->setParsingInlineAsm(true); - TargetParser->setParsingInlineAsm(true); - - ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, - AsmToks, TokOffsets); - TargetParser->setSemaCallback(&Callback); - TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback, - &Callback); - - unsigned NumOutputs; - unsigned NumInputs; - std::string AsmStringIR; - SmallVector<std::pair<void *, bool>, 4> OpExprs; - SmallVector<std::string, 4> Constraints; - SmallVector<std::string, 4> Clobbers; - if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, - NumOutputs, NumInputs, OpExprs, Constraints, - Clobbers, MII, IP, Callback)) - return StmtError(); - - // Build the vector of clobber StringRefs. - unsigned NumClobbers = Clobbers.size(); - ClobberRefs.resize(NumClobbers); - for (unsigned i = 0; i != NumClobbers; ++i) - ClobberRefs[i] = StringRef(Clobbers[i]); - - // Recast the void pointers and build the vector of constraint StringRefs. - unsigned NumExprs = NumOutputs + NumInputs; - ConstraintRefs.resize(NumExprs); - Exprs.resize(NumExprs); - for (unsigned i = 0, e = NumExprs; i != e; ++i) { - Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first); - if (!OpExpr) - return StmtError(); - - // Need address of variable. - if (OpExprs[i].second) - OpExpr = Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr) - .take(); - - ConstraintRefs[i] = StringRef(Constraints[i]); - Exprs[i] = OpExpr; - } - - // FIXME: We should be passing source locations for better diagnostics. - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, AsmStringIR, - NumOutputs, NumInputs, - ConstraintRefs, ClobberRefs, Exprs, EndLoc); -} - -/// ParseAsmStatement - Parse a GNU extended asm statement. -/// asm-statement: -/// gnu-asm-statement -/// ms-asm-statement -/// -/// [GNU] gnu-asm-statement: -/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';' -/// -/// [GNU] asm-argument: -/// asm-string-literal -/// asm-string-literal ':' asm-operands[opt] -/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] -/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] -/// ':' asm-clobbers -/// -/// [GNU] asm-clobbers: -/// asm-string-literal -/// asm-clobbers ',' asm-string-literal -/// -StmtResult Parser::ParseAsmStatement(bool &msAsm) { - assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); - SourceLocation AsmLoc = ConsumeToken(); - - if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) && - !isTypeQualifier()) { - msAsm = true; - return ParseMicrosoftAsmStatement(AsmLoc); - } - DeclSpec DS(AttrFactory); - SourceLocation Loc = Tok.getLocation(); - ParseTypeQualifierListOpt(DS, true, false); - - // GNU asms accept, but warn, about type-qualifiers other than volatile. - if (DS.getTypeQualifiers() & DeclSpec::TQ_const) - Diag(Loc, diag::w_asm_qualifier_ignored) << "const"; - if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) - Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict"; - // FIXME: Once GCC supports _Atomic, check whether it permits it here. - if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) - Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic"; - - // Remember if this was a volatile asm. - bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; - if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen_after) << "asm"; - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - BalancedDelimiterTracker T(*this, tok::l_paren); - T.consumeOpen(); - - ExprResult AsmString(ParseAsmStringLiteral()); - if (AsmString.isInvalid()) { - // Consume up to and including the closing paren. - T.skipToEnd(); - return StmtError(); - } - - SmallVector<IdentifierInfo *, 4> Names; - ExprVector Constraints; - ExprVector Exprs; - ExprVector Clobbers; - - if (Tok.is(tok::r_paren)) { - // We have a simple asm expression like 'asm("foo")'. - T.consumeClose(); - return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, - /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, - Constraints, Exprs, AsmString.take(), - Clobbers, T.getCloseLocation()); - } - - // Parse Outputs, if present. - bool AteExtraColon = false; - if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { - // In C++ mode, parse "::" like ": :". - AteExtraColon = Tok.is(tok::coloncolon); + // Get loop hints and consume annotated token. + while (Tok.is(tok::annot_pragma_loop_hint)) { + LoopHint Hint = HandlePragmaLoopHint(); ConsumeToken(); - if (!AteExtraColon && - ParseAsmOperandsOpt(Names, Constraints, Exprs)) - return StmtError(); + ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.ValueLoc, + ArgsUnion(Hint.ValueExpr)}; + TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr, + Hint.PragmaNameLoc->Loc, ArgHints, 4, + AttributeList::AS_Pragma); } - unsigned NumOutputs = Names.size(); - - // Parse Inputs, if present. - if (AteExtraColon || - Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { - // In C++ mode, parse "::" like ": :". - if (AteExtraColon) - AteExtraColon = false; - else { - AteExtraColon = Tok.is(tok::coloncolon); - ConsumeToken(); - } + // Get the next statement. + MaybeParseCXX11Attributes(Attrs); - if (!AteExtraColon && - ParseAsmOperandsOpt(Names, Constraints, Exprs)) - return StmtError(); - } - - assert(Names.size() == Constraints.size() && - Constraints.size() == Exprs.size() && - "Input operand size mismatch!"); - - unsigned NumInputs = Names.size() - NumOutputs; - - // Parse the clobbers, if present. - if (AteExtraColon || Tok.is(tok::colon)) { - if (!AteExtraColon) - ConsumeToken(); - - // Parse the asm-string list for clobbers if present. - if (Tok.isNot(tok::r_paren)) { - while (1) { - ExprResult Clobber(ParseAsmStringLiteral()); - - if (Clobber.isInvalid()) - break; - - Clobbers.push_back(Clobber.release()); - - if (Tok.isNot(tok::comma)) break; - ConsumeToken(); - } - } - } + StmtResult S = ParseStatementOrDeclarationAfterAttributes( + Stmts, OnlyStatement, TrailingElseLoc, Attrs); - T.consumeClose(); - return Actions.ActOnGCCAsmStmt(AsmLoc, false, isVolatile, NumOutputs, - NumInputs, Names.data(), Constraints, Exprs, - AsmString.take(), Clobbers, - T.getCloseLocation()); -} - -/// ParseAsmOperands - Parse the asm-operands production as used by -/// asm-statement, assuming the leading ':' token was eaten. -/// -/// [GNU] asm-operands: -/// asm-operand -/// asm-operands ',' asm-operand -/// -/// [GNU] asm-operand: -/// asm-string-literal '(' expression ')' -/// '[' identifier ']' asm-string-literal '(' expression ')' -/// -// -// FIXME: Avoid unnecessary std::string trashing. -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; - - while (1) { - // Read the [id] if present. - if (Tok.is(tok::l_square)) { - BalancedDelimiterTracker T(*this, tok::l_square); - T.consumeOpen(); - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - - IdentifierInfo *II = Tok.getIdentifierInfo(); - ConsumeToken(); - - Names.push_back(II); - T.consumeClose(); - } else - Names.push_back(0); - - ExprResult Constraint(ParseAsmStringLiteral()); - if (Constraint.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - Constraints.push_back(Constraint.release()); - - if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen_after) << "asm operand"; - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - - // Read the parenthesized expression. - BalancedDelimiterTracker T(*this, tok::l_paren); - T.consumeOpen(); - ExprResult Res(ParseExpression()); - T.consumeClose(); - if (Res.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - Exprs.push_back(Res.release()); - // Eat the comma and continue parsing if it exists. - if (Tok.isNot(tok::comma)) return false; - ConsumeToken(); - } + Attrs.takeAllFrom(TempAttrs); + return S; } Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { @@ -2464,7 +1880,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { } BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); + return Actions.ActOnFinishFunctionBody(Decl, FnBody.get()); } /// ParseFunctionTryBlock - Parse a C++ function-try-block. @@ -2501,7 +1917,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { } BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); + return Actions.ActOnFinishFunctionBody(Decl, FnBody.get()); } bool Parser::trySkippingFunctionBody() { @@ -2554,16 +1970,28 @@ StmtResult Parser::ParseCXXTryBlock() { /// /// [Borland] try-block: /// 'try' compound-statement seh-except-block -/// 'try' compound-statment seh-finally-block +/// 'try' compound-statement seh-finally-block /// StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { if (Tok.isNot(tok::l_brace)) - return StmtError(Diag(Tok, diag::err_expected_lbrace)); + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); // FIXME: Possible draft standard bug: attribute-specifier should be allowed? - StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, - Scope::DeclScope | Scope::TryScope | - (FnTry ? Scope::FnTryCatchScope : 0))); + int SEHTryIndex, SEHTryParentIndex; + StmtResult TryBlock; + { + assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); + + // Enter a scope to hold everything within the compound stmt. Compound + // statements can always hold declarations. + ParseScope CompoundScope(this, Scope::DeclScope | Scope::TryScope | + (FnTry ? Scope::FnTryCatchScope : 0)); + SEHTryIndex = getCurScope()->getSEHTryIndex(); + SEHTryParentIndex = getCurScope()->getSEHTryParentIndex(); + + // Parse the statements in the body. + TryBlock = ParseCompoundStatementBody(); + } if (TryBlock.isInvalid()) return TryBlock; @@ -2587,8 +2015,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { return Actions.ActOnSEHTryBlock(true /* IsCXXTry */, TryLoc, - TryBlock.take(), - Handler.take()); + TryBlock.get(), + Handler.get(), + SEHTryIndex, + SEHTryParentIndex); } else { StmtVector Handlers; @@ -2602,14 +2032,14 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { while (Tok.is(tok::kw_catch)) { StmtResult Handler(ParseCXXCatchBlock(FnTry)); if (!Handler.isInvalid()) - Handlers.push_back(Handler.release()); + Handlers.push_back(Handler.get()); } // Don't bother creating the full statement if we don't have any usable // handlers. if (Handlers.empty()) return StmtError(); - return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), Handlers); + return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers); } } @@ -2629,7 +2059,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { SourceLocation CatchLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return StmtError(); // C++ 3.3.2p3: @@ -2640,7 +2070,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { // exception-declaration is equivalent to '...' or a parameter-declaration // without default arguments. - Decl *ExceptionDecl = 0; + Decl *ExceptionDecl = nullptr; if (Tok.isNot(tok::ellipsis)) { ParsedAttributesWithRange Attributes(AttrFactory); MaybeParseCXX11Attributes(Attributes); @@ -2662,14 +2092,14 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { return StmtError(); if (Tok.isNot(tok::l_brace)) - return StmtError(Diag(Tok, diag::err_expected_lbrace)); + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); // FIXME: Possible draft standard bug: attribute-specifier should be allowed? StmtResult Block(ParseCompoundStatement()); if (Block.isInvalid()) return Block; - return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take()); + return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.get()); } void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { @@ -2683,7 +2113,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { // inside these braces escaping to the surrounding code. if (Result.Behavior == IEB_Dependent) { if (!Tok.is(tok::l_brace)) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return; } @@ -2703,7 +2133,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return; } @@ -2724,7 +2154,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { while (Tok.isNot(tok::r_brace)) { StmtResult R = ParseStatementOrDeclaration(Stmts, false); if (R.isUsable()) - Stmts.push_back(R.release()); + Stmts.push_back(R.get()); } Braces.consumeClose(); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp new file mode 100644 index 0000000..f7e8307 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp @@ -0,0 +1,761 @@ +//===---- ParseStmtAsm.cpp - Assembly Statement Parser --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements parsing for GCC and Microsoft inline assembly. +// +//===----------------------------------------------------------------------===// + +#include "clang/Parse/Parser.h" +#include "RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +using namespace clang; + +namespace { +class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback { + Parser &TheParser; + SourceLocation AsmLoc; + StringRef AsmString; + + /// The tokens we streamed into AsmString and handed off to MC. + ArrayRef<Token> AsmToks; + + /// The offset of each token in AsmToks within AsmString. + ArrayRef<unsigned> AsmTokOffsets; + +public: + ClangAsmParserCallback(Parser &P, SourceLocation Loc, StringRef AsmString, + ArrayRef<Token> Toks, ArrayRef<unsigned> Offsets) + : TheParser(P), AsmLoc(Loc), AsmString(AsmString), AsmToks(Toks), + AsmTokOffsets(Offsets) { + assert(AsmToks.size() == AsmTokOffsets.size()); + } + + void *LookupInlineAsmIdentifier(StringRef &LineBuf, + llvm::InlineAsmIdentifierInfo &Info, + bool IsUnevaluatedContext) override { + // Collect the desired tokens. + SmallVector<Token, 16> LineToks; + const Token *FirstOrigToken = nullptr; + findTokensForString(LineBuf, LineToks, FirstOrigToken); + + unsigned NumConsumedToks; + ExprResult Result = TheParser.ParseMSAsmIdentifier( + LineToks, NumConsumedToks, &Info, IsUnevaluatedContext); + + // If we consumed the entire line, tell MC that. + // Also do this if we consumed nothing as a way of reporting failure. + if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) { + // By not modifying LineBuf, we're implicitly consuming it all. + + // Otherwise, consume up to the original tokens. + } else { + assert(FirstOrigToken && "not using original tokens?"); + + // Since we're using original tokens, apply that offset. + assert(FirstOrigToken[NumConsumedToks].getLocation() == + LineToks[NumConsumedToks].getLocation()); + unsigned FirstIndex = FirstOrigToken - AsmToks.begin(); + unsigned LastIndex = FirstIndex + NumConsumedToks - 1; + + // The total length we've consumed is the relative offset + // of the last token we consumed plus its length. + unsigned TotalOffset = + (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() - + AsmTokOffsets[FirstIndex]); + LineBuf = LineBuf.substr(0, TotalOffset); + } + + // Initialize the "decl" with the lookup result. + Info.OpDecl = static_cast<void *>(Result.get()); + return Info.OpDecl; + } + + bool LookupInlineAsmField(StringRef Base, StringRef Member, + unsigned &Offset) override { + return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset, + AsmLoc); + } + + static void DiagHandlerCallback(const llvm::SMDiagnostic &D, void *Context) { + ((ClangAsmParserCallback *)Context)->handleDiagnostic(D); + } + +private: + /// Collect the appropriate tokens for the given string. + void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks, + const Token *&FirstOrigToken) const { + // For now, assert that the string we're working with is a substring + // of what we gave to MC. This lets us use the original tokens. + assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) && + !std::less<const char *>()(AsmString.end(), Str.end())); + + // Try to find a token whose offset matches the first token. + unsigned FirstCharOffset = Str.begin() - AsmString.begin(); + const unsigned *FirstTokOffset = std::lower_bound( + AsmTokOffsets.begin(), AsmTokOffsets.end(), FirstCharOffset); + + // For now, assert that the start of the string exactly + // corresponds to the start of a token. + assert(*FirstTokOffset == FirstCharOffset); + + // Use all the original tokens for this line. (We assume the + // end of the line corresponds cleanly to a token break.) + unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin(); + FirstOrigToken = &AsmToks[FirstTokIndex]; + unsigned LastCharOffset = Str.end() - AsmString.begin(); + for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) { + if (AsmTokOffsets[i] >= LastCharOffset) + break; + TempToks.push_back(AsmToks[i]); + } + } + + void handleDiagnostic(const llvm::SMDiagnostic &D) { + // Compute an offset into the inline asm buffer. + // FIXME: This isn't right if .macro is involved (but hopefully, no + // real-world code does that). + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + const llvm::MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + + // Figure out which token that offset points into. + const unsigned *TokOffsetPtr = + std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset); + unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin(); + unsigned TokOffset = *TokOffsetPtr; + + // If we come up with an answer which seems sane, use it; otherwise, + // just point at the __asm keyword. + // FIXME: Assert the answer is sane once we handle .macro correctly. + SourceLocation Loc = AsmLoc; + if (TokIndex < AsmToks.size()) { + const Token &Tok = AsmToks[TokIndex]; + Loc = Tok.getLocation(); + Loc = Loc.getLocWithOffset(Offset - TokOffset); + } + TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); + } +}; +} + +/// Parse an identifier in an MS-style inline assembly block. +/// +/// \param CastInfo - a void* so that we don't have to teach Parser.h +/// about the actual type. +ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, + unsigned &NumLineToksConsumed, + void *CastInfo, + bool IsUnevaluatedContext) { + llvm::InlineAsmIdentifierInfo &Info = + *(llvm::InlineAsmIdentifierInfo *)CastInfo; + + // Push a fake token on the end so that we don't overrun the token + // stream. We use ';' because it expression-parsing should never + // overrun it. + const tok::TokenKind EndOfStream = tok::semi; + Token EndOfStreamTok; + EndOfStreamTok.startToken(); + EndOfStreamTok.setKind(EndOfStream); + LineToks.push_back(EndOfStreamTok); + + // Also copy the current token over. + LineToks.push_back(Tok); + + PP.EnterTokenStream(LineToks.begin(), LineToks.size(), + /*disable macros*/ true, + /*owns tokens*/ false); + + // Clear the current token and advance to the first token in LineToks. + ConsumeAnyToken(); + + // Parse an optional scope-specifier if we're in C++. + CXXScopeSpec SS; + if (getLangOpts().CPlusPlus) { + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + } + + // Require an identifier here. + SourceLocation TemplateKWLoc; + UnqualifiedId Id; + bool Invalid = + ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*ObjectType=*/ParsedType(), TemplateKWLoc, Id); + + // Figure out how many tokens we are into LineToks. + unsigned LineIndex = 0; + if (Tok.is(EndOfStream)) { + LineIndex = LineToks.size() - 2; + } else { + while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { + LineIndex++; + assert(LineIndex < LineToks.size() - 2); // we added two extra tokens + } + } + + // If we've run into the poison token we inserted before, or there + // was a parsing error, then claim the entire line. + if (Invalid || Tok.is(EndOfStream)) { + NumLineToksConsumed = LineToks.size() - 2; + } else { + // Otherwise, claim up to the start of the next token. + NumLineToksConsumed = LineIndex; + } + + // Finally, restore the old parsing state by consuming all the tokens we + // staged before, implicitly killing off the token-lexer we pushed. + for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) { + ConsumeAnyToken(); + } + assert(Tok.is(EndOfStream)); + ConsumeToken(); + + // Leave LineToks in its original state. + LineToks.pop_back(); + LineToks.pop_back(); + + // Perform the lookup. + return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, + IsUnevaluatedContext); +} + +/// Turn a sequence of our tokens back into a string that we can hand +/// to the MC asm parser. +static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc, + ArrayRef<Token> AsmToks, + SmallVectorImpl<unsigned> &TokOffsets, + SmallString<512> &Asm) { + assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!"); + + // Is this the start of a new assembly statement? + bool isNewStatement = true; + + for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { + const Token &Tok = AsmToks[i]; + + // Start each new statement with a newline and a tab. + if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) { + Asm += "\n\t"; + isNewStatement = true; + } + + // Preserve the existence of leading whitespace except at the + // start of a statement. + if (!isNewStatement && Tok.hasLeadingSpace()) + Asm += ' '; + + // Remember the offset of this token. + TokOffsets.push_back(Asm.size()); + + // Don't actually write '__asm' into the assembly stream. + if (Tok.is(tok::kw_asm)) { + // Complain about __asm at the end of the stream. + if (i + 1 == e) { + PP.Diag(AsmLoc, diag::err_asm_empty); + return true; + } + + continue; + } + + // Append the spelling of the token. + SmallString<32> SpellingBuffer; + bool SpellingInvalid = false; + Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid); + assert(!SpellingInvalid && "spelling was invalid after correct parse?"); + + // We are no longer at the start of a statement. + isNewStatement = false; + } + + // Ensure that the buffer is null-terminated. + Asm.push_back('\0'); + Asm.pop_back(); + + assert(TokOffsets.size() == AsmToks.size()); + return false; +} + +/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, +/// this routine is called to collect the tokens for an MS asm statement. +/// +/// [MS] ms-asm-statement: +/// 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] ms-asm-instruction-block +/// ms-asm-line +/// ms-asm-line '\n' ms-asm-instruction-block +/// +StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { + SourceManager &SrcMgr = PP.getSourceManager(); + SourceLocation EndLoc = AsmLoc; + SmallVector<Token, 4> AsmToks; + + unsigned BraceNesting = 0; + unsigned short savedBraceCount = BraceCount; + bool InAsmComment = false; + FileID FID; + unsigned LineNo = 0; + unsigned NumTokensRead = 0; + SmallVector<SourceLocation, 4> LBraceLocs; + bool SkippedStartOfLine = false; + + if (Tok.is(tok::l_brace)) { + // Braced inline asm: consume the opening brace. + BraceNesting = 1; + EndLoc = ConsumeBrace(); + LBraceLocs.push_back(EndLoc); + ++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); + LBraceLocs.push_back(SourceLocation()); + } + + SourceLocation TokLoc = Tok.getLocation(); + do { + // If we hit EOF, we're done, period. + if (isEofOrEom()) + break; + + if (!InAsmComment && Tok.is(tok::l_brace)) { + // Consume the opening brace. + SkippedStartOfLine = Tok.isAtStartOfLine(); + EndLoc = ConsumeBrace(); + BraceNesting++; + LBraceLocs.push_back(EndLoc); + TokLoc = Tok.getLocation(); + ++NumTokensRead; + continue; + } else if (!InAsmComment && Tok.is(tok::semi)) { + // A semicolon in an asm is the start of a comment. + InAsmComment = true; + if (BraceNesting) { + // 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 (!BraceNesting || 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 (!BraceNesting) + 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; + } + } + if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) && + BraceCount == (savedBraceCount + BraceNesting)) { + // Consume the closing brace. + SkippedStartOfLine = Tok.isAtStartOfLine(); + EndLoc = ConsumeBrace(); + BraceNesting--; + // Finish if all of the opened braces in the inline asm section were + // consumed. + if (BraceNesting == 0) + break; + else { + LBraceLocs.pop_back(); + TokLoc = Tok.getLocation(); + ++NumTokensRead; + continue; + } + } + + // Consume the next token; make sure we don't modify the brace count etc. + // if we are in a comment. + EndLoc = TokLoc; + if (InAsmComment) + PP.Lex(Tok); + else { + // Set the token as the start of line if we skipped the original start + // of line token in case it was a nested brace. + if (SkippedStartOfLine) + Tok.setFlag(Token::StartOfLine); + AsmToks.push_back(Tok); + ConsumeAnyToken(); + } + TokLoc = Tok.getLocation(); + ++NumTokensRead; + SkippedStartOfLine = false; + } while (1); + + if (BraceNesting && BraceCount != savedBraceCount) { + // __asm without closing brace (this can happen at EOF). + for (unsigned i = 0; i < BraceNesting; ++i) { + Diag(Tok, diag::err_expected) << tok::r_brace; + Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace; + LBraceLocs.pop_back(); + } + return StmtError(); + } else if (NumTokensRead == 0) { + // Empty __asm. + Diag(Tok, diag::err_expected) << tok::l_brace; + return StmtError(); + } + + // Okay, prepare to use MC to parse the assembly. + SmallVector<StringRef, 4> ConstraintRefs; + SmallVector<Expr *, 4> Exprs; + SmallVector<StringRef, 4> ClobberRefs; + + // We need an actual supported target. + const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple(); + llvm::Triple::ArchType ArchTy = TheTriple.getArch(); + const std::string &TT = TheTriple.getTriple(); + const llvm::Target *TheTarget = nullptr; + bool UnsupportedArch = + (ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64); + if (UnsupportedArch) { + Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); + } else { + std::string Error; + TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error); + if (!TheTarget) + Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error; + } + + assert(!LBraceLocs.empty() && "Should have at least one location here"); + + // If we don't support assembly, or the assembly is empty, we don't + // need to instantiate the AsmParser, etc. + if (!TheTarget || AsmToks.empty()) { + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(), + /*NumOutputs*/ 0, /*NumInputs*/ 0, + ConstraintRefs, ClobberRefs, Exprs, EndLoc); + } + + // Expand the tokens into a string buffer. + SmallString<512> AsmString; + SmallVector<unsigned, 8> TokOffsets; + if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString)) + return StmtError(); + + std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); + std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); + // Get the instruction descriptor. + std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo()); + std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); + std::unique_ptr<llvm::MCSubtargetInfo> STI( + TheTarget->createMCSubtargetInfo(TT, "", "")); + + llvm::SourceMgr TempSrcMgr; + llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); + llvm::MemoryBuffer *Buffer = + llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + TempSrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); + + std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); + std::unique_ptr<llvm::MCAsmParser> Parser( + createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI)); + + // FIXME: init MCOptions from sanitizer flags here. + llvm::MCTargetOptions MCOptions; + std::unique_ptr<llvm::MCTargetAsmParser> TargetParser( + TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions)); + + std::unique_ptr<llvm::MCInstPrinter> IP( + TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI)); + + // Change to the Intel dialect. + Parser->setAssemblerDialect(1); + Parser->setTargetParser(*TargetParser.get()); + Parser->setParsingInlineAsm(true); + TargetParser->setParsingInlineAsm(true); + + ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks, + TokOffsets); + TargetParser->setSemaCallback(&Callback); + TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback, + &Callback); + + unsigned NumOutputs; + unsigned NumInputs; + std::string AsmStringIR; + SmallVector<std::pair<void *, bool>, 4> OpExprs; + SmallVector<std::string, 4> Constraints; + SmallVector<std::string, 4> Clobbers; + if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs, + NumInputs, OpExprs, Constraints, Clobbers, + MII.get(), IP.get(), Callback)) + return StmtError(); + + // Filter out "fpsw". Clang doesn't accept it, and it always lists flags and + // fpsr as clobbers. + auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw"); + Clobbers.erase(End, Clobbers.end()); + + // Build the vector of clobber StringRefs. + ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end()); + + // Recast the void pointers and build the vector of constraint StringRefs. + unsigned NumExprs = NumOutputs + NumInputs; + ConstraintRefs.resize(NumExprs); + Exprs.resize(NumExprs); + for (unsigned i = 0, e = NumExprs; i != e; ++i) { + Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first); + if (!OpExpr) + return StmtError(); + + // Need address of variable. + if (OpExprs[i].second) + OpExpr = + Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get(); + + ConstraintRefs[i] = StringRef(Constraints[i]); + Exprs[i] = OpExpr; + } + + // FIXME: We should be passing source locations for better diagnostics. + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR, + NumOutputs, NumInputs, ConstraintRefs, + ClobberRefs, Exprs, EndLoc); +} + +/// ParseAsmStatement - Parse a GNU extended asm statement. +/// asm-statement: +/// gnu-asm-statement +/// ms-asm-statement +/// +/// [GNU] gnu-asm-statement: +/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';' +/// +/// [GNU] asm-argument: +/// asm-string-literal +/// asm-string-literal ':' asm-operands[opt] +/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] +/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] +/// ':' asm-clobbers +/// +/// [GNU] asm-clobbers: +/// asm-string-literal +/// asm-clobbers ',' asm-string-literal +/// +StmtResult Parser::ParseAsmStatement(bool &msAsm) { + assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); + SourceLocation AsmLoc = ConsumeToken(); + + if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) && + !isTypeQualifier()) { + msAsm = true; + return ParseMicrosoftAsmStatement(AsmLoc); + } + DeclSpec DS(AttrFactory); + SourceLocation Loc = Tok.getLocation(); + ParseTypeQualifierListOpt(DS, true, false); + + // GNU asms accept, but warn, about type-qualifiers other than volatile. + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(Loc, diag::w_asm_qualifier_ignored) << "const"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) + Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict"; + // FIXME: Once GCC supports _Atomic, check whether it permits it here. + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) + Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic"; + + // Remember if this was a volatile asm. + bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; + if (Tok.isNot(tok::l_paren)) { + Diag(Tok, diag::err_expected_lparen_after) << "asm"; + SkipUntil(tok::r_paren, StopAtSemi); + return StmtError(); + } + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + + ExprResult AsmString(ParseAsmStringLiteral()); + if (AsmString.isInvalid()) { + // Consume up to and including the closing paren. + T.skipToEnd(); + return StmtError(); + } + + SmallVector<IdentifierInfo *, 4> Names; + ExprVector Constraints; + ExprVector Exprs; + ExprVector Clobbers; + + if (Tok.is(tok::r_paren)) { + // We have a simple asm expression like 'asm("foo")'. + T.consumeClose(); + return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, + /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr, + Constraints, Exprs, AsmString.get(), + Clobbers, T.getCloseLocation()); + } + + // Parse Outputs, if present. + bool AteExtraColon = false; + if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { + // 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. + if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { + // In C++ mode, parse "::" like ": :". + if (AteExtraColon) + AteExtraColon = false; + else { + AteExtraColon = Tok.is(tok::coloncolon); + ConsumeToken(); + } + + if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) + return StmtError(); + } + + assert(Names.size() == Constraints.size() && + Constraints.size() == Exprs.size() && "Input operand size mismatch!"); + + unsigned NumInputs = Names.size() - NumOutputs; + + // Parse the clobbers, if present. + if (AteExtraColon || Tok.is(tok::colon)) { + if (!AteExtraColon) + ConsumeToken(); + + // Parse the asm-string list for clobbers if present. + if (Tok.isNot(tok::r_paren)) { + while (1) { + ExprResult Clobber(ParseAsmStringLiteral()); + + if (Clobber.isInvalid()) + break; + + Clobbers.push_back(Clobber.get()); + + if (!TryConsumeToken(tok::comma)) + break; + } + } + } + + T.consumeClose(); + return Actions.ActOnGCCAsmStmt( + AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(), + Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation()); +} + +/// ParseAsmOperands - Parse the asm-operands production as used by +/// asm-statement, assuming the leading ':' token was eaten. +/// +/// [GNU] asm-operands: +/// asm-operand +/// asm-operands ',' asm-operand +/// +/// [GNU] asm-operand: +/// asm-string-literal '(' expression ')' +/// '[' identifier ']' asm-string-literal '(' expression ')' +/// +// +// FIXME: Avoid unnecessary std::string trashing. +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; + + while (1) { + // Read the [id] if present. + if (Tok.is(tok::l_square)) { + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_expected) << tok::identifier; + SkipUntil(tok::r_paren, StopAtSemi); + return true; + } + + IdentifierInfo *II = Tok.getIdentifierInfo(); + ConsumeToken(); + + Names.push_back(II); + T.consumeClose(); + } else + Names.push_back(nullptr); + + ExprResult Constraint(ParseAsmStringLiteral()); + if (Constraint.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return true; + } + Constraints.push_back(Constraint.get()); + + if (Tok.isNot(tok::l_paren)) { + Diag(Tok, diag::err_expected_lparen_after) << "asm operand"; + SkipUntil(tok::r_paren, StopAtSemi); + return true; + } + + // Read the parenthesized expression. + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + ExprResult Res(ParseExpression()); + T.consumeClose(); + if (Res.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return true; + } + Exprs.push_back(Res.get()); + // Eat the comma and continue parsing if it exists. + if (!TryConsumeToken(tok::comma)) + return false; + } +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 076edb9..fa6401f 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -101,17 +101,13 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, do { // Consume the 'export', if any. SourceLocation ExportLoc; - if (Tok.is(tok::kw_export)) { - ExportLoc = ConsumeToken(); - } + TryConsumeToken(tok::kw_export, ExportLoc); // Consume the 'template', which should be here. SourceLocation TemplateLoc; - if (Tok.is(tok::kw_template)) { - TemplateLoc = ConsumeToken(); - } else { + if (!TryConsumeToken(tok::kw_template, TemplateLoc)) { Diag(Tok.getLocation(), diag::err_expected_template); - return 0; + return nullptr; } // Parse the '<' template-parameter-list '>' @@ -121,9 +117,8 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, TemplateParams, LAngleLoc, RAngleLoc)) { // Skip until the semi-colon or a }. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); - if (Tok.is(tok::semi)) - ConsumeToken(); - return 0; + TryConsumeToken(tok::semi); + return nullptr; } ParamLists.push_back( @@ -175,7 +170,7 @@ Parser::ParseSingleDeclarationAfterTemplate( // We are parsing a member template. ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo, &DiagsFromTParams); - return 0; + return nullptr; } ParsedAttributesWithRange prefixAttrs(AttrFactory); @@ -219,7 +214,7 @@ Parser::ParseSingleDeclarationAfterTemplate( SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); if (Tok.is(tok::semi)) ConsumeToken(); - return 0; + return nullptr; } LateParsedAttrList LateParsedAttrs(true); @@ -255,8 +250,8 @@ Parser::ParseSingleDeclarationAfterTemplate( // Recover as if it were an explicit specialization. TemplateParameterLists FakedParamLists; FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0, - LAngleLoc)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr, + 0, LAngleLoc)); return ParseFunctionDefinition( DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists, @@ -302,11 +297,10 @@ bool Parser::ParseTemplateParameters(unsigned Depth, SourceLocation &LAngleLoc, SourceLocation &RAngleLoc) { // Get the template parameter list. - if (!Tok.is(tok::less)) { + if (!TryConsumeToken(tok::less, LAngleLoc)) { Diag(Tok.getLocation(), diag::err_expected_less_after) << "template"; return true; } - LAngleLoc = ConsumeToken(); // Try to parse the template parameter list. bool Failed = false; @@ -322,10 +316,8 @@ bool Parser::ParseTemplateParameters(unsigned Depth, Tok.setKind(tok::greater); RAngleLoc = Tok.getLocation(); Tok.setLocation(Tok.getLocation().getLocWithOffset(1)); - } else if (Tok.is(tok::greater)) - RAngleLoc = ConsumeToken(); - else if (Failed) { - Diag(Tok.getLocation(), diag::err_expected_greater); + } else if (!TryConsumeToken(tok::greater, RAngleLoc) && Failed) { + Diag(Tok.getLocation(), diag::err_expected) << tok::greater; return true; } return false; @@ -481,12 +473,8 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { SourceLocation KeyLoc = ConsumeToken(); // Grab the ellipsis (if given). - bool Ellipsis = false; SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) { - Ellipsis = true; - EllipsisLoc = ConsumeToken(); - + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) { Diag(EllipsisLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates @@ -495,7 +483,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { // Grab the template parameter name (if given) SourceLocation NameLoc; - IdentifierInfo* ParamName = 0; + IdentifierInfo *ParamName = nullptr; if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); @@ -504,34 +492,40 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. } else { - Diag(Tok.getLocation(), diag::err_expected_ident); - return 0; + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; + return nullptr; } + // Recover from misplaced ellipsis. + bool AlreadyHasEllipsis = EllipsisLoc.isValid(); + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true); + // Grab a default argument (if available). // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before // we introduce the type parameter into the local scope. SourceLocation EqualLoc; ParsedType DefaultArg; - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); - DefaultArg = ParseTypeName(/*Range=*/0, + if (TryConsumeToken(tok::equal, EqualLoc)) + DefaultArg = ParseTypeName(/*Range=*/nullptr, Declarator::TemplateTypeArgContext).get(); - } - return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis, - EllipsisLoc, KeyLoc, ParamName, NameLoc, - Depth, Position, EqualLoc, DefaultArg); + return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc, + KeyLoc, ParamName, NameLoc, Depth, Position, + EqualLoc, DefaultArg); } /// ParseTemplateTemplateParameter - Handle the parsing of template /// template parameters. /// /// type-parameter: [C++ temp.param] -/// 'template' '<' template-parameter-list '>' 'class' +/// 'template' '<' template-parameter-list '>' type-parameter-key /// ...[opt] identifier[opt] -/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] -/// = id-expression +/// 'template' '<' template-parameter-list '>' type-parameter-key +/// identifier[opt] = id-expression +/// type-parameter-key: +/// 'class' +/// 'typename' [C++1z] Decl * Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { assert(Tok.is(tok::kw_template) && "Expected 'template' keyword"); @@ -544,45 +538,50 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { ParseScope TemplateParmScope(this, Scope::TemplateParamScope); if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc, RAngleLoc)) { - return 0; + return nullptr; } } + // Provide an ExtWarn if the C++1z feature of using 'typename' here is used. // Generate a meaningful error if the user forgot to put class before the // identifier, comma, or greater. Provide a fixit if the identifier, comma, - // or greater appear immediately or after 'typename' or 'struct'. In the - // latter case, replace the keyword with 'class'. - if (!Tok.is(tok::kw_class)) { + // or greater appear immediately or after 'struct'. In the latter case, + // replace the keyword with 'class'. + if (!TryConsumeToken(tok::kw_class)) { bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct); - const Token& Next = Replace ? NextToken() : Tok; - if (Next.is(tok::identifier) || Next.is(tok::comma) || - Next.is(tok::greater) || Next.is(tok::greatergreater) || - Next.is(tok::ellipsis)) + const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok; + if (Tok.is(tok::kw_typename)) { + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus1z + ? diag::warn_cxx1y_compat_template_template_param_typename + : diag::ext_template_template_param_typename) + << (!getLangOpts().CPlusPlus1z + ? FixItHint::CreateReplacement(Tok.getLocation(), "class") + : FixItHint()); + } else if (Next.is(tok::identifier) || Next.is(tok::comma) || + Next.is(tok::greater) || Next.is(tok::greatergreater) || + Next.is(tok::ellipsis)) { Diag(Tok.getLocation(), diag::err_class_on_template_template_param) << (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class") : FixItHint::CreateInsertion(Tok.getLocation(), "class ")); - else + } else Diag(Tok.getLocation(), diag::err_class_on_template_template_param); if (Replace) ConsumeToken(); - } else - ConsumeToken(); + } // Parse the ellipsis, if given. SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) { - EllipsisLoc = ConsumeToken(); - + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) Diag(EllipsisLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); - } // Get the identifier, if given. SourceLocation NameLoc; - IdentifierInfo* ParamName = 0; + IdentifierInfo *ParamName = nullptr; if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); @@ -591,10 +590,15 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. } else { - Diag(Tok.getLocation(), diag::err_expected_ident); - return 0; + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; + return nullptr; } + // Recover from misplaced ellipsis. + bool AlreadyHasEllipsis = EllipsisLoc.isValid(); + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true); + TemplateParameterList *ParamList = Actions.ActOnTemplateParameterList(Depth, SourceLocation(), TemplateLoc, LAngleLoc, @@ -607,8 +611,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { // we introduce the template parameter into the local scope. SourceLocation EqualLoc; ParsedTemplateArgument DefaultArg; - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); + if (TryConsumeToken(tok::equal, EqualLoc)) { DefaultArg = ParseTemplateTemplateArgument(); if (DefaultArg.isInvalid()) { Diag(Tok.getLocation(), @@ -643,17 +646,20 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { ParseDeclarator(ParamDecl); if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { Diag(Tok.getLocation(), diag::err_expected_template_parameter); - return 0; + return nullptr; } + // Recover from misplaced ellipsis. + SourceLocation EllipsisLoc; + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, ParamDecl); + // If there is a default value, parse it. // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before // we introduce the template parameter into the local scope. SourceLocation EqualLoc; ExprResult DefaultArg; - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); - + if (TryConsumeToken(tok::equal, EqualLoc)) { // C++ [temp.param]p15: // When parsing a default template-argument for a non-type // template-parameter, the first non-nested > is taken as the @@ -670,7 +676,29 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // Create the parameter. return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl, Depth, Position, EqualLoc, - DefaultArg.take()); + DefaultArg.get()); +} + +void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc, + SourceLocation CorrectLoc, + bool AlreadyHasEllipsis, + bool IdentifierHasName) { + FixItHint Insertion; + if (!AlreadyHasEllipsis) + Insertion = FixItHint::CreateInsertion(CorrectLoc, "..."); + Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration) + << FixItHint::CreateRemoval(EllipsisLoc) << Insertion + << !IdentifierHasName; +} + +void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc, + Declarator &D) { + assert(EllipsisLoc.isValid()); + bool AlreadyHasEllipsis = D.getEllipsisLoc().isValid(); + if (!AlreadyHasEllipsis) + D.setEllipsisLoc(EllipsisLoc); + DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(), + AlreadyHasEllipsis, D.hasName()); } /// \brief Parses a '>' at the end of a template list. @@ -692,7 +720,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, switch (Tok.getKind()) { default: - Diag(Tok.getLocation(), diag::err_expected_greater); + Diag(Tok.getLocation(), diag::err_expected) << tok::greater; return true; case tok::greater: @@ -723,7 +751,9 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, // This template-id is terminated by a token which starts with a '>'. Outside // C++11, this is now error recovery, and in C++11, this is error recovery if - // the token isn't '>>'. + // the token isn't '>>' or '>>>'. + // '>>>' is for CUDA, where this sequence of characters is parsed into + // tok::greatergreatergreater, rather than two separate tokens. RAngleLoc = Tok.getLocation(); @@ -753,7 +783,8 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; - if (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)) + if (getLangOpts().CPlusPlus11 && + (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater))) DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) DiagId = diag::err_right_angle_bracket_equal_needs_space; @@ -900,8 +931,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, if (Invalid) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. - if (Tok.is(tok::greater)) - ConsumeToken(); + TryConsumeToken(tok::greater); return true; } @@ -916,8 +946,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, if (Type.isInvalid()) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. - if (Tok.is(tok::greater)) - ConsumeToken(); + TryConsumeToken(tok::greater); return true; } @@ -940,7 +969,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateId->Name = TemplateName.Identifier; TemplateId->Operator = OO_None; } else { - TemplateId->Name = 0; + TemplateId->Name = nullptr; TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; } TemplateId->SS = SS; @@ -1044,11 +1073,9 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { UnqualifiedId Name; Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier - - // Parse the ellipsis. - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); - + + TryConsumeToken(tok::ellipsis, EllipsisLoc); + // If the next token signals the end of a template argument, // then we have a dependent template name that could be a template // template argument. @@ -1067,10 +1094,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { UnqualifiedId Name; Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier - - // Parse the ellipsis. - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); + + TryConsumeToken(tok::ellipsis, EllipsisLoc); if (isEndOfTemplateArgument(Tok)) { bool MemberOfUnknownSpecialization; @@ -1111,7 +1136,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // Therefore, we initially try to parse a type-id. if (isCXXTypeId(TypeIdAsTemplateArgument)) { SourceLocation Loc = Tok.getLocation(); - TypeResult TypeArg = ParseTypeName(/*Range=*/0, + TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr, Declarator::TemplateTypeArgContext); if (TypeArg.isInvalid()) return ParsedTemplateArgument(); @@ -1143,7 +1168,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { return ParsedTemplateArgument(); return ParsedTemplateArgument(ParsedTemplateArgument::NonType, - ExprArg.release(), Loc); + ExprArg.get(), Loc); } /// \brief Determine whether the current tokens can only be parsed as a @@ -1161,16 +1186,15 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { } // '<' - if (!Tok.is(tok::less)) + if (!TryConsumeToken(tok::less)) return false; - ConsumeToken(); // An empty template argument list. if (Tok.is(tok::greater)) return true; // See whether we have declaration specifiers, which indicate a type. - while (isCXXDeclarationSpecifier() == TPResult::True()) + while (isCXXDeclarationSpecifier() == TPResult::True) ConsumeToken(); // If we have a '>' or a ',' then this is a template argument list. @@ -1187,13 +1211,13 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { // Template argument lists are constant-evaluation contexts. EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated); + ColonProtectionRAIIObject ColonProtection(*this, false); - while (true) { + do { ParsedTemplateArgument Arg = ParseTemplateArgument(); - if (Tok.is(tok::ellipsis)) { - SourceLocation EllipsisLoc = ConsumeToken(); + SourceLocation EllipsisLoc; + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc); - } if (Arg.isInvalid()) { SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch); @@ -1205,11 +1229,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { // If the next token is a comma, consume it and keep reading // arguments. - if (Tok.isNot(tok::comma)) break; - - // Consume the comma. - ConsumeToken(); - } + } while (TryConsumeToken(tok::comma)); return false; } @@ -1258,9 +1278,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { return; // Get the FunctionDecl. - FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LPT.D); - FunctionDecl *FunD = - FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LPT.D); + FunctionDecl *FunD = LPT.D->getAsFunction(); // Track template parameter depth. TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); @@ -1271,7 +1289,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { // Get the list of DeclContexts to reenter. SmallVector<DeclContext*, 4> DeclContextsToReenter; - DeclContext *DD = FunD->getLexicalParent(); + DeclContext *DD = FunD; while (DD && !DD->isTranslationUnit()) { DeclContextsToReenter.push_back(DD); DD = DD->getLexicalParent(); @@ -1281,35 +1299,16 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { SmallVectorImpl<DeclContext *>::reverse_iterator II = DeclContextsToReenter.rbegin(); for (; II != DeclContextsToReenter.rend(); ++II) { - if (ClassTemplatePartialSpecializationDecl *MD = - dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) { - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope)); - Actions.ActOnReenterTemplateScope(getCurScope(), MD); - ++CurTemplateDepthTracker; - } else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) { - bool IsClassTemplate = MD->getDescribedClassTemplate() != 0; - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope, - /*ManageScope*/IsClassTemplate)); - Actions.ActOnReenterTemplateScope(getCurScope(), - MD->getDescribedClassTemplate()); - if (IsClassTemplate) - ++CurTemplateDepthTracker; + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope)); + unsigned NumParamLists = + Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II)); + CurTemplateDepthTracker.addDepth(NumParamLists); + if (*II != FunD) { + TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); + Actions.PushDeclContext(Actions.getCurScope(), *II); } - TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); - Actions.PushDeclContext(Actions.getCurScope(), *II); - } - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope)); - - DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD); - if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { - Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); - ++CurTemplateDepthTracker; } - Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D); - ++CurTemplateDepthTracker; assert(!LPT.Toks.empty() && "Empty body!"); @@ -1341,14 +1340,16 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { Actions.ActOnDefaultCtorInitializers(LPT.D); if (Tok.is(tok::l_brace)) { - assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() < - TemplateParameterDepth) && + assert((!isa<FunctionTemplateDecl>(LPT.D) || + cast<FunctionTemplateDecl>(LPT.D) + ->getTemplateParameters() + ->getDepth() == TemplateParameterDepth - 1) && "TemplateParameterDepth should be greater than the depth of " "current template being instantiated!"); ParseFunctionStatementBody(LPT.D, FnScope); Actions.UnmarkAsLateParsedTemplate(FunD); } else - Actions.ActOnFinishFunctionBody(LPT.D, 0); + Actions.ActOnFinishFunctionBody(LPT.D, nullptr); } // Exit scopes. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index a1d6b13..8514af2 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -101,15 +101,15 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) { // an ambiguity if the first decl-specifier is // simple-type-specifier/typename-specifier followed by a '(', which may // indicate a function-style cast expression. - // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such + // isCXXDeclarationSpecifier will return TPResult::Ambiguous only in such // a case. bool InvalidAsDeclaration = false; - TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), + TPResult TPR = isCXXDeclarationSpecifier(TPResult::False, &InvalidAsDeclaration); - if (TPR != TPResult::Ambiguous()) - return TPR != TPResult::False(); // Returns true for TPResult::True() or - // TPResult::Error(). + if (TPR != TPResult::Ambiguous) + return TPR != TPResult::False; // Returns true for TPResult::True or + // TPResult::Error. // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer, // and so gets some cases wrong. We can't carry on if we've already seen @@ -131,15 +131,15 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) { PA.Revert(); // In case of an error, let the declaration parsing code handle it. - if (TPR == TPResult::Error()) + if (TPR == TPResult::Error) return true; // Declarations take precedence over expressions. - if (TPR == TPResult::Ambiguous()) - TPR = TPResult::True(); + if (TPR == TPResult::Ambiguous) + TPR = TPResult::True; - assert(TPR == TPResult::True() || TPR == TPResult::False()); - return TPR == TPResult::True(); + assert(TPR == TPResult::True || TPR == TPResult::False); + return TPR == TPResult::True; } /// Try to consume a token sequence that we've already identified as @@ -157,10 +157,10 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { case tok::kw___underlying_type: { ConsumeToken(); if (Tok.isNot(tok::l_paren)) - return TPResult::Error(); + return TPResult::Error; ConsumeParen(); if (!SkipUntil(tok::r_paren)) - return TPResult::Error(); + return TPResult::Error; break; } @@ -184,23 +184,23 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { if (Tok.is(tok::l_square)) { ConsumeBracket(); if (!SkipUntil(tok::r_square)) - return TPResult::Error(); + return TPResult::Error; } else { ConsumeToken(); if (Tok.isNot(tok::l_paren)) - return TPResult::Error(); + return TPResult::Error; ConsumeParen(); if (!SkipUntil(tok::r_paren)) - return TPResult::Error(); + return TPResult::Error; } } if (TryAnnotateCXXScopeToken()) - return TPResult::Error(); + return TPResult::Error; if (Tok.is(tok::annot_cxxscope)) ConsumeToken(); if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) - return TPResult::Error(); + return TPResult::Error; ConsumeToken(); break; @@ -215,7 +215,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { break; } - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } /// simple-declaration: @@ -227,29 +227,29 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { /// attribute-specifier-seqopt type-specifier-seq declarator /// Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) { - if (TryConsumeDeclarationSpecifier() == TPResult::Error()) - return TPResult::Error(); + if (TryConsumeDeclarationSpecifier() == TPResult::Error) + return TPResult::Error; // Two decl-specifiers in a row conclusively disambiguate this as being a // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the // overwhelmingly common case that the next token is a '('. if (Tok.isNot(tok::l_paren)) { TPResult TPR = isCXXDeclarationSpecifier(); - if (TPR == TPResult::Ambiguous()) - return TPResult::True(); - if (TPR == TPResult::True() || TPR == TPResult::Error()) + if (TPR == TPResult::Ambiguous) + return TPResult::True; + if (TPR == TPResult::True || TPR == TPResult::Error) return TPR; - assert(TPR == TPResult::False()); + assert(TPR == TPResult::False); } TPResult TPR = TryParseInitDeclaratorList(); - if (TPR != TPResult::Ambiguous()) + if (TPR != TPResult::Ambiguous) return TPR; if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon))) - return TPResult::False(); + return TPResult::False; - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } /// Tentatively parse an init-declarator-list in order to disambiguate it from @@ -283,23 +283,23 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() { while (1) { // declarator TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); - if (TPR != TPResult::Ambiguous()) + if (TPR != TPResult::Ambiguous) return TPR; // [GNU] simple-asm-expr[opt] attributes[opt] if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) - return TPResult::True(); + return TPResult::True; // initializer[opt] if (Tok.is(tok::l_paren)) { // Parse through the parens. ConsumeParen(); if (!SkipUntil(tok::r_paren, StopAtSemi)) - return TPResult::Error(); + return TPResult::Error; } else if (Tok.is(tok::l_brace)) { // A left-brace here is sufficient to disambiguate the parse; an // expression can never be followed directly by a braced-init-list. - return TPResult::True(); + return TPResult::True; } else if (Tok.is(tok::equal) || isTokIdentifier_in()) { // MSVC and g++ won't examine the rest of declarators if '=' is // encountered; they just conclude that we have a declaration. @@ -317,15 +317,14 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() { // in any other context 'in' is invalid after a declaration and parser // issues the error regardless of outcome of this decision. // FIXME: Change if above assumption does not hold. - return TPResult::True(); + return TPResult::True; } - if (Tok.isNot(tok::comma)) + if (!TryConsumeToken(tok::comma)) break; - ConsumeToken(); // the comma. } - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } /// isCXXConditionDeclaration - Disambiguates between a declaration or an @@ -343,9 +342,9 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() { /// bool Parser::isCXXConditionDeclaration() { TPResult TPR = isCXXDeclarationSpecifier(); - if (TPR != TPResult::Ambiguous()) - return TPR != TPResult::False(); // Returns true for TPResult::True() or - // TPResult::Error(). + if (TPR != TPResult::Ambiguous) + return TPR != TPResult::False; // Returns true for TPResult::True or + // TPResult::Error. // FIXME: Add statistics about the number of ambiguous statements encountered // and how they were resolved (number of declarations+number of expressions). @@ -363,25 +362,25 @@ bool Parser::isCXXConditionDeclaration() { TPR = TryParseDeclarator(false/*mayBeAbstract*/); // In case of an error, let the declaration parsing code handle it. - if (TPR == TPResult::Error()) - TPR = TPResult::True(); + if (TPR == TPResult::Error) + TPR = TPResult::True; - if (TPR == TPResult::Ambiguous()) { + if (TPR == TPResult::Ambiguous) { // '=' // [GNU] simple-asm-expr[opt] attributes[opt] if (Tok.is(tok::equal) || Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) - TPR = TPResult::True(); + TPR = TPResult::True; else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) - TPR = TPResult::True(); + TPR = TPResult::True; else - TPR = TPResult::False(); + TPR = TPResult::False; } PA.Revert(); - assert(TPR == TPResult::True() || TPR == TPResult::False()); - return TPR == TPResult::True(); + assert(TPR == TPResult::True || TPR == TPResult::False); + return TPR == TPResult::True; } /// \brief Determine whether the next set of tokens contains a type-id. @@ -413,9 +412,9 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { // in its syntactic context shall be considered a type-id. TPResult TPR = isCXXDeclarationSpecifier(); - if (TPR != TPResult::Ambiguous()) - return TPR != TPResult::False(); // Returns true for TPResult::True() or - // TPResult::Error(). + if (TPR != TPResult::Ambiguous) + return TPR != TPResult::False; // Returns true for TPResult::True or + // TPResult::Error. // FIXME: Add statistics about the number of ambiguous statements encountered // and how they were resolved (number of declarations+number of expressions). @@ -433,14 +432,14 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); // In case of an error, let the declaration parsing code handle it. - if (TPR == TPResult::Error()) - TPR = TPResult::True(); + if (TPR == TPResult::Error) + TPR = TPResult::True; - if (TPR == TPResult::Ambiguous()) { + if (TPR == TPResult::Ambiguous) { // We are supposed to be inside parens, so if after the abstract declarator // we encounter a ')' this is a type-id, otherwise it's an expression. if (Context == TypeIdInParens && Tok.is(tok::r_paren)) { - TPR = TPResult::True(); + TPR = TPResult::True; isAmbiguous = true; // We are supposed to be inside a template argument, so if after @@ -449,17 +448,17 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { } else if (Context == TypeIdAsTemplateArgument && (Tok.is(tok::greater) || Tok.is(tok::comma) || (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) { - TPR = TPResult::True(); + TPR = TPResult::True; isAmbiguous = true; } else - TPR = TPResult::False(); + TPR = TPResult::False; } PA.Revert(); - assert(TPR == TPResult::True() || TPR == TPResult::False()); - return TPR == TPResult::True(); + assert(TPR == TPResult::True || TPR == TPResult::False); + return TPR == TPResult::True; } /// \brief Returns true if this is a C++11 attribute-specifier. Per @@ -595,13 +594,10 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate, } } - if (Tok.is(tok::ellipsis)) - ConsumeToken(); + TryConsumeToken(tok::ellipsis); - if (Tok.isNot(tok::comma)) + if (!TryConsumeToken(tok::comma)) break; - - ConsumeToken(); } // An attribute must end ']]'. @@ -628,7 +624,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() { while (true) { if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) if (TryAnnotateCXXScopeToken(true)) - return TPResult::Error(); + return TPResult::Error; if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || Tok.is(tok::ampamp) || @@ -640,7 +636,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() { Tok.is(tok::kw_restrict)) ConsumeToken(); } else { - return TPResult::True(); + return TPResult::True; } } } @@ -675,20 +671,20 @@ Parser::TPResult Parser::TryParseOperatorId() { ConsumeBracket(); ConsumeBracket(); } - return TPResult::True(); + return TPResult::True; #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \ case tok::Token: #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly) #include "clang/Basic/OperatorKinds.def" ConsumeToken(); - return TPResult::True(); + return TPResult::True; case tok::l_square: if (NextToken().is(tok::r_square)) { ConsumeBracket(); ConsumeBracket(); - return TPResult::True(); + return TPResult::True; } break; @@ -696,7 +692,7 @@ Parser::TPResult Parser::TryParseOperatorId() { if (NextToken().is(tok::r_paren)) { ConsumeParen(); ConsumeParen(); - return TPResult::True(); + return TPResult::True; } break; @@ -716,24 +712,24 @@ Parser::TPResult Parser::TryParseOperatorId() { if (Tok.is(tok::identifier)) ConsumeToken(); else - return TPResult::Error(); + return TPResult::Error; } - return TPResult::True(); + return TPResult::True; } // Maybe this is a conversion-function-id. bool AnyDeclSpecifiers = false; while (true) { TPResult TPR = isCXXDeclarationSpecifier(); - if (TPR == TPResult::Error()) + if (TPR == TPResult::Error) return TPR; - if (TPR == TPResult::False()) { + if (TPR == TPResult::False) { if (!AnyDeclSpecifiers) - return TPResult::Error(); + return TPResult::Error; break; } - if (TryConsumeDeclarationSpecifier() == TPResult::Error()) - return TPResult::Error(); + if (TryConsumeDeclarationSpecifier() == TPResult::Error) + return TPResult::Error; AnyDeclSpecifiers = true; } return TryParsePtrOperatorSeq(); @@ -797,8 +793,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, // declarator: // direct-declarator // ptr-operator declarator - if (TryParsePtrOperatorSeq() == TPResult::Error()) - return TPResult::Error(); + if (TryParsePtrOperatorSeq() == TPResult::Error) + return TPResult::Error; // direct-declarator: // direct-abstract-declarator: @@ -815,8 +811,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, else if (Tok.is(tok::identifier)) TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo()); if (Tok.is(tok::kw_operator)) { - if (TryParseOperatorId() == TPResult::Error()) - return TPResult::Error(); + if (TryParseOperatorId() == TPResult::Error) + return TPResult::Error; } else ConsumeToken(); } else if (Tok.is(tok::l_paren)) { @@ -829,7 +825,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] // exception-specification[opt] TPResult TPR = TryParseFunctionDeclarator(); - if (TPR != TPResult::Ambiguous()) + if (TPR != TPResult::Ambiguous) return TPR; } else { // '(' declarator ')' @@ -842,20 +838,20 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___unaligned)) - return TPResult::True(); // attributes indicate declaration + return TPResult::True; // attributes indicate declaration TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); - if (TPR != TPResult::Ambiguous()) + if (TPR != TPResult::Ambiguous) return TPR; if (Tok.isNot(tok::r_paren)) - return TPResult::False(); + return TPResult::False; ConsumeParen(); } } else if (!mayBeAbstract) { - return TPResult::False(); + return TPResult::False; } while (1) { - TPResult TPR(TPResult::Ambiguous()); + TPResult TPR(TPResult::Ambiguous); // abstract-declarator: ... if (Tok.is(tok::ellipsis)) @@ -881,11 +877,11 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, break; } - if (TPR != TPResult::Ambiguous()) + if (TPR != TPResult::Ambiguous) return TPR; } - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } Parser::TPResult @@ -935,42 +931,19 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___alignof: case tok::kw___builtin_choose_expr: case tok::kw___builtin_offsetof: - case tok::kw___builtin_types_compatible_p: case tok::kw___builtin_va_arg: case tok::kw___imag: case tok::kw___real: case tok::kw___FUNCTION__: case tok::kw___FUNCDNAME__: + case tok::kw___FUNCSIG__: case tok::kw_L__FUNCTION__: case tok::kw___PRETTY_FUNCTION__: - case tok::kw___has_nothrow_assign: - case tok::kw___has_nothrow_copy: - case tok::kw___has_nothrow_constructor: - case tok::kw___has_trivial_assign: - case tok::kw___has_trivial_copy: - case tok::kw___has_trivial_constructor: - case tok::kw___has_trivial_destructor: - case tok::kw___has_virtual_destructor: - case tok::kw___is_abstract: - case tok::kw___is_base_of: - case tok::kw___is_class: - case tok::kw___is_convertible_to: - case tok::kw___is_empty: - case tok::kw___is_enum: - case tok::kw___is_interface_class: - case tok::kw___is_final: - case tok::kw___is_literal: - case tok::kw___is_literal_type: - case tok::kw___is_pod: - case tok::kw___is_polymorphic: - case tok::kw___is_sealed: - case tok::kw___is_trivial: - case tok::kw___is_trivially_assignable: - case tok::kw___is_trivially_constructible: - case tok::kw___is_trivially_copyable: - case tok::kw___is_union: case tok::kw___uuidof: - return TPResult::True(); +#define TYPE_TRAIT(N,Spelling,K) \ + case tok::kw_##Spelling: +#include "clang/Basic/TokenKinds.def" + return TPResult::True; // Obviously starts a type-specifier-seq: case tok::kw_char: @@ -1015,22 +988,14 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___vector: case tok::kw___pixel: case tok::kw__Atomic: - case tok::kw_image1d_t: - case tok::kw_image1d_array_t: - case tok::kw_image1d_buffer_t: - case tok::kw_image2d_t: - case tok::kw_image2d_array_t: - case tok::kw_image3d_t: - case tok::kw_sampler_t: - case tok::kw_event_t: case tok::kw___unknown_anytype: - return TPResult::False(); + return TPResult::False; default: break; } - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } bool Parser::isTentativelyDeclared(IdentifierInfo *II) { @@ -1039,16 +1004,16 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) { != TentativelyDeclaredIdentifiers.end(); } -/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration -/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could -/// be either a decl-specifier or a function-style cast, and TPResult::Error() +/// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration +/// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could +/// be either a decl-specifier or a function-style cast, and TPResult::Error /// if a parsing error was found and reported. /// /// If HasMissingTypename is provided, a name with a dependent scope specifier /// will be treated as ambiguous if the 'typename' keyword is missing. If this /// happens, *HasMissingTypename will be set to 'true'. This will also be used /// as an indicator that undeclared identifiers (which will trigger a later -/// parse error) should be treated as types. Returns TPResult::Ambiguous() in +/// parse error) should be treated as types. Returns TPResult::Ambiguous in /// such cases. /// /// decl-specifier: @@ -1152,12 +1117,12 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // Check for need to substitute AltiVec __vector keyword // for "vector" identifier. if (TryAltiVecVectorToken()) - return TPResult::True(); + return TPResult::True; const Token &Next = NextToken(); // In 'foo bar', 'foo' is always a type name outside of Objective-C. if (!getLangOpts().ObjC1 && Next.is(tok::identifier)) - return TPResult::True(); + return TPResult::True; if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) { // Determine whether this is a valid expression. If not, we will hit @@ -1170,15 +1135,15 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, switch (TryAnnotateName(false /* no nested name specifier */, &TypoCorrection)) { case ANK_Error: - return TPResult::Error(); + return TPResult::Error; case ANK_TentativeDecl: - return TPResult::False(); + return TPResult::False; case ANK_TemplateName: // A bare type template-name which can't be a template template // argument is an error, and was probably intended to be a type. - return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); + return GreaterThanIsOperator ? TPResult::True : TPResult::False; case ANK_Unresolved: - return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False(); + return HasMissingTypename ? TPResult::Ambiguous : TPResult::False; case ANK_Success: break; } @@ -1190,12 +1155,12 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // since it will annotate as a primary expression, and we want to use the // "missing 'typename'" logic. if (TryAnnotateTypeOrScopeToken()) - return TPResult::Error(); + return TPResult::Error; // If annotation failed, assume it's a non-type. // FIXME: If this happens due to an undeclared identifier, treat it as // ambiguous. if (Tok.is(tok::identifier)) - return TPResult::False(); + return TPResult::False; } // We annotated this token as something. Recurse to handle whatever we got. @@ -1206,21 +1171,21 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) - return TPResult::Error(); + return TPResult::Error; return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); case tok::coloncolon: { // ::foo::bar const Token &Next = NextToken(); if (Next.is(tok::kw_new) || // ::new Next.is(tok::kw_delete)) // ::delete - return TPResult::False(); + return TPResult::False; } // Fall through. case tok::kw_decltype: // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) - return TPResult::Error(); + return TPResult::Error; return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); // decl-specifier: @@ -1277,7 +1242,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw_restrict: case tok::kw__Complex: case tok::kw___attribute: - return TPResult::True(); + return TPResult::True; // Microsoft case tok::kw___declspec: @@ -1292,20 +1257,20 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw___ptr32: case tok::kw___forceinline: case tok::kw___unaligned: - return TPResult::True(); + return TPResult::True; // Borland case tok::kw___pascal: - return TPResult::True(); + return TPResult::True; // AltiVec case tok::kw___vector: - return TPResult::True(); + return TPResult::True; case tok::annot_template_id: { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->Kind != TNK_Type_template) - return TPResult::False(); + return TPResult::False; CXXScopeSpec SS; AnnotateTemplateIdTokenAsType(); assert(Tok.is(tok::annot_typename)); @@ -1315,7 +1280,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed // We've already annotated a scope; try to annotate a type. if (TryAnnotateTypeOrScopeToken()) - return TPResult::Error(); + return TPResult::Error; if (!Tok.is(tok::annot_typename)) { // If the next token is an identifier or a type qualifier, then this // can't possibly be a valid expression either. @@ -1329,37 +1294,37 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, ConsumeToken(); ConsumeToken(); bool isIdentifier = Tok.is(tok::identifier); - TPResult TPR = TPResult::False(); + TPResult TPR = TPResult::False; if (!isIdentifier) TPR = isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); PA.Revert(); if (isIdentifier || - TPR == TPResult::True() || TPR == TPResult::Error()) - return TPResult::Error(); + TPR == TPResult::True || TPR == TPResult::Error) + return TPResult::Error; if (HasMissingTypename) { // We can't tell whether this is a missing 'typename' or a valid // expression. *HasMissingTypename = true; - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } } else { // Try to resolve the name. If it doesn't exist, assume it was // intended to name a type and keep disambiguating. switch (TryAnnotateName(false /* SS is not dependent */)) { case ANK_Error: - return TPResult::Error(); + return TPResult::Error; case ANK_TentativeDecl: - return TPResult::False(); + return TPResult::False; case ANK_TemplateName: // A bare type template-name which can't be a template template // argument is an error, and was probably intended to be a type. - return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); + return GreaterThanIsOperator ? TPResult::True : TPResult::False; case ANK_Unresolved: - return HasMissingTypename ? TPResult::Ambiguous() - : TPResult::False(); + return HasMissingTypename ? TPResult::Ambiguous + : TPResult::False; case ANK_Success: // Annotated it, check again. assert(Tok.isNot(tok::annot_cxxscope) || @@ -1369,7 +1334,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, } } } - return TPResult::False(); + return TPResult::False; } // If that succeeded, fallthrough into the generic simple-type-id case. @@ -1405,16 +1370,16 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, PA.Revert(); - if (TPR == TPResult::Error()) - return TPResult::Error(); + if (TPR == TPResult::Error) + return TPResult::Error; if (isFollowedByParen) - return TPResult::Ambiguous(); + return TPResult::Ambiguous; if (getLangOpts().CPlusPlus11 && isFollowedByBrace) return BracedCastResult; - return TPResult::True(); + return TPResult::True; } case tok::kw_char: @@ -1435,7 +1400,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw_void: case tok::annot_decltype: if (NextToken().is(tok::l_paren)) - return TPResult::Ambiguous(); + return TPResult::Ambiguous; // This is a function-style cast in all cases we disambiguate other than // one: @@ -1447,14 +1412,14 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return BracedCastResult; if (isStartOfObjCClassMessageMissingOpenBracket()) - return TPResult::False(); + return TPResult::False; - return TPResult::True(); + return TPResult::True; // GNU typeof support. case tok::kw_typeof: { if (NextToken().isNot(tok::l_paren)) - return TPResult::True(); + return TPResult::True; TentativeParsingAction PA(*this); @@ -1464,28 +1429,28 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, PA.Revert(); - if (TPR == TPResult::Error()) - return TPResult::Error(); + if (TPR == TPResult::Error) + return TPResult::Error; if (isFollowedByParen) - return TPResult::Ambiguous(); + return TPResult::Ambiguous; if (getLangOpts().CPlusPlus11 && isFollowedByBrace) return BracedCastResult; - return TPResult::True(); + return TPResult::True; } // C++0x type traits support case tok::kw___underlying_type: - return TPResult::True(); + return TPResult::True; // C11 _Atomic case tok::kw__Atomic: - return TPResult::True(); + return TPResult::True; default: - return TPResult::False(); + return TPResult::False; } } @@ -1551,9 +1516,9 @@ Parser::TPResult Parser::TryParseTypeofSpecifier() { // Parse through the parens after 'typeof'. ConsumeParen(); if (!SkipUntil(tok::r_paren, StopAtSemi)) - return TPResult::Error(); + return TPResult::Error; - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } /// [ObjC] protocol-qualifiers: @@ -1563,7 +1528,7 @@ Parser::TPResult Parser::TryParseProtocolQualifiers() { ConsumeToken(); do { if (Tok.isNot(tok::identifier)) - return TPResult::Error(); + return TPResult::Error; ConsumeToken(); if (Tok.is(tok::comma)) { @@ -1573,11 +1538,11 @@ Parser::TPResult Parser::TryParseProtocolQualifiers() { if (Tok.is(tok::greater)) { ConsumeToken(); - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } } while (false); - return TPResult::Error(); + return TPResult::Error; } /// isCXXFunctionDeclarator - Disambiguates between a function declarator or @@ -1606,9 +1571,9 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) { ConsumeParen(); bool InvalidAsDeclaration = false; TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration); - if (TPR == TPResult::Ambiguous()) { + if (TPR == TPResult::Ambiguous) { if (Tok.isNot(tok::r_paren)) - TPR = TPResult::False(); + TPR = TPResult::False; else { const Token &Next = NextToken(); if (Next.is(tok::amp) || Next.is(tok::ampamp) || @@ -1620,20 +1585,20 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) { // The next token cannot appear after a constructor-style initializer, // and can appear next in a function definition. This must be a function // declarator. - TPR = TPResult::True(); + TPR = TPResult::True; else if (InvalidAsDeclaration) // Use the absence of 'typename' as a tie-breaker. - TPR = TPResult::False(); + TPR = TPResult::False; } } PA.Revert(); - if (IsAmbiguous && TPR == TPResult::Ambiguous()) + if (IsAmbiguous && TPR == TPResult::Ambiguous) *IsAmbiguous = true; // In case of an error, let the declaration parsing code handle it. - return TPR != TPResult::False(); + return TPR != TPResult::False; } /// parameter-declaration-clause: @@ -1658,7 +1623,7 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration, bool VersusTemplateArgument) { if (Tok.is(tok::r_paren)) - return TPResult::Ambiguous(); + return TPResult::Ambiguous; // parameter-declaration-list[opt] '...'[opt] // parameter-declaration-list ',' '...' @@ -1672,15 +1637,15 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration, if (Tok.is(tok::ellipsis)) { ConsumeToken(); if (Tok.is(tok::r_paren)) - return TPResult::True(); // '...)' is a sign of a function declarator. + return TPResult::True; // '...)' is a sign of a function declarator. else - return TPResult::False(); + return TPResult::False; } // An attribute-specifier-seq here is a sign of a function declarator. if (isCXX11AttributeSpecifier(/*Disambiguate*/false, /*OuterMightBeMessageSend*/true)) - return TPResult::True(); + return TPResult::True; ParsedAttributes attrs(AttrFactory); MaybeParseMicrosoftAttributes(attrs); @@ -1688,43 +1653,43 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration, // decl-specifier-seq // A parameter-declaration's initializer must be preceded by an '=', so // decl-specifier-seq '{' is not a parameter in C++11. - TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), + TPResult TPR = isCXXDeclarationSpecifier(TPResult::False, InvalidAsDeclaration); - if (VersusTemplateArgument && TPR == TPResult::True()) { + if (VersusTemplateArgument && TPR == TPResult::True) { // Consume the decl-specifier-seq. We have to look past it, since a // type-id might appear here in a template argument. bool SeenType = false; do { SeenType |= isCXXDeclarationSpecifierAType(); - if (TryConsumeDeclarationSpecifier() == TPResult::Error()) - return TPResult::Error(); + if (TryConsumeDeclarationSpecifier() == TPResult::Error) + return TPResult::Error; // If we see a parameter name, this can't be a template argument. if (SeenType && Tok.is(tok::identifier)) - return TPResult::True(); + return TPResult::True; - TPR = isCXXDeclarationSpecifier(TPResult::False(), + TPR = isCXXDeclarationSpecifier(TPResult::False, InvalidAsDeclaration); - if (TPR == TPResult::Error()) + if (TPR == TPResult::Error) return TPR; - } while (TPR != TPResult::False()); - } else if (TPR == TPResult::Ambiguous()) { + } while (TPR != TPResult::False); + } else if (TPR == TPResult::Ambiguous) { // Disambiguate what follows the decl-specifier. - if (TryConsumeDeclarationSpecifier() == TPResult::Error()) - return TPResult::Error(); + if (TryConsumeDeclarationSpecifier() == TPResult::Error) + return TPResult::Error; } else return TPR; // declarator // abstract-declarator[opt] TPR = TryParseDeclarator(true/*mayBeAbstract*/); - if (TPR != TPResult::Ambiguous()) + if (TPR != TPResult::Ambiguous) return TPR; // [GNU] attributes[opt] if (Tok.is(tok::kw___attribute)) - return TPResult::True(); + return TPResult::True; // If we're disambiguating a template argument in a default argument in // a class definition versus a parameter declaration, an '=' here @@ -1737,37 +1702,36 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration, // parameter-declaration-clause, and the last param is missing its default // argument. if (VersusTemplateArgument) - return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True() - : TPResult::False(); + return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True + : TPResult::False; if (Tok.is(tok::equal)) { // '=' assignment-expression // Parse through assignment-expression. // FIXME: assignment-expression may contain an unparenthesized comma. if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch)) - return TPResult::Error(); + return TPResult::Error; } if (Tok.is(tok::ellipsis)) { ConsumeToken(); if (Tok.is(tok::r_paren)) - return TPResult::True(); // '...)' is a sign of a function declarator. + return TPResult::True; // '...)' is a sign of a function declarator. else - return TPResult::False(); + return TPResult::False; } - if (Tok.isNot(tok::comma)) + if (!TryConsumeToken(tok::comma)) break; - ConsumeToken(); // the comma. } - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } /// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue /// parsing as a function declarator. /// If TryParseFunctionDeclarator fully parsed the function declarator, it will -/// return TPResult::Ambiguous(), otherwise it will return either False() or +/// return TPResult::Ambiguous, otherwise it will return either False() or /// Error(). /// /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] @@ -1781,15 +1745,15 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { // The '(' is already parsed. TPResult TPR = TryParseParameterDeclarationClause(); - if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) - TPR = TPResult::False(); + if (TPR == TPResult::Ambiguous && Tok.isNot(tok::r_paren)) + TPR = TPResult::False; - if (TPR == TPResult::False() || TPR == TPResult::Error()) + if (TPR == TPResult::False || TPR == TPResult::Error) return TPR; // Parse through the parens. if (!SkipUntil(tok::r_paren, StopAtSemi)) - return TPResult::Error(); + return TPResult::Error; // cv-qualifier-seq while (Tok.is(tok::kw_const) || @@ -1805,12 +1769,12 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { if (Tok.is(tok::kw_throw)) { ConsumeToken(); if (Tok.isNot(tok::l_paren)) - return TPResult::Error(); + return TPResult::Error; // Parse through the parens after 'throw'. ConsumeParen(); if (!SkipUntil(tok::r_paren, StopAtSemi)) - return TPResult::Error(); + return TPResult::Error; } if (Tok.is(tok::kw_noexcept)) { ConsumeToken(); @@ -1819,11 +1783,11 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { // Find the matching rparen. ConsumeParen(); if (!SkipUntil(tok::r_paren, StopAtSemi)) - return TPResult::Error(); + return TPResult::Error; } } - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } /// '[' constant-expression[opt] ']' @@ -1831,7 +1795,7 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { Parser::TPResult Parser::TryParseBracketDeclarator() { ConsumeBracket(); if (!SkipUntil(tok::r_square, StopAtSemi)) - return TPResult::Error(); + return TPResult::Error; - return TPResult::Ambiguous(); + return TPResult::Ambiguous; } diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 457dd36..37ce157 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "ParsePragma.h" #include "RAIIObjectsForParser.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" @@ -33,7 +33,7 @@ class ActionCommentHandler : public CommentHandler { public: explicit ActionCommentHandler(Sema &S) : S(S) { } - virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) { + bool HandleComment(Preprocessor &PP, SourceRange Comment) override { S.ActOnComment(Comment); return false; } @@ -56,58 +56,14 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; Tok.startToken(); Tok.setKind(tok::eof); - Actions.CurScope = 0; + Actions.CurScope = nullptr; NumCachedScopes = 0; ParenCount = BracketCount = BraceCount = 0; - CurParsedObjCImpl = 0; + CurParsedObjCImpl = nullptr; // Add #pragma handlers. These are removed and destroyed in the // destructor. - AlignHandler.reset(new PragmaAlignHandler()); - PP.AddPragmaHandler(AlignHandler.get()); - - GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); - PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); - - OptionsHandler.reset(new PragmaOptionsHandler()); - PP.AddPragmaHandler(OptionsHandler.get()); - - PackHandler.reset(new PragmaPackHandler()); - PP.AddPragmaHandler(PackHandler.get()); - - MSStructHandler.reset(new PragmaMSStructHandler()); - PP.AddPragmaHandler(MSStructHandler.get()); - - UnusedHandler.reset(new PragmaUnusedHandler()); - PP.AddPragmaHandler(UnusedHandler.get()); - - WeakHandler.reset(new PragmaWeakHandler()); - PP.AddPragmaHandler(WeakHandler.get()); - - RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); - PP.AddPragmaHandler(RedefineExtnameHandler.get()); - - FPContractHandler.reset(new PragmaFPContractHandler()); - PP.AddPragmaHandler("STDC", FPContractHandler.get()); - - if (getLangOpts().OpenCL) { - OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); - PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); - - PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); - } - if (getLangOpts().OpenMP) - OpenMPHandler.reset(new PragmaOpenMPHandler()); - else - OpenMPHandler.reset(new PragmaNoOpenMPHandler()); - PP.AddPragmaHandler(OpenMPHandler.get()); - - if (getLangOpts().MicrosoftExt) { - MSCommentHandler.reset(new PragmaCommentHandler(actions)); - PP.AddPragmaHandler(MSCommentHandler.get()); - MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions)); - PP.AddPragmaHandler(MSDetectMismatchHandler.get()); - } + initializePragmaHandlers(); CommentSemaHandler.reset(new ActionCommentHandler(actions)); PP.addCommentHandler(CommentSemaHandler.get()); @@ -152,14 +108,8 @@ static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { } } -/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the -/// input. If so, it is consumed and false is returned. -/// -/// If the input is malformed, this emits the specified diagnostic. Next, if -/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is -/// returned. bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, - const char *Msg, tok::TokenKind SkipToTok) { + StringRef Msg) { if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) { ConsumeAnyToken(); return false; @@ -168,35 +118,48 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, // Detect common single-character typos and resume. if (IsCommonTypo(ExpectedTok, Tok)) { SourceLocation Loc = Tok.getLocation(); - Diag(Loc, DiagID) - << Msg - << FixItHint::CreateReplacement(SourceRange(Loc), - getTokenSimpleSpelling(ExpectedTok)); - ConsumeAnyToken(); + { + DiagnosticBuilder DB = Diag(Loc, DiagID); + DB << FixItHint::CreateReplacement( + SourceRange(Loc), tok::getPunctuatorSpelling(ExpectedTok)); + if (DiagID == diag::err_expected) + DB << ExpectedTok; + else if (DiagID == diag::err_expected_after) + DB << Msg << ExpectedTok; + else + DB << Msg; + } // Pretend there wasn't a problem. + ConsumeAnyToken(); return false; } - const char *Spelling = 0; SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); - if (EndLoc.isValid() && - (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) { - // Show what code to insert to fix this problem. - Diag(EndLoc, DiagID) - << Msg - << FixItHint::CreateInsertion(EndLoc, Spelling); - } else - Diag(Tok, DiagID) << Msg; + const char *Spelling = nullptr; + if (EndLoc.isValid()) + Spelling = tok::getPunctuatorSpelling(ExpectedTok); + + DiagnosticBuilder DB = + Spelling + ? Diag(EndLoc, DiagID) << FixItHint::CreateInsertion(EndLoc, Spelling) + : Diag(Tok, DiagID); + if (DiagID == diag::err_expected) + DB << ExpectedTok; + else if (DiagID == diag::err_expected_after) + DB << Msg << ExpectedTok; + else + DB << Msg; - if (SkipToTok != tok::unknown) - SkipUntil(SkipToTok, StopAtSemi); return true; } bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { - if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) { - ConsumeToken(); + if (TryConsumeToken(tok::semi)) + return false; + + if (Tok.is(tok::code_completion)) { + handleUnexpectedCodeCompletionToken(); return false; } @@ -241,7 +204,8 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis) Diag(StartLoc, diag::ext_extra_semi) - << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST) + << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST, + Actions.getASTContext().getPrintingPolicy()) << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); else // A single semicolon is valid after a member function definition. @@ -288,7 +252,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { if (Toks.size() == 1 && Toks[0] == tok::eof && !HasFlagsSet(Flags, StopAtSemi) && !HasFlagsSet(Flags, StopAtCodeCompletion)) { - while (Tok.getKind() != tok::eof) + while (Tok.isNot(tok::eof)) ConsumeAnyToken(); return true; } @@ -297,10 +261,20 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { case tok::eof: // Ran out of tokens. return false; - + + case tok::annot_pragma_openmp_end: + // Stop before an OpenMP pragma boundary. + case tok::annot_module_begin: + case tok::annot_module_end: + case tok::annot_module_include: + // Stop before we change submodules. They generally indicate a "good" + // place to pick up parsing again (except in the special case where + // we're trying to skip to EOF). + return false; + case tok::code_completion: if (!HasFlagsSet(Flags, StopAtCodeCompletion)) - ConsumeToken(); + handleUnexpectedCodeCompletionToken(); return false; case tok::l_paren: @@ -391,8 +365,7 @@ void Parser::ExitScope() { // Inform the actions module that this scope is going away if there are any // decls in it. - if (!getCurScope()->decl_empty()) - Actions.ActOnPopScope(Tok.getLocation(), getCurScope()); + Actions.ActOnPopScope(Tok.getLocation(), getCurScope()); Scope *OldScope = getCurScope(); Actions.CurScope = OldScope->getParent(); @@ -407,7 +380,7 @@ void Parser::ExitScope() { /// this object does nothing. Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags) - : CurScope(ManageFlags ? Self->getCurScope() : 0) { + : CurScope(ManageFlags ? Self->getCurScope() : nullptr) { if (CurScope) { OldFlags = CurScope->getFlags(); CurScope->setFlags(ScopeFlags); @@ -429,47 +402,13 @@ Parser::ParseScopeFlags::~ParseScopeFlags() { Parser::~Parser() { // If we still have scopes active, delete the scope tree. delete getCurScope(); - Actions.CurScope = 0; - + Actions.CurScope = nullptr; + // Free the scope cache. for (unsigned i = 0, e = NumCachedScopes; i != e; ++i) delete ScopeCache[i]; - // Remove the pragma handlers we installed. - PP.RemovePragmaHandler(AlignHandler.get()); - AlignHandler.reset(); - PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get()); - GCCVisibilityHandler.reset(); - PP.RemovePragmaHandler(OptionsHandler.get()); - OptionsHandler.reset(); - PP.RemovePragmaHandler(PackHandler.get()); - PackHandler.reset(); - PP.RemovePragmaHandler(MSStructHandler.get()); - MSStructHandler.reset(); - PP.RemovePragmaHandler(UnusedHandler.get()); - UnusedHandler.reset(); - PP.RemovePragmaHandler(WeakHandler.get()); - WeakHandler.reset(); - PP.RemovePragmaHandler(RedefineExtnameHandler.get()); - RedefineExtnameHandler.reset(); - - if (getLangOpts().OpenCL) { - PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); - OpenCLExtensionHandler.reset(); - PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); - } - PP.RemovePragmaHandler(OpenMPHandler.get()); - OpenMPHandler.reset(); - - if (getLangOpts().MicrosoftExt) { - PP.RemovePragmaHandler(MSCommentHandler.get()); - MSCommentHandler.reset(); - PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); - MSDetectMismatchHandler.reset(); - } - - PP.RemovePragmaHandler("STDC", FPContractHandler.get()); - FPContractHandler.reset(); + resetPragmaHandlers(); PP.removeCommentHandler(CommentSemaHandler.get()); @@ -482,7 +421,7 @@ Parser::~Parser() { /// void Parser::Initialize() { // Create the translation unit scope. Install it as the current scope. - assert(getCurScope() == 0 && "A scope is already active?"); + assert(getCurScope() == nullptr && "A scope is already active?"); EnterScope(Scope::DeclScope); Actions.ActOnTranslationUnitScope(getCurScope()); @@ -497,10 +436,10 @@ void Parser::Initialize() { ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref"); } - Ident_instancetype = 0; - Ident_final = 0; - Ident_sealed = 0; - Ident_override = 0; + Ident_instancetype = nullptr; + Ident_final = nullptr; + Ident_sealed = nullptr; + Ident_override = nullptr; Ident_super = &PP.getIdentifierTable().get("super"); @@ -510,16 +449,18 @@ void Parser::Initialize() { Ident_bool = &PP.getIdentifierTable().get("bool"); } - Ident_introduced = 0; - Ident_deprecated = 0; - Ident_obsoleted = 0; - Ident_unavailable = 0; + Ident_introduced = nullptr; + Ident_deprecated = nullptr; + Ident_obsoleted = nullptr; + Ident_unavailable = nullptr; - Ident__except = 0; - - Ident__exception_code = Ident__exception_info = Ident__abnormal_termination = 0; - Ident___exception_code = Ident___exception_info = Ident___abnormal_termination = 0; - Ident_GetExceptionCode = Ident_GetExceptionInfo = Ident_AbnormalTermination = 0; + Ident__except = nullptr; + + Ident__exception_code = Ident__exception_info = nullptr; + Ident__abnormal_termination = Ident___exception_code = nullptr; + Ident___exception_info = Ident___abnormal_termination = nullptr; + Ident_GetExceptionCode = Ident_GetExceptionInfo = nullptr; + Ident_AbnormalTermination = nullptr; if(getLangOpts().Borland) { Ident__exception_info = PP.getIdentifierInfo("_exception_info"); @@ -574,7 +515,7 @@ namespace { bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds); - // Skip over the EOF token, flagging end of previous input for incremental + // Skip over the EOF token, flagging end of previous input for incremental // processing if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) ConsumeToken(); @@ -592,6 +533,12 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { ConsumeToken(); return false; + case tok::annot_module_begin: + case tok::annot_module_end: + // FIXME: Update visibility based on the submodule we're in. + ConsumeToken(); + return false; + case tok::eof: // Late template parsing can begin. if (getLangOpts().DelayedTemplateParsing) @@ -647,7 +594,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return DeclGroupPtrTy(); } - Decl *SingleDecl = 0; + Decl *SingleDecl = nullptr; switch (Tok.getKind()) { case tok::annot_pragma_vis: HandlePragmaVisibility(); @@ -679,6 +626,15 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_openmp: ParseOpenMPDeclarativeDirective(); return DeclGroupPtrTy(); + case tok::annot_pragma_ms_pointers_to_members: + HandlePragmaMSPointersToMembers(); + return DeclGroupPtrTy(); + case tok::annot_pragma_ms_vtordisp: + HandlePragmaMSVtorDisp(); + return DeclGroupPtrTy(); + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + return DeclGroupPtrTy(); case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), @@ -706,7 +662,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, SourceLocation EndLoc; ExprResult Result(ParseSimpleAsm(&EndLoc)); - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, + ExpectAndConsume(tok::semi, diag::err_expected_after, "top-level asm block"); if (Result.isInvalid()) @@ -793,7 +749,6 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParseExplicitInstantiation(Declarator::FileContext, ExternLoc, TemplateLoc, DeclEnd)); } - // FIXME: Detect C++ linkage specifications here? goto dont_know; case tok::kw___if_exists: @@ -907,9 +862,10 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, DS.abort(); - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; - if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID)) + if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID, + Actions.getASTContext().getPrintingPolicy())) Diag(AtLoc, DiagID) << PrevSpec; if (Tok.isObjCAtKeyword(tok::objc_protocol)) @@ -922,7 +878,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, // If the declspec consisted only of 'extern' and we have a string // literal following it, this must be a C++ linkage specifier like // 'extern "C"'. - if (Tok.is(tok::string_literal) && getLangOpts().CPlusPlus && + if (getLangOpts().CPlusPlus && isTokenStringLiteral() && DS.getStorageClassSpec() == DeclSpec::SCS_extern && DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext); @@ -949,26 +905,6 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs, } } - -static inline bool isFunctionDeclaratorRequiringReturnTypeDeduction( - const Declarator &D) { - if (!D.isFunctionDeclarator() || !D.getDeclSpec().containsPlaceholderType()) - return false; - for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) { - unsigned chunkIndex = E - I - 1; - const DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); - if (DeclType.Kind == DeclaratorChunk::Function) { - const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - if (!FTI.hasTrailingReturnType()) - return true; - QualType TrailingRetType = FTI.getTrailingReturnType().get(); - return TrailingRetType->getCanonicalTypeInternal() - ->getContainedAutoType(); - } - } - return false; -} - /// ParseFunctionDefinition - We parsed and verified that the specified /// Declarator is well formed. If this is a K&R-style function, read the /// parameters declaration-list, then start the compound-statement. @@ -996,9 +932,11 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (getLangOpts().ImplicitInt && D.getDeclSpec().isEmpty()) { const char *PrevSpec; unsigned DiagID; + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int, D.getIdentifierLoc(), - PrevSpec, DiagID); + PrevSpec, DiagID, + Policy); D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin()); } @@ -1021,7 +959,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // If we didn't find the '{', bail out. if (Tok.isNot(tok::l_brace)) - return 0; + return nullptr; } // Check to make sure that any normal attributes are allowed to be on @@ -1029,10 +967,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (Tok.isNot(tok::equal)) { AttributeList *DtorAttrs = D.getAttributes(); while (DtorAttrs) { - if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName()) && + if (DtorAttrs->isKnownToGCC() && !DtorAttrs->isCXX11Attribute()) { Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) - << DtorAttrs->getName()->getName(); + << DtorAttrs->getName(); } DtorAttrs = DtorAttrs->getNext(); } @@ -1042,8 +980,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // tokens and store them for late parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && TemplateInfo.Kind == ParsedTemplateInfo::Template && - !D.getDeclSpec().isConstexprSpecified() && - !isFunctionDeclaratorRequiringReturnTypeDeduction(D)) { + Actions.canDelayFunctionBody(D)) { MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -1059,12 +996,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, LexTemplateFunctionForLateParsing(Toks); if (DP) { - FunctionDecl *FnD = 0; - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(DP)) - FnD = FunTmpl->getTemplatedDecl(); - else - FnD = cast<FunctionDecl>(DP); - + FunctionDecl *FnD = DP->getAsFunction(); Actions.CheckForFunctionRedefinition(FnD); Actions.MarkAsLateParsedTemplate(FnD, DP, Toks); } @@ -1077,7 +1009,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, Actions.CurContext->isTranslationUnit()) { ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); - + D.setFunctionDefinitionKind(FDK_Definition); Decl *FuncDecl = Actions.HandleDeclarator(ParentScope, D, MultiTemplateParamsArg()); @@ -1089,8 +1021,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, CurParsedObjCImpl->HasCFunction = true; return FuncDecl; } + // FIXME: Should we really fall through here? } - + // Enter a scope for the function body. ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -1108,28 +1041,22 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // safe because we're always the sole owner. D.getMutableDeclSpec().abort(); - if (Tok.is(tok::equal)) { + if (TryConsumeToken(tok::equal)) { assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='"); - ConsumeToken(); + Actions.ActOnFinishFunctionBody(Res, nullptr, false); - Actions.ActOnFinishFunctionBody(Res, 0, false); - bool Delete = false; SourceLocation KWLoc; - if (Tok.is(tok::kw_delete)) { - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_deleted_function : - diag::ext_deleted_function); - - KWLoc = ConsumeToken(); + if (TryConsumeToken(tok::kw_delete, KWLoc)) { + Diag(KWLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_deleted_function + : diag::ext_deleted_function); Actions.SetDeclDeleted(Res, KWLoc); Delete = true; - } else if (Tok.is(tok::kw_default)) { - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_defaulted_function : - diag::ext_defaulted_function); - - KWLoc = ConsumeToken(); + } else if (TryConsumeToken(tok::kw_default, KWLoc)) { + Diag(KWLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_defaulted_function + : diag::ext_defaulted_function); Actions.SetDeclDefaulted(Res, KWLoc); } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); @@ -1139,9 +1066,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) << Delete; SkipUntil(tok::semi); - } else { - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - Delete ? "delete" : "default", tok::semi); + } else if (ExpectAndConsume(tok::semi, diag::err_expected_after, + Delete ? "delete" : "default")) { + SkipUntil(tok::semi); } return Res; @@ -1158,7 +1085,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Recover from error. if (!Tok.is(tok::l_brace)) { BodyScope.Exit(); - Actions.ActOnFinishFunctionBody(Res, 0); + Actions.ActOnFinishFunctionBody(Res, nullptr); return Res; } } else @@ -1195,9 +1122,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // NOTE: GCC just makes this an ext-warn. It's not clear what it does with // the declarations though. It's trivial to ignore them, really hard to do // anything else with them. - if (Tok.is(tok::semi)) { + if (TryConsumeToken(tok::semi)) { Diag(DSStart, diag::err_declaration_does_not_declare_param); - ConsumeToken(); continue; } @@ -1237,20 +1163,20 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { for (unsigned i = 0; ; ++i) { // C99 6.9.1p6: those declarators shall declare only identifiers from // the identifier list. - if (i == FTI.NumArgs) { + if (i == FTI.NumParams) { Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param) << ParmDeclarator.getIdentifier(); break; } - if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) { + if (FTI.Params[i].Ident == ParmDeclarator.getIdentifier()) { // Reject redefinitions of parameters. - if (FTI.ArgInfo[i].Param) { + if (FTI.Params[i].Param) { Diag(ParmDeclarator.getIdentifierLoc(), diag::err_param_redefinition) << ParmDeclarator.getIdentifier(); } else { - FTI.ArgInfo[i].Param = Param; + FTI.Params[i].Param = Param; } break; } @@ -1271,12 +1197,14 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { ParseDeclarator(ParmDeclarator); } - if (ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) { - // Skip to end of block or statement - SkipUntil(tok::semi); - if (Tok.is(tok::semi)) - ConsumeToken(); - } + // Consume ';' and continue parsing. + if (!ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) + continue; + + // Otherwise recover by skipping to next semi or mandatory function body. + if (SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch)) + break; + TryConsumeToken(tok::semi); } // The actions module must verify that all arguments were declared. @@ -1340,16 +1268,15 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { ExprResult Result(ParseAsmStringLiteral()); - if (Result.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); - if (EndLoc) - *EndLoc = Tok.getLocation(); - ConsumeAnyToken(); - } else { + if (!Result.isInvalid()) { // Close the paren and get the location of the end bracket T.consumeClose(); if (EndLoc) *EndLoc = T.getCloseLocation(); + } else if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) { + if (EndLoc) + *EndLoc = Tok.getLocation(); + ConsumeParen(); } return Result; @@ -1430,11 +1357,11 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, // Look up and classify the identifier. We don't perform any typo-correction // after a scope specifier, because in general we can't recover from typos - // there (eg, after correcting 'A::tempalte B<X>::C', we would need to jump - // back into scope specifier parsing). + // there (eg, after correcting 'A::tempalte B<X>::C' [sic], we would need to + // jump back into scope specifier parsing). Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next, - IsAddressOfOperand, SS.isEmpty() ? CCC : 0); + IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr); switch (Classification.getKind()) { case Sema::NC_Error: @@ -1504,16 +1431,34 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, } bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { - assert(Tok.isNot(tok::identifier)); + assert(!Tok.is(tok::identifier) && !Tok.isAnnotation()); Diag(Tok, diag::ext_keyword_as_ident) << PP.getSpelling(Tok) << DisableKeyword; - if (DisableKeyword) - Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); + if (DisableKeyword) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + ContextualKeywords[II] = Tok.getKind(); + II->RevertTokenIDToIdentifier(); + } Tok.setKind(tok::identifier); return true; } +bool Parser::TryIdentKeywordUpgrade() { + assert(Tok.is(tok::identifier)); + const IdentifierInfo *II = Tok.getIdentifierInfo(); + assert(II->hasRevertedTokenIDToIdentifier()); + // If we find that this is in fact the name of a type trait, + // update the token kind in place and parse again to treat it as + // the appropriate kind of type trait. + llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind>::iterator Known = + ContextualKeywords.find(II); + if (Known == ContextualKeywords.end()) + return false; + Tok.setKind(Known->second); + return true; +} + /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens @@ -1549,7 +1494,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { // We will consume the typedef token here and put it back after we have // parsed the first identifier, transforming it into something more like: // typename T_::D typedef D; - if (getLangOpts().MicrosoftMode && NextToken().is(tok::kw_typedef)) { + if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) { Token TypedefToken; PP.Lex(TypedefToken); bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType); @@ -1570,7 +1515,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { CXXScopeSpec SS; if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), /*EnteringContext=*/false, - 0, /*IsTypename*/true)) + nullptr, /*IsTypename*/ true)) return true; if (!SS.isSet()) { if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) || @@ -1601,7 +1546,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { Tok.getLocation()); } else if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); - if (TemplateId->Kind == TNK_Function_template) { + if (TemplateId->Kind != TNK_Type_template && + TemplateId->Kind != TNK_Dependent_template_name) { Diag(Tok, diag::err_typename_refers_to_non_type_template) << Tok.getAnnotationRange(); return true; @@ -1652,7 +1598,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, CXXScopeSpec &SS, bool IsNewScope) { if (Tok.is(tok::identifier)) { - IdentifierInfo *CorrectedII = 0; + IdentifierInfo *CorrectedII = nullptr; // Determine whether the identifier is a type name. if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), @@ -1660,8 +1606,9 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, NextToken().is(tok::period), ParsedType(), /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo*/true, - NeedType ? &CorrectedII : NULL)) { + /*NonTrivialTypeSourceInfo*/ true, + NeedType ? &CorrectedII + : nullptr)) { // A FixIt was applied as a result of typo correction if (CorrectedII) Tok.setIdentifierInfo(CorrectedII); @@ -1725,8 +1672,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, // annotation token to a type annotation token now. AnnotateTemplateIdTokenAsType(); return false; - } else if (TemplateId->Kind == TNK_Var_template) - return false; + } } if (SS.isEmpty()) @@ -1780,8 +1726,8 @@ bool Parser::isTokenEqualOrEqualTypo() { case tok::pipeequal: // |= case tok::equalequal: // == Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) - << getTokenSimpleSpelling(Kind) - << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); + << Kind + << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); case tok::equal: return true; } @@ -1910,7 +1856,7 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return; } @@ -1928,14 +1874,15 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { } // Parse the declarations. - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + // FIXME: Support module import within __if_exists? + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); DeclGroupPtrTy Result = ParseExternalDeclaration(attrs); if (Result && !getCurScope()->getParent()) Actions.getASTConsumer().HandleTopLevelDecl(Result.get()); - } + } Braces.consumeClose(); } @@ -1951,8 +1898,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) { if (!Tok.is(tok::identifier)) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteModuleImport(ImportLoc, Path); - ConsumeCodeCompletionToken(); - SkipUntil(tok::semi); + cutOffParsing(); return DeclGroupPtrTy(); } @@ -1991,17 +1937,20 @@ bool BalancedDelimiterTracker::diagnoseOverflow() { P.Diag(P.Tok, diag::err_bracket_depth_exceeded) << P.getLangOpts().BracketDepth; P.Diag(P.Tok, diag::note_bracket_depth); - P.SkipUntil(tok::eof); - return true; + P.cutOffParsing(); + return true; } bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, - const char *Msg, - tok::TokenKind SkipToToc ) { + const char *Msg, + tok::TokenKind SkipToTok) { LOpen = P.Tok.getLocation(); - if (P.ExpectAndConsume(Kind, DiagID, Msg, SkipToToc)) + if (P.ExpectAndConsume(Kind, DiagID, Msg)) { + if (SkipToTok != tok::unknown) + P.SkipUntil(SkipToTok, Parser::StopAtSemi); return true; - + } + if (getDepth() < MaxDepth) return false; @@ -2010,17 +1959,9 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, bool BalancedDelimiterTracker::diagnoseMissingClose() { assert(!P.Tok.is(Close) && "Should have consumed closing delimiter"); - - const char *LHSName = "unknown"; - diag::kind DID; - switch (Close) { - default: llvm_unreachable("Unexpected balanced token"); - 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; - } - P.Diag(P.Tok, DID); - P.Diag(LOpen, diag::note_matching) << LHSName; + + P.Diag(P.Tok, diag::err_expected) << Close; + P.Diag(LOpen, diag::note_matching) << Kind; // If we're not already at some kind of closing bracket, skip to our closing // token. diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h index f68a2e0..4f5f3ab 100644 --- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h +++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h @@ -50,7 +50,7 @@ namespace clang { public: /// Begin suppressing access-like checks SuppressAccessChecks(Parser &P, bool activate = true) - : S(P.getActions()), DiagnosticPool(NULL) { + : S(P.getActions()), DiagnosticPool(nullptr) { if (activate) { State = S.PushParsingDeclaration(DiagnosticPool); Active = true; @@ -61,7 +61,7 @@ namespace clang { void done() { assert(Active && "trying to end an inactive suppression"); - S.PopParsingDeclaration(State, NULL); + S.PopParsingDeclaration(State, nullptr); Active = false; } @@ -93,7 +93,7 @@ namespace clang { public: enum NoParent_t { NoParent }; ParsingDeclRAIIObject(Parser &P, NoParent_t _) - : Actions(P.getActions()), DiagnosticPool(NULL) { + : Actions(P.getActions()), DiagnosticPool(nullptr) { push(); } @@ -109,7 +109,7 @@ namespace clang { /// RAII object (which is assumed to be the current top pool). ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other) : Actions(P.getActions()), - DiagnosticPool(other ? other->DiagnosticPool.getParent() : NULL) { + DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) { if (other) { DiagnosticPool.steal(other->DiagnosticPool); other->abort(); @@ -137,7 +137,7 @@ namespace clang { /// Signals that the context was completed without an appropriate /// declaration being parsed. void abort() { - pop(0); + pop(nullptr); } void complete(Decl *D) { @@ -148,7 +148,7 @@ namespace clang { /// Unregister this object from Sema, but remember all the /// diagnostics that were emitted into it. void abortAndRemember() { - pop(0); + pop(nullptr); } private: @@ -415,8 +415,8 @@ namespace clang { return diagnoseOverflow(); } - - bool expectAndConsume(unsigned DiagID, + + bool expectAndConsume(unsigned DiagID = diag::err_expected, const char *Msg = "", tok::TokenKind SkipToTok = tok::unknown); bool consumeClose() { |