diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
16 files changed, 1658 insertions, 723 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp index 0f5a1b3..6727afc 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseAST.cpp @@ -14,7 +14,6 @@ #include "clang/Parse/ParseAST.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Stmt.h" #include "clang/Parse/ParseDiagnostic.h" @@ -146,10 +145,8 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { } // Process any TopLevelDecls generated by #pragma weak. - for (SmallVectorImpl<Decl *>::iterator - I = S.WeakTopLevelDecls().begin(), - E = S.WeakTopLevelDecls().end(); I != E; ++I) - Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); + for (Decl *D : S.WeakTopLevelDecls()) + Consumer->HandleTopLevelDecl(DeclGroupRef(D)); Consumer->HandleTranslationUnit(S.getASTContext()); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index 30a9120..59b491a 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -218,6 +218,7 @@ void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) { Eof.startToken(); Eof.setKind(tok::eof); Eof.setLocation(Tok.getLocation()); + Eof.setEofData(VarD); Toks.push_back(Eof); } @@ -308,10 +309,17 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Introduce the parameter into scope. Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); - if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { - // Save the current token position. - SourceLocation origLoc = Tok.getLocation(); + // Mark the end of the default argument so that we know when to stop when + // we parse it later on. + Token LastDefaultArgToken = Toks->back(); + Token DefArgEnd; + DefArgEnd.startToken(); + DefArgEnd.setKind(tok::eof); + DefArgEnd.setLocation(LastDefaultArgToken.getLocation().getLocWithOffset( + LastDefaultArgToken.getLength())); + DefArgEnd.setEofData(LM.DefaultArgs[I].Param); + Toks->push_back(DefArgEnd); // Parse the default argument from its saved token stream. Toks->push_back(Tok); // So that the current token doesn't get lost @@ -336,11 +344,13 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { DefArgResult = ParseBraceInitializer(); } else DefArgResult = ParseAssignmentExpression(); - if (DefArgResult.isInvalid()) + DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult); + if (DefArgResult.isInvalid()) { Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param, EqualLoc); - else { - if (!TryConsumeToken(tok::cxx_defaultarg_end)) { + } else { + if (Tok.isNot(tok::eof) || + Tok.getEofData() != LM.DefaultArgs[I].Param) { // 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. @@ -353,12 +363,12 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { DefArgResult.get()); } - assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, - Tok.getLocation()) && - "ParseAssignmentExpression went over the default arg tokens!"); // There could be leftover tokens (e.g. because of an error). - // Skip through until we reach the original token position. - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + // Skip through until we reach the 'end of default argument' token. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.DefaultArgs[I].Param) ConsumeAnyToken(); delete Toks; @@ -366,6 +376,80 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { } } + // Parse a delayed exception-specification, if there is one. + if (CachedTokens *Toks = LM.ExceptionSpecTokens) { + // Add the 'stop' token. + Token LastExceptionSpecToken = Toks->back(); + Token ExceptionSpecEnd; + ExceptionSpecEnd.startToken(); + ExceptionSpecEnd.setKind(tok::eof); + ExceptionSpecEnd.setLocation( + LastExceptionSpecToken.getLocation().getLocWithOffset( + LastExceptionSpecToken.getLength())); + ExceptionSpecEnd.setEofData(LM.Method); + Toks->push_back(ExceptionSpecEnd); + + // Parse the default argument from its saved token stream. + Toks->push_back(Tok); // So that the current token doesn't get lost + PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); + + // Consume the previously-pushed token. + ConsumeAnyToken(); + + // C++11 [expr.prim.general]p3: + // If a declaration declares a member function or member function + // template of a class X, the expression this is a prvalue of type + // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq + // and the end of the function-definition, member-declarator, or + // declarator. + CXXMethodDecl *Method; + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(LM.Method)) + Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + else + Method = cast<CXXMethodDecl>(LM.Method); + + Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(), + Method->getTypeQualifiers(), + getLangOpts().CPlusPlus11); + + // Parse the exception-specification. + SourceRange SpecificationRange; + SmallVector<ParsedType, 4> DynamicExceptions; + SmallVector<SourceRange, 4> DynamicExceptionRanges; + ExprResult NoexceptExpr; + CachedTokens *ExceptionSpecTokens; + + ExceptionSpecificationType EST + = tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges, NoexceptExpr, + ExceptionSpecTokens); + + if (Tok.isNot(tok::eof) || Tok.getEofData() != LM.Method) + Diag(Tok.getLocation(), diag::err_except_spec_unparsed); + + // Attach the exception-specification to the method. + Actions.actOnDelayedExceptionSpecification(LM.Method, EST, + SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr.isUsable()? + NoexceptExpr.get() : nullptr); + + // There could be leftover tokens (e.g. because of an error). + // Skip through until we reach the original token position. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + // Clean up the remaining EOF token. + if (Tok.is(tok::eof) && Tok.getEofData() == LM.Method) + ConsumeAnyToken(); + + delete Toks; + LM.ExceptionSpecTokens = nullptr; + } + PrototypeScope.Exit(); // Finish the delayed C++ method declaration. @@ -400,10 +484,16 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); ++CurTemplateDepthTracker; } - // Save the current token position. - SourceLocation origLoc = Tok.getLocation(); assert(!LM.Toks.empty() && "Empty body!"); + Token LastBodyToken = LM.Toks.back(); + Token BodyEnd; + BodyEnd.startToken(); + BodyEnd.setKind(tok::eof); + BodyEnd.setLocation( + LastBodyToken.getLocation().getLocWithOffset(LastBodyToken.getLength())); + BodyEnd.setEofData(LM.D); + LM.Toks.push_back(BodyEnd); // Append the current token at the end of the new token stream so that it // doesn't get lost. LM.Toks.push_back(Tok); @@ -421,12 +511,11 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { if (Tok.is(tok::kw_try)) { ParseFunctionTryBlock(LM.D, FnScope); - assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, - Tok.getLocation()) && - "ParseFunctionTryBlock went over the cached tokens!"); - // There could be leftover tokens (e.g. because of an error). - // Skip through until we reach the original token position. - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.D) ConsumeAnyToken(); return; } @@ -437,7 +526,11 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { if (!Tok.is(tok::l_brace)) { FnScope.Exit(); Actions.ActOnFinishFunctionBody(LM.D, nullptr); - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.D) ConsumeAnyToken(); return; } @@ -457,17 +550,11 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { if (LM.D) LM.D->getAsFunction()->setLateTemplateParsed(false); - if (Tok.getLocation() != origLoc) { - // Due to parsing error, we either went over the cached tokens or - // there are still cached tokens left. If it's the latter case skip the - // leftover tokens. - // Since this is an uncommon situation that should be avoided, use the - // expensive isBeforeInTranslationUnit call. - if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), - origLoc)) - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) - ConsumeAnyToken(); - } + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.D) + ConsumeAnyToken(); if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D)) Actions.ActOnFinishInlineMethodDef(MD); @@ -540,17 +627,21 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { // The next token should be our artificial terminating EOF token. if (Tok.isNot(tok::eof)) { - SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); - if (!EndLoc.isValid()) - EndLoc = Tok.getLocation(); - // No fixit; we can't recover as if there were a semicolon here. - Diag(EndLoc, diag::err_expected_semi_decl_list); + if (!Init.isInvalid()) { + SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); + if (!EndLoc.isValid()) + EndLoc = Tok.getLocation(); + // No fixit; we can't recover as if there were a semicolon here. + Diag(EndLoc, diag::err_expected_semi_decl_list); + } // Consume tokens until we hit the artificial EOF. while (Tok.isNot(tok::eof)) ConsumeAnyToken(); } - ConsumeAnyToken(); + // Make sure this is *our* artificial EOF token. + if (Tok.getEofData() == MI.Field) + ConsumeAnyToken(); } /// ConsumeAndStoreUntil - Consume and store the token at the passed token @@ -891,11 +982,13 @@ private: /// ConsumeAndStoreInitializer - Consume and store the token at the passed token /// container until the end of the current initializer expression (either a /// default argument or an in-class initializer for a non-static data member). -/// The final token is not consumed. +/// +/// Returns \c true if we reached the end of something initializer-shaped, +/// \c false if we bailed out. bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, CachedInitKind CIK) { // We always want this function to consume at least one token if not at EOF. - bool IsFirstTokenConsumed = true; + bool IsFirstToken = true; // Number of possible unclosed <s we've seen so far. These might be templates, // and might not, but if there were none of them (or we know for sure that @@ -942,7 +1035,7 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, case CIK_DefaultArgument: bool InvalidAsDeclaration = false; Result = TryParseParameterDeclarationClause( - &InvalidAsDeclaration, /*VersusTemplateArgument*/true); + &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) @@ -1014,6 +1107,7 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, Toks.push_back(Tok); ConsumeToken(); if (Tok.is(tok::less)) { + ++AngleCount; ++KnownTemplateCount; Toks.push_back(Tok); ConsumeToken(); @@ -1063,21 +1157,28 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, // Since the user wasn't looking for this token (if they were, it would // already be handled), this isn't balanced. If there is a LHS token at a // higher level, we will assume that this matches the unbalanced token - // and return it. Otherwise, this is a spurious RHS token, which we skip. + // and return it. Otherwise, this is a spurious RHS token, which we + // consume and pass on to downstream code to diagnose. case tok::r_paren: if (CIK == CIK_DefaultArgument) return true; // End of the default argument. - if (ParenCount && !IsFirstTokenConsumed) - return false; // Matches something. - goto consume_token; + if (ParenCount && !IsFirstToken) + return false; + Toks.push_back(Tok); + ConsumeParen(); + continue; case tok::r_square: - if (BracketCount && !IsFirstTokenConsumed) - return false; // Matches something. - goto consume_token; + if (BracketCount && !IsFirstToken) + return false; + Toks.push_back(Tok); + ConsumeBracket(); + continue; case tok::r_brace: - if (BraceCount && !IsFirstTokenConsumed) - return false; // Matches something. - goto consume_token; + if (BraceCount && !IsFirstToken) + return false; + Toks.push_back(Tok); + ConsumeBrace(); + continue; case tok::code_completion: Toks.push_back(Tok); @@ -1102,6 +1203,6 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, ConsumeToken(); break; } - IsFirstTokenConsumed = false; + IsFirstToken = false; } } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 62d4376..4d05e16 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -143,10 +143,12 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, continue; // Expect an identifier or declaration specifier (const, int, etc.) - if (Tok.isNot(tok::identifier) && !isDeclarationSpecifier()) + if (Tok.isAnnotation()) break; - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + if (!AttrName) + break; + SourceLocation AttrNameLoc = ConsumeToken(); if (Tok.isNot(tok::l_paren)) { @@ -302,7 +304,8 @@ unsigned Parser::ParseAttributeArgsCommon( Unevaluated.reset( new EnterExpressionEvaluationContext(Actions, Sema::Unevaluated)); - ExprResult ArgExpr(ParseAssignmentExpression()); + ExprResult ArgExpr( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); if (ArgExpr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return 0; @@ -588,15 +591,64 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) { void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { // Treat these like attributes - while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) || - Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___cdecl) || - Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64) || - Tok.is(tok::kw___ptr32) || Tok.is(tok::kw___unaligned) || - Tok.is(tok::kw___sptr) || Tok.is(tok::kw___uptr)) { - IdentifierInfo *AttrName = Tok.getIdentifierInfo(); - SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + while (true) { + switch (Tok.getKind()) { + case tok::kw___fastcall: + case tok::kw___stdcall: + case tok::kw___thiscall: + case tok::kw___cdecl: + case tok::kw___vectorcall: + case tok::kw___ptr64: + case tok::kw___w64: + case tok::kw___ptr32: + case tok::kw___unaligned: + case tok::kw___sptr: + case tok::kw___uptr: { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + SourceLocation AttrNameLoc = ConsumeToken(); + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + AttributeList::AS_Keyword); + break; + } + default: + return; + } + } +} + +void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() { + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes(); + + if (EndLoc.isValid()) { + SourceRange Range(StartLoc, EndLoc); + Diag(StartLoc, diag::warn_microsoft_qualifiers_ignored) << Range; + } +} + +SourceLocation Parser::SkipExtendedMicrosoftTypeAttributes() { + SourceLocation EndLoc; + + while (true) { + switch (Tok.getKind()) { + case tok::kw_const: + case tok::kw_volatile: + case tok::kw___fastcall: + case tok::kw___stdcall: + case tok::kw___thiscall: + case tok::kw___cdecl: + case tok::kw___vectorcall: + case tok::kw___ptr32: + case tok::kw___ptr64: + case tok::kw___w64: + case tok::kw___unaligned: + case tok::kw___sptr: + case tok::kw___uptr: + EndLoc = ConsumeToken(); + break; + default: + return EndLoc; + } } } @@ -627,6 +679,10 @@ void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { AttributeList::AS_Keyword); } +static bool VersionNumberSeparator(const char Separator) { + return (Separator == '.' || Separator == '_'); +} + /// \brief Parse a version number. /// /// version: @@ -684,7 +740,9 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(Major); } - if (ThisTokBegin[AfterMajor] != '.' || (AfterMajor + 1 == ActualLength)) { + const char AfterMajorSeparator = ThisTokBegin[AfterMajor]; + if (!VersionNumberSeparator(AfterMajorSeparator) + || (AfterMajor + 1 == ActualLength)) { Diag(Tok, diag::err_expected_version); SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); @@ -708,16 +766,21 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(); } - return VersionTuple(Major, Minor); + return VersionTuple(Major, Minor, (AfterMajorSeparator == '_')); } - // If what follows is not a '.', we have a problem. - if (ThisTokBegin[AfterMinor] != '.') { + const char AfterMinorSeparator = ThisTokBegin[AfterMinor]; + // If what follows is not a '.' or '_', we have a problem. + if (!VersionNumberSeparator(AfterMinorSeparator)) { Diag(Tok, diag::err_expected_version); SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch | StopAtCodeCompletion); return VersionTuple(); } + + // Warn if separators, be it '.' or '_', do not match. + if (AfterMajorSeparator != AfterMinorSeparator) + Diag(Tok, diag::warn_expected_consistent_version_separator); // Parse the subminor version. unsigned AfterSubminor = AfterMinor + 1; @@ -734,7 +797,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(); } ConsumeToken(); - return VersionTuple(Major, Minor, Subminor); + return VersionTuple(Major, Minor, Subminor, (AfterMajorSeparator == '_')); } /// \brief Parse the contents of the "availability" attribute. @@ -846,6 +909,19 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, break; } + // Special handling of 'NA' only when applied to introduced or + // deprecated. + if ((Keyword == Ident_introduced || Keyword == Ident_deprecated) && + Tok.is(tok::identifier)) { + IdentifierInfo *NA = Tok.getIdentifierInfo(); + if (NA->getName() == "NA") { + ConsumeToken(); + if (Keyword == Ident_introduced) + UnavailableLoc = KeywordLoc; + continue; + } + } + SourceRange VersionRange; VersionTuple Version = ParseVersionTuple(VersionRange); @@ -1071,8 +1147,14 @@ void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, /// to the Attribute list for the decl. void Parser::ParseLexedAttribute(LateParsedAttribute &LA, bool EnterScope, bool OnDefinition) { - // Save the current token position. - SourceLocation OrigLoc = Tok.getLocation(); + // Create a fake EOF so that attribute parsing won't go off the end of the + // attribute. + Token AttrEnd; + AttrEnd.startToken(); + AttrEnd.setKind(tok::eof); + AttrEnd.setLocation(Tok.getLocation()); + AttrEnd.setEofData(LA.Toks.data()); + LA.Toks.push_back(AttrEnd); // Append the current token at the end of the new token stream so that it // doesn't get lost. @@ -1137,16 +1219,13 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, 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 - // there are still cached tokens left, so we skip the leftover tokens. - // Since this is an uncommon situation that should be avoided, use the - // expensive isBeforeInTranslationUnit call. - if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), - OrigLoc)) - while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) - ConsumeAnyToken(); - } + // Due to a parsing error, we either went over the cached tokens or + // there are still cached tokens left, so we skip the leftover tokens. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData()) + ConsumeAnyToken(); } void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, @@ -1297,8 +1376,7 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) { /// [C++11/C11] static_assert-declaration /// others... [FIXME] /// -Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, - unsigned Context, +Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs) { ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -1322,7 +1400,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc); break; } - return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs, + return ParseSimpleDeclaration(Context, DeclEnd, attrs, true); case tok::kw_namespace: ProhibitAttributes(attrs); @@ -1338,7 +1416,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs, true); + return ParseSimpleDeclaration(Context, DeclEnd, attrs, true); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -1364,7 +1442,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, /// of a simple-declaration. If we find that we are, we also parse the /// for-range-initializer, and place it here. Parser::DeclGroupPtrTy -Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context, +Parser::ParseSimpleDeclaration(unsigned Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI) { @@ -1393,7 +1471,7 @@ Parser::ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context, } DS.takeAttributesFrom(Attrs); - return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd, FRI); + return ParseDeclGroup(DS, Context, &DeclEnd, FRI); } /// Returns true if this might be the start of a declarator, or a common typo @@ -1548,7 +1626,6 @@ void Parser::SkipMalformedDecl() { /// result. Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, - bool AllowFunctionDefinitions, SourceLocation *DeclEnd, ForRangeInit *FRI) { // Parse the first declarator. @@ -1565,9 +1642,30 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // appropriate function scope after the function Decl has been constructed. // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList. LateParsedAttrList LateParsedAttrs(true); - if (D.isFunctionDeclarator()) + if (D.isFunctionDeclarator()) { MaybeParseGNUAttributes(D, &LateParsedAttrs); + // The _Noreturn keyword can't appear here, unlike the GNU noreturn + // attribute. If we find the keyword here, tell the user to put it + // at the start instead. + if (Tok.is(tok::kw__Noreturn)) { + SourceLocation Loc = ConsumeToken(); + const char *PrevSpec; + unsigned DiagID; + + // We can offer a fixit if it's valid to mark this function as _Noreturn + // and we don't have any other declarators in this declaration. + bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID); + MaybeParseGNUAttributes(D, &LateParsedAttrs); + Fixit &= Tok.is(tok::semi) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try); + + Diag(Loc, diag::err_c11_noreturn_misplaced) + << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint()) + << (Fixit ? FixItHint::CreateInsertion(D.getLocStart(), "_Noreturn ") + : FixItHint()); + } + } + // Check to see if we have a function *definition* which must have a body. if (D.isFunctionDeclarator() && // Look at the next token to make sure that this isn't a function @@ -1575,7 +1673,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // start of a function definition in GCC-extended K&R C. !isDeclarationAfterDeclarator()) { - if (AllowFunctionDefinitions) { + // Function definitions are only allowed at file scope and in C++ classes. + // The C++ inline method definition case is handled elsewhere, so we only + // need to handle the file scope definition case. + if (Context == Declarator::FileContext) { if (isStartOfFunctionDefinition(D)) { if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { Diag(Tok, diag::err_function_declared_typedef); @@ -1674,6 +1775,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // short x, __attribute__((common)) var; -> declarator MaybeParseGNUAttributes(D); + // MSVC parses but ignores qualifiers after the comma as an extension. + if (getLangOpts().MicrosoftExt) + DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); + ParseDeclarator(D); if (!D.isInvalidType()) { Decl *ThisDecl = ParseDeclarationAfterDeclarator(D); @@ -2449,8 +2554,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs) { if (DS.getSourceRange().isInvalid()) { + // Start the range at the current token but make the end of the range + // invalid. This will make the entire range invalid unless we successfully + // consume a token. DS.SetRangeStart(Tok.getLocation()); - DS.SetRangeEnd(Tok.getLocation()); + DS.SetRangeEnd(SourceLocation()); } bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); @@ -2459,6 +2567,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); while (1) { bool isInvalid = false; + bool isStorageClass = false; const char *PrevSpec = nullptr; unsigned DiagID = 0; @@ -2728,6 +2837,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; // typedef-name + case tok::kw___super: case tok::kw_decltype: case tok::identifier: { // This identifier can only be a typedef name if we haven't already seen @@ -2862,6 +2972,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___vectorcall: case tok::kw___unaligned: ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; @@ -2880,22 +2991,26 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw_typedef: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc, PrevSpec, DiagID, Policy); + isStorageClass = true; 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, Policy); + isStorageClass = true; break; case tok::kw___private_extern__: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern, Loc, PrevSpec, DiagID, Policy); + isStorageClass = true; 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, Policy); + isStorageClass = true; break; case tok::kw_auto: if (getLangOpts().CPlusPlus11) { @@ -2911,18 +3026,22 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } else isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, PrevSpec, DiagID, Policy); + isStorageClass = true; break; case tok::kw_register: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc, PrevSpec, DiagID, Policy); + isStorageClass = true; break; case tok::kw_mutable: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc, PrevSpec, DiagID, Policy); + isStorageClass = true; break; case tok::kw___thread: isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc, PrevSpec, DiagID); + isStorageClass = true; break; case tok::kw_thread_local: isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc, @@ -2931,6 +3050,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw__Thread_local: isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, Loc, PrevSpec, DiagID); + isStorageClass = true; break; // function-specifier @@ -3083,6 +3203,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___pixel: isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___bool: + isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw___unknown_anytype: isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc, PrevSpec, DiagID, Policy); @@ -3169,6 +3292,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; // OpenCL qualifiers: + case tok::kw___generic: + // generic address space is introduced only in OpenCL v2.0 + // see OpenCL C Spec v2.0 s6.5.5 + if (Actions.getLangOpts().OpenCLVersion < 200) { + DiagID = diag::err_opencl_unknown_type_specifier; + PrevSpec = Tok.getIdentifierInfo()->getNameStart(); + isInvalid = true; + break; + }; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -3203,6 +3335,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DiagID == diag::ext_duplicate_declspec) Diag(Tok, DiagID) << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); + else if (DiagID == diag::err_opencl_unknown_type_specifier) + Diag(Tok, DiagID) << PrevSpec << isStorageClass; else Diag(Tok, DiagID) << PrevSpec; } @@ -3232,14 +3366,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, /// declarator[opt] ':' constant-expression /// [GNU] declarator[opt] ':' constant-expression attributes[opt] /// -void Parser:: -ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) { +void Parser::ParseStructDeclaration( + ParsingDeclSpec &DS, + llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback) { if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. ConsumeToken(); - return ParseStructDeclaration(DS, Fields); + return ParseStructDeclaration(DS, FieldsCallback); } // Parse the common specifier-qualifiers-list piece. @@ -3271,7 +3406,8 @@ ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR. ColonProtectionRAIIObject X(*this); ParseDeclarator(DeclaratorInfo.D); - } + } else + DeclaratorInfo.D.SetIdentifier(nullptr, Tok.getLocation()); if (TryConsumeToken(tok::colon)) { ExprResult Res(ParseConstantExpression()); @@ -3285,7 +3421,7 @@ ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Fields) { MaybeParseGNUAttributes(DeclaratorInfo.D); // We're done with this declarator; invoke the callback. - Fields.invoke(DeclaratorInfo); + FieldsCallback(DeclaratorInfo); // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. @@ -3349,28 +3485,19 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, } if (!Tok.is(tok::at)) { - struct CFieldCallback : FieldCallback { - Parser &P; - Decl *TagDecl; - SmallVectorImpl<Decl *> &FieldDecls; - - CFieldCallback(Parser &P, Decl *TagDecl, - SmallVectorImpl<Decl *> &FieldDecls) : - P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {} - - 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(), - FD.D, FD.BitfieldSize); - FieldDecls.push_back(Field); - FD.complete(Field); - } - } Callback(*this, TagDecl, FieldDecls); + auto CFieldCallback = [&](ParsingFieldDeclarator &FD) { + // Install the declarator into the current TagDecl. + Decl *Field = + Actions.ActOnField(getCurScope(), TagDecl, + FD.D.getDeclSpec().getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + FieldDecls.push_back(Field); + FD.complete(Field); + }; // Parse all the comma separated declarators. ParsingDeclSpec DS(*this); - ParseStructDeclaration(DS, Callback); + ParseStructDeclaration(DS, CFieldCallback); } else { // Handle @defs ConsumeToken(); if (!Tok.isObjCAtKeyword(tok::objc_defs)) { @@ -3778,8 +3905,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, /// enumerator /// enumerator-list ',' enumerator /// enumerator: -/// enumeration-constant -/// enumeration-constant '=' constant-expression +/// enumeration-constant attributes[opt] +/// enumeration-constant attributes[opt] '=' constant-expression /// enumeration-constant: /// identifier /// @@ -3816,8 +3943,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // If attributes exist after the enumerator, parse them. ParsedAttributesWithRange attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - MaybeParseCXX11Attributes(attrs); - ProhibitAttributes(attrs); + ProhibitAttributes(attrs); // GNU-style attributes are prohibited. + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (!getLangOpts().CPlusPlus1z) + Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute) + << 1 /*enumerator*/; + ParseCXX11Attributes(attrs); + } SourceLocation EqualLoc; ExprResult AssignedVal; @@ -3921,6 +4053,7 @@ bool Parser::isTypeQualifier() const { case tok::kw___local: case tok::kw___global: case tok::kw___constant: + case tok::kw___generic: case tok::kw___read_only: case tok::kw___read_write: case tok::kw___write_only: @@ -4059,6 +4192,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___vectorcall: case tok::kw___w64: case tok::kw___ptr64: case tok::kw___ptr32: @@ -4069,6 +4203,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___local: case tok::kw___global: case tok::kw___constant: + case tok::kw___generic: case tok::kw___read_only: case tok::kw___read_write: case tok::kw___write_only: @@ -4227,6 +4362,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___vectorcall: case tok::kw___w64: case tok::kw___sptr: case tok::kw___uptr: @@ -4240,6 +4376,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___local: case tok::kw___global: case tok::kw___constant: + case tok::kw___generic: case tok::kw___read_only: case tok::kw___read_write: case tok::kw___write_only: @@ -4373,20 +4510,18 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { /// type-qualifier-list: [C99 6.7.5] /// type-qualifier /// [vendor] attributes -/// [ only if VendorAttributesAllowed=true ] +/// [ only if AttrReqs & AR_VendorAttributesParsed ] /// type-qualifier-list type-qualifier /// [vendor] type-qualifier-list attributes -/// [ only if VendorAttributesAllowed=true ] +/// [ only if AttrReqs & AR_VendorAttributesParsed ] /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq -/// [ only if CXX11AttributesAllowed=true ] -/// Note: vendor can be GNU, MS, etc. -/// -void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, - bool VendorAttributesAllowed, - bool CXX11AttributesAllowed, +/// [ only if AttReqs & AR_CXX11AttributesParsed ] +/// Note: vendor can be GNU, MS, etc and can be explicitly controlled via +/// AttrRequirements bitmask values. +void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed, bool IdentifierRequired) { - if (getLangOpts().CPlusPlus11 && CXX11AttributesAllowed && + if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); ParseCXX11Attributes(attrs); @@ -4430,6 +4565,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___global: case tok::kw___local: case tok::kw___constant: + case tok::kw___generic: case tok::kw___read_only: case tok::kw___write_only: case tok::kw___read_write: @@ -4439,7 +4575,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___uptr: // GNU libc headers in C mode use '__uptr' as an identifer which conflicts // with the MS modifier keyword. - if (VendorAttributesAllowed && !getLangOpts().CPlusPlus && + if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus && IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) { if (TryKeywordIdentFallback(false)) continue; @@ -4452,20 +4588,28 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___vectorcall: case tok::kw___unaligned: - if (VendorAttributesAllowed) { + if (AttrReqs & AR_DeclspecAttributesParsed) { ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; } goto DoneWithTypeQuals; case tok::kw___pascal: - if (VendorAttributesAllowed) { + if (AttrReqs & AR_VendorAttributesParsed) { ParseBorlandTypeAttributes(DS.getAttributes()); continue; } goto DoneWithTypeQuals; case tok::kw___attribute: - if (VendorAttributesAllowed) { + if (AttrReqs & AR_GNUAttributesParsedAndRejected) + // When GNU attributes are expressly forbidden, diagnose their usage. + Diag(Tok, diag::err_attributes_not_allowed); + + // Parse the attributes even if they are rejected to ensure that error + // recovery is graceful. + if (AttrReqs & AR_GNUAttributesParsed || + AttrReqs & AR_GNUAttributesParsedAndRejected) { ParseGNUAttributes(DS.getAttributes()); continue; // do *not* consume the next token! } @@ -4498,15 +4642,27 @@ void Parser::ParseDeclarator(Declarator &D) { ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); } -static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang) { +static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, + unsigned TheContext) { if (Kind == tok::star || Kind == tok::caret) return true; - // We parse rvalue refs in C++03, because otherwise the errors are scary. if (!Lang.CPlusPlus) return false; - return Kind == tok::amp || Kind == tok::ampamp; + if (Kind == tok::amp) + return true; + + // We parse rvalue refs in C++03, because otherwise the errors are scary. + // But we must not parse them in conversion-type-ids and new-type-ids, since + // those can be legitimately followed by a && operator. + // (The same thing can in theory happen after a trailing-return-type, but + // since those are a C++11 feature, there is no rejects-valid issue there.) + if (Kind == tok::ampamp) + return Lang.CPlusPlus11 || (TheContext != Declarator::ConversionIdContext && + TheContext != Declarator::CXXNewContext); + + return false; } /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator @@ -4577,7 +4733,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(), - Loc), + DS.getLocEnd()), DS.getAttributes(), /* Don't replace range end. */SourceLocation()); return; @@ -4586,7 +4742,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, tok::TokenKind Kind = Tok.getKind(); // Not a pointer, C++ reference, or block. - if (!isPtrOperatorToken(Kind, getLangOpts())) { + if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) { if (DirectDeclParser) (this->*DirectDeclParser)(D); return; @@ -4601,8 +4757,13 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Is a pointer. DeclSpec DS(AttrFactory); - // FIXME: GNU attributes are not allowed here in a new-type-id. - ParseTypeQualifierListOpt(DS, true, true, true, !D.mayOmitIdentifier()); + // GNU attributes are not allowed here in a new-type-id, but Declspec and + // C++11 attributes are allowed. + unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed | + ((D.getContext() != Declarator::CXXNewContext) + ? AR_GNUAttributesParsed + : AR_GNUAttributesParsedAndRejected); + ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier()); D.ExtendWithDeclSpec(DS); // Recursively parse the declarator. @@ -4762,21 +4923,22 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } // C++0x [dcl.fct]p14: - // There is a syntactic ambiguity when an ellipsis occurs at the end - // of a parameter-declaration-clause without a preceding comma. In - // this case, the ellipsis is parsed as part of the - // abstract-declarator if the type of the parameter names a template - // parameter pack that has not been expanded; otherwise, it is parsed - // as part of the parameter-declaration-clause. + // There is a syntactic ambiguity when an ellipsis occurs at the end of a + // parameter-declaration-clause without a preceding comma. In this case, + // the ellipsis is parsed as part of the abstract-declarator if the type + // of the parameter either names a template parameter pack that has not + // been expanded or contains auto; otherwise, it is parsed as part of the + // parameter-declaration-clause. if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() && !((D.getContext() == Declarator::PrototypeContext || D.getContext() == Declarator::LambdaExprParameterContext || D.getContext() == Declarator::BlockLiteralContext) && NextToken().is(tok::r_paren) && !D.hasGroupingParens() && - !Actions.containsUnexpandedParameterPacks(D))) { + !Actions.containsUnexpandedParameterPacks(D) && + D.getDeclSpec().getTypeSpecType() != TST_auto)) { SourceLocation EllipsisLoc = ConsumeToken(); - if (isPtrOperatorToken(Tok.getKind(), getLangOpts())) { + if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) { // The ellipsis was put in the wrong place. Recover, and explain to // the user what they should have done. ParseDeclarator(D); @@ -5102,11 +5264,13 @@ void Parser::ParseFunctionDeclarator(Declarator &D, SourceLocation RefQualifierLoc; SourceLocation ConstQualifierLoc; SourceLocation VolatileQualifierLoc; + SourceLocation RestrictQualifierLoc; ExceptionSpecificationType ESpecType = EST_None; SourceRange ESpecRange; SmallVector<ParsedType, 2> DynamicExceptions; SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; + CachedTokens *ExceptionSpecTokens = 0; ParsedAttributes FnAttrs(AttrFactory); TypeResult TrailingReturnType; @@ -5149,13 +5313,13 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // with the virt-specifier-seq and pure-specifier in the same way. // Parse cv-qualifier-seq[opt]. - ParseTypeQualifierListOpt(DS, /*VendorAttributesAllowed*/ false, - /*CXX11AttributesAllowed*/ false, + ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, /*AtomicAllowed*/ false); if (!DS.getSourceRange().getEnd().isInvalid()) { EndLoc = DS.getSourceRange().getEnd(); ConstQualifierLoc = DS.getConstSpecLoc(); VolatileQualifierLoc = DS.getVolatileSpecLoc(); + RestrictQualifierLoc = DS.getRestrictSpecLoc(); } // Parse ref-qualifier[opt]. @@ -5188,15 +5352,36 @@ void Parser::ParseFunctionDeclarator(Declarator &D, dyn_cast<CXXRecordDecl>(Actions.CurContext), DS.getTypeQualifiers() | (D.getDeclSpec().isConstexprSpecified() && - !getLangOpts().CPlusPlus1y + !getLangOpts().CPlusPlus14 ? Qualifiers::Const : 0), IsCXX11MemberFunction); // Parse exception-specification[opt]. - ESpecType = tryParseExceptionSpecification(ESpecRange, + bool Delayed = D.isFirstDeclarationOfMember() && + D.isFunctionDeclaratorAFunctionDeclaration(); + if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) && + GetLookAheadToken(0).is(tok::kw_noexcept) && + GetLookAheadToken(1).is(tok::l_paren) && + GetLookAheadToken(2).is(tok::kw_noexcept) && + GetLookAheadToken(3).is(tok::l_paren) && + GetLookAheadToken(4).is(tok::identifier) && + GetLookAheadToken(4).getIdentifierInfo()->isStr("swap")) { + // HACK: We've got an exception-specification + // noexcept(noexcept(swap(...))) + // or + // noexcept(noexcept(swap(...)) && noexcept(swap(...))) + // on a 'swap' member function. This is a libstdc++ bug; the lookup + // for 'swap' will only find the function we're currently declaring, + // whereas it expects to find a non-member swap through ADL. Turn off + // delayed parsing to give it a chance to find what it expects. + Delayed = false; + } + ESpecType = tryParseExceptionSpecification(Delayed, + ESpecRange, DynamicExceptions, DynamicExceptionRanges, - NoexceptExpr); + NoexceptExpr, + ExceptionSpecTokens); if (ESpecType != EST_None) EndLoc = ESpecRange.getEnd(); @@ -5228,6 +5413,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, RefQualifierIsLValueRef, RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, + RestrictQualifierLoc, /*MutableLoc=*/SourceLocation(), ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), @@ -5235,6 +5421,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + ExceptionSpecTokens, StartLoc, LocalEndLoc, D, TrailingReturnType), FnAttrs, EndLoc); @@ -5306,7 +5493,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList( Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII; // Verify that the argument identifier has not already been mentioned. - if (!ParamsSoFar.insert(ParmII)) { + if (!ParamsSoFar.insert(ParmII).second) { Diag(Tok, diag::err_param_redefinition) << ParmII; } else { // Remember this identifier in ParamInfo. @@ -5414,10 +5601,18 @@ void Parser::ParseParameterDeclarationClause( // Otherwise, we have something. Add it and let semantic analysis try // to grok it and add the result to the ParamInfo we are building. + // Last chance to recover from a misplaced ellipsis in an attempted + // parameter pack declaration. + if (Tok.is(tok::ellipsis) && + (NextToken().isNot(tok::r_paren) || + (!ParmDeclarator.getEllipsisLoc().isValid() && + !Actions.isUnexpandedParameterPackPermitted())) && + Actions.containsUnexpandedParameterPacks(ParmDeclarator)) + DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator); + // Inform the actions module about the parameter declarator, so it gets // added to the current scope. - Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), - ParmDeclarator); + Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator); // Parse the default argument, if any. We parse the default // arguments in all dialects; the semantic analysis in // ActOnParamDefaultArgument will reject the default argument in @@ -5433,20 +5628,14 @@ void Parser::ParseParameterDeclarationClause( // FIXME: Can we use a smart pointer for Toks? DefArgToks = new CachedTokens; + SourceLocation ArgStartLoc = NextToken().getLocation(); if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) { delete DefArgToks; 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. - Token DefArgEnd; - DefArgEnd.startToken(); - DefArgEnd.setKind(tok::cxx_defaultarg_end); - DefArgEnd.setLocation(Tok.getLocation()); - DefArgToks->push_back(DefArgEnd); Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc, - (*DefArgToks)[1].getLocation()); + ArgStartLoc); } } else { // Consume the '='. @@ -5464,6 +5653,7 @@ void Parser::ParseParameterDeclarationClause( DefArgResult = ParseBraceInitializer(); } else DefArgResult = ParseAssignmentExpression(); + DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult); if (DefArgResult.isInvalid()) { Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch); @@ -5480,12 +5670,34 @@ void Parser::ParseParameterDeclarationClause( Param, DefArgToks)); } - 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) + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) { + 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, ", "); + } else if (ParmDeclarator.getEllipsisLoc().isValid() || + Actions.containsUnexpandedParameterPacks(ParmDeclarator)) { + // It looks like this was supposed to be a parameter pack. Warn and + // point out where the ellipsis should have gone. + SourceLocation ParmEllipsis = ParmDeclarator.getEllipsisLoc(); + Diag(EllipsisLoc, diag::warn_misplaced_ellipsis_vararg) + << ParmEllipsis.isValid() << ParmEllipsis; + if (ParmEllipsis.isValid()) { + Diag(ParmEllipsis, + diag::note_misplaced_ellipsis_vararg_existing_ellipsis); + } else { + Diag(ParmDeclarator.getIdentifierLoc(), + diag::note_misplaced_ellipsis_vararg_add_ellipsis) + << FixItHint::CreateInsertion(ParmDeclarator.getIdentifierLoc(), + "...") + << !ParmDeclarator.hasName(); + } + Diag(EllipsisLoc, diag::note_misplaced_ellipsis_vararg_add_comma) << FixItHint::CreateInsertion(EllipsisLoc, ", "); + } + + // We can't have any more parameters after an ellipsis. break; } @@ -5546,7 +5758,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // If there is a type-qualifier-list, read it now. // Type qualifiers in an array subscript are a C99 feature. DeclSpec DS(AttrFactory); - ParseTypeQualifierListOpt(DS, false /*no attributes*/); + ParseTypeQualifierListOpt(DS, AR_CXX11AttributesParsed); // If we haven't already read 'static', check to see if there is one after the // type-qualifier-list. @@ -5582,7 +5794,13 @@ void Parser::ParseBracketDeclarator(Declarator &D) { } else { EnterExpressionEvaluationContext Unevaluated(Actions, Sema::ConstantEvaluated); - NumElements = ParseAssignmentExpression(); + NumElements = + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + } + } else { + if (StaticLoc.isValid()) { + Diag(StaticLoc, diag::err_unspecified_size_with_static); + StaticLoc = SourceLocation(); // Drop the static. } } @@ -5716,8 +5934,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { bool isCastExpr; ParsedType CastTy; SourceRange CastRange; - ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, - CastTy, CastRange); + ExprResult Operand = Actions.CorrectDelayedTyposInExpr( + ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange)); if (hasParens) DS.setTypeofParensRange(CastRange); @@ -5817,6 +6035,7 @@ bool Parser::TryAltiVecVectorTokenOutOfLine() { case tok::kw_float: case tok::kw_double: case tok::kw_bool: + case tok::kw___bool: case tok::kw___pixel: Tok.setKind(tok::kw___vector); return true; @@ -5850,6 +6069,7 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, case tok::kw_float: case tok::kw_double: case tok::kw_bool: + case tok::kw___bool: case tok::kw___pixel: isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy); return true; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 6200363..87d9909 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -17,8 +17,8 @@ #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/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" @@ -73,7 +73,15 @@ Decl *Parser::ParseNamespace(unsigned Context, std::vector<IdentifierInfo*> ExtraIdent; std::vector<SourceLocation> ExtraNamespaceLoc; - Token attrTok; + ParsedAttributesWithRange attrs(AttrFactory); + SourceLocation attrLoc; + if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { + if (!getLangOpts().CPlusPlus1z) + Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute) + << 0 /*namespace*/; + attrLoc = Tok.getLocation(); + ParseCXX11Attributes(attrs); + } if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); @@ -85,10 +93,13 @@ Decl *Parser::ParseNamespace(unsigned Context, } } + // A nested namespace definition cannot have attributes. + if (!ExtraNamespaceLoc.empty() && attrLoc.isValid()) + Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute); + // Read label attributes, if present. - ParsedAttributes attrs(AttrFactory); if (Tok.is(tok::kw___attribute)) { - attrTok = Tok; + attrLoc = Tok.getLocation(); ParseGNUAttributes(attrs); } @@ -99,8 +110,8 @@ Decl *Parser::ParseNamespace(unsigned Context, SkipUntil(tok::semi); return nullptr; } - if (!attrs.empty()) - Diag(attrTok, diag::err_unexpected_namespace_attributes_alias); + if (attrLoc.isValid()) + Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias); if (InlineLoc.isValid()) Diag(InlineLoc, diag::err_inline_namespace_alias) << FixItHint::CreateRemoval(InlineLoc); @@ -110,39 +121,36 @@ Decl *Parser::ParseNamespace(unsigned Context, BalancedDelimiterTracker T(*this, tok::l_brace); if (T.consumeOpen()) { - if (!ExtraIdent.empty()) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) - << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); - } - 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() || getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() || getCurScope()->getFnParent()) { - if (!ExtraIdent.empty()) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) - << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); - } Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace); return nullptr; } - if (!ExtraIdent.empty()) { + if (ExtraIdent.empty()) { + // Normal namespace definition, not a nested-namespace-definition. + } else if (InlineLoc.isValid()) { + Diag(InlineLoc, diag::err_inline_nested_namespace_definition); + } else if (getLangOpts().CPlusPlus1z) { + Diag(ExtraNamespaceLoc[0], + diag::warn_cxx14_compat_nested_namespace_definition); + } else { TentativeParsingAction TPA(*this); SkipUntil(tok::r_brace, StopBeforeMatch); Token rBraceToken = Tok; TPA.Revert(); if (!rBraceToken.is(tok::r_brace)) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); } else { std::string NamespaceFix; @@ -156,7 +164,7 @@ Decl *Parser::ParseNamespace(unsigned Context, for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i) RBraces += "} "; - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()), NamespaceFix) @@ -195,11 +203,11 @@ Decl *Parser::ParseNamespace(unsigned Context, } /// ParseInnerNamespace - Parse the contents of a namespace. -void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, - std::vector<IdentifierInfo*>& Ident, - std::vector<SourceLocation>& NamespaceLoc, - unsigned int index, SourceLocation& InlineLoc, - ParsedAttributes& attrs, +void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, + std::vector<IdentifierInfo *> &Ident, + std::vector<SourceLocation> &NamespaceLoc, + unsigned int index, SourceLocation &InlineLoc, + ParsedAttributes &attrs, BalancedDelimiterTracker &Tracker) { if (index == Ident.size()) { while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { @@ -216,7 +224,9 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, return; } - // Parse improperly nested namespaces. + // Handle a nested namespace definition. + // FIXME: Preserve the source information through to the AST rather than + // desugaring it here. ParseScope NamespaceScope(this, Scope::DeclScope); Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), @@ -493,6 +503,12 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, if (TryConsumeToken(tok::kw_typename, TypenameLoc)) HasTypenameKeyword = true; + if (Tok.is(tok::kw___super)) { + Diag(Tok.getLocation(), diag::err_super_in_using_declaration); + SkipUntil(tok::semi); + return nullptr; + } + // Parse nested-name-specifier. IdentifierInfo *LastII = nullptr; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false, @@ -692,7 +708,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ ExprResult AssertMessage; if (Tok.is(tok::r_paren)) { Diag(Tok, getLangOpts().CPlusPlus1z - ? diag::warn_cxx1y_compat_static_assert_no_message + ? diag::warn_cxx14_compat_static_assert_no_message : diag::ext_static_assert_no_message) << (getLangOpts().CPlusPlus1z ? FixItHint() @@ -769,7 +785,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // because the typename-specifier in a function-style cast operation can't // be 'auto'. Diag(Tok.getLocation(), - getLangOpts().CPlusPlus1y + getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_decltype_auto_type_specifier : diag::ext_decltype_auto_type_specifier); ConsumeToken(); @@ -780,7 +796,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // The operand of the decltype specifier is an unevaluated operand. EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, nullptr,/*IsDecltype=*/true); - Result = ParseExpression(); + Result = Actions.CorrectDelayedTyposInExpr(ParseExpression()); if (Result.isInvalid()) { DS.SetTypeSpecError(); if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) { @@ -903,8 +919,8 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { /// In C++98, instead of base-type-specifier, we have: /// /// ::[opt] nested-name-specifier[opt] class-name -Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, - SourceLocation &EndLocation) { +TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, + SourceLocation &EndLocation) { // Ignore attempts to use typename if (Tok.is(tok::kw_typename)) { Diag(Tok, diag::err_expected_class_name_not_template) @@ -1066,6 +1082,11 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::comma: // __builtin_offsetof(struct foo{...} , case tok::kw_operator: // struct foo operator ++() {...} case tok::kw___declspec: // struct foo {...} __declspec(...) + case tok::l_square: // void f(struct f [ 3]) + case tok::ellipsis: // void f(struct f ... [Ns]) + // FIXME: we should emit semantic diagnostic when declaration + // attribute is in type attribute position. + case tok::kw___attribute: // struct foo __attribute__((used)) x; return true; case tok::colon: return CouldBeBitfield; // enum E { ... } : 2; @@ -1073,6 +1094,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::kw_const: // struct foo {...} const x; case tok::kw_volatile: // struct foo {...} volatile x; case tok::kw_restrict: // struct foo {...} restrict x; + case tok::kw__Atomic: // struct foo {...} _Atomic x; + case tok::kw___unaligned: // struct foo {...} __unaligned *x; // Function specifiers // Note, no 'explicit'. An explicit function must be either a conversion // operator or a constructor. Either way, it can't have a return type. @@ -1111,10 +1134,6 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { if (!getLangOpts().CPlusPlus) return true; break; - // C++11 attributes - case tok::l_square: // enum E [[]] x - // Note, no tok::kw_alignas here; alignas cannot appertain to a type. - return getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square); case tok::greater: // template<class T = class X> return getLangOpts().CPlusPlus; @@ -1224,17 +1243,65 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // C++11 attributes SourceLocation AttrFixitLoc = Tok.getLocation(); - // 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); - } + if (TagType == DeclSpec::TST_struct && + Tok.isNot(tok::identifier) && + !Tok.isAnnotation() && + Tok.getIdentifierInfo() && + (Tok.is(tok::kw___is_abstract) || + Tok.is(tok::kw___is_arithmetic) || + Tok.is(tok::kw___is_array) || + Tok.is(tok::kw___is_base_of) || + Tok.is(tok::kw___is_class) || + Tok.is(tok::kw___is_complete_type) || + Tok.is(tok::kw___is_compound) || + Tok.is(tok::kw___is_const) || + Tok.is(tok::kw___is_constructible) || + Tok.is(tok::kw___is_convertible) || + Tok.is(tok::kw___is_convertible_to) || + Tok.is(tok::kw___is_destructible) || + Tok.is(tok::kw___is_empty) || + Tok.is(tok::kw___is_enum) || + Tok.is(tok::kw___is_floating_point) || + Tok.is(tok::kw___is_final) || + Tok.is(tok::kw___is_function) || + Tok.is(tok::kw___is_fundamental) || + Tok.is(tok::kw___is_integral) || + Tok.is(tok::kw___is_interface_class) || + Tok.is(tok::kw___is_literal) || + Tok.is(tok::kw___is_lvalue_expr) || + Tok.is(tok::kw___is_lvalue_reference) || + Tok.is(tok::kw___is_member_function_pointer) || + Tok.is(tok::kw___is_member_object_pointer) || + Tok.is(tok::kw___is_member_pointer) || + Tok.is(tok::kw___is_nothrow_assignable) || + Tok.is(tok::kw___is_nothrow_constructible) || + Tok.is(tok::kw___is_nothrow_destructible) || + Tok.is(tok::kw___is_object) || + Tok.is(tok::kw___is_pod) || + Tok.is(tok::kw___is_pointer) || + Tok.is(tok::kw___is_polymorphic) || + Tok.is(tok::kw___is_reference) || + Tok.is(tok::kw___is_rvalue_expr) || + Tok.is(tok::kw___is_rvalue_reference) || + Tok.is(tok::kw___is_same) || + Tok.is(tok::kw___is_scalar) || + Tok.is(tok::kw___is_sealed) || + Tok.is(tok::kw___is_signed) || + Tok.is(tok::kw___is_standard_layout) || + Tok.is(tok::kw___is_trivial) || + Tok.is(tok::kw___is_trivially_assignable) || + Tok.is(tok::kw___is_trivially_constructible) || + Tok.is(tok::kw___is_trivially_copyable) || + Tok.is(tok::kw___is_union) || + Tok.is(tok::kw___is_unsigned) || + Tok.is(tok::kw___is_void) || + Tok.is(tok::kw___is_volatile))) + // 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); // Parse the (optional) nested-name-specifier. CXXScopeSpec &SS = DS.getTypeSpecScope(); @@ -1669,7 +1736,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Also enforce C++ [temp]p3: // In a template-declaration which defines a class, no declarator // is permitted. + // + // After a type-specifier, we don't expect a semicolon. This only happens in + // C, since definitions are not permitted in this context in C++. if (TUK == Sema::TUK_Definition && + (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) && (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { if (Tok.isNot(tok::semi)) { const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); @@ -1731,7 +1802,7 @@ void Parser::ParseBaseClause(Decl *ClassDecl) { /// base-type-specifier /// attribute-specifier-seq[opt] access-specifier 'virtual'[opt] /// base-type-specifier -Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { +BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { bool IsVirtual = false; SourceLocation StartLoc = Tok.getLocation(); @@ -1806,16 +1877,34 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const { } /// \brief If the given declarator has any parts for which parsing has to be -/// delayed, e.g., default arguments, create a late-parsed method declaration -/// record to handle the parsing at the end of the class definition. +/// delayed, e.g., default arguments or an exception-specification, create a +/// late-parsed method declaration record to handle the parsing at the end of +/// the class definition. 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. + // has any default arguments or an exception-specification, we'll need to + // parse them later. LateParsedMethodDeclaration *LateMethod = nullptr; DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo(); + // If there was a late-parsed exception-specification, hold onto its tokens. + if (FTI.getExceptionSpecType() == EST_Unparsed) { + // Push this method onto the stack of late-parsed method + // declarations. + LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); + getCurrentClass().LateParsedDeclarations.push_back(LateMethod); + LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); + + // Stash the exception-specification tokens in the late-pased mthod. + LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; + FTI.ExceptionSpecTokens = 0; + + // Reserve space for the parameters. + LateMethod->DefaultArgs.reserve(FTI.NumParams); + } + for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) { if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) { if (!LateMethod) { @@ -1879,12 +1968,22 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const { /// virt-specifier /// virt-specifier-seq virt-specifier void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, - bool IsInterface) { + bool IsInterface, + SourceLocation FriendLoc) { while (true) { VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(); if (Specifier == VirtSpecifiers::VS_None) return; + if (FriendLoc.isValid()) { + Diag(Tok.getLocation(), diag::err_friend_decl_spec) + << VirtSpecifiers::getSpecifierName(Specifier) + << FixItHint::CreateRemoval(Tok.getLocation()) + << SourceRange(FriendLoc, FriendLoc); + ConsumeToken(); + continue; + } + // C++ [class.mem]p8: // A virt-specifier-seq shall contain at most one of each virt-specifier. const char *PrevSpec = nullptr; @@ -1929,13 +2028,19 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( // identifier[opt] ':' constant-expression if (Tok.isNot(tok::colon)) ParseDeclarator(DeclaratorInfo); + else + DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation()); if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) { + assert(DeclaratorInfo.isPastIdentifier() && + "don't know where identifier would go yet?"); BitfieldSize = ParseConstantExpression(); if (BitfieldSize.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); } else - ParseOptionalCXX11VirtSpecifierSeq(VS, getCurrentClass().IsInterface); + ParseOptionalCXX11VirtSpecifierSeq( + VS, getCurrentClass().IsInterface, + DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { @@ -1953,10 +2058,21 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( // 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); + if (BitfieldSize.isUnset() && VS.isUnset()) { + ParseOptionalCXX11VirtSpecifierSeq( + VS, getCurrentClass().IsInterface, + DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); + if (!VS.isUnset()) { + // If we saw any GNU-style attributes that are known to GCC followed by a + // virt-specifier, issue a GCC-compat warning. + const AttributeList *Attr = DeclaratorInfo.getAttributes(); + while (Attr) { + if (Attr->isKnownToGCC() && !Attr->isCXX11Attribute()) + Diag(Attr->getLoc(), diag::warn_gcc_attribute_location); + Attr = Attr->getNext(); + } + } + } } /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. @@ -2021,7 +2137,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Access declarations. bool MalformedTypeSpec = false; if (!TemplateInfo.Kind && - (Tok.is(tok::identifier) || Tok.is(tok::coloncolon))) { + (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + Tok.is(tok::kw___super))) { if (TryAnnotateCXXScopeToken()) MalformedTypeSpec = true; @@ -2039,6 +2156,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + if (SS.isInvalid()) { + SkipUntil(tok::semi); + return; + } + // Try to parse an unqualified-id. SourceLocation TemplateKWLoc; UnqualifiedId Name; @@ -2066,9 +2188,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } } - // static_assert-declaration - if (Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) { - // FIXME: Check for templates + // static_assert-declaration. A templated static_assert declaration is + // diagnosed in Parser::ParseSingleDeclarationAfterTemplate. + if (!TemplateInfo.Kind && + (Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert))) { SourceLocation DeclEnd; ParseStaticAssertDeclaration(DeclEnd); return; @@ -2309,7 +2432,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, E = Ranges.end(); I != E; ++I) Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I; - // TODO: handle initializers, VS, bitfields, 'delete' ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); } else { @@ -2487,7 +2609,10 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, Diag(ConsumeToken(), diag::err_default_special_members); return ExprError(); } - + } + if (const auto *PD = dyn_cast_or_null<MSPropertyDecl>(D)) { + Diag(Tok, diag::err_ms_property_initializer) << PD; + return ExprError(); } return ParseInitializer(); } @@ -2581,17 +2706,60 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // and the only possible place for them to appertain // to the class would be between class-key and class-name. CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc); + + // ParseClassSpecifier() does only a superficial check for attributes before + // deciding to call this method. For example, for + // `class C final alignas ([l) {` it will decide that this looks like a + // misplaced attribute since it sees `alignas '(' ')'`. But the actual + // attribute parsing code will try to parse the '[' as a constexpr lambda + // and consume enough tokens that the alignas parsing code will eat the + // opening '{'. So bail out if the next token isn't one we expect. + if (!Tok.is(tok::colon) && !Tok.is(tok::l_brace)) { + if (TagDecl) + Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); + return; + } } if (Tok.is(tok::colon)) { ParseBaseClause(TagDecl); - if (!Tok.is(tok::l_brace)) { - Diag(Tok, diag::err_expected_lbrace_after_base_specifiers); - - if (TagDecl) - Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); - return; + bool SuggestFixIt = false; + SourceLocation BraceLoc = PP.getLocForEndOfToken(PrevTokLocation); + if (Tok.isAtStartOfLine()) { + switch (Tok.getKind()) { + case tok::kw_private: + case tok::kw_protected: + case tok::kw_public: + SuggestFixIt = NextToken().getKind() == tok::colon; + break; + case tok::kw_static_assert: + case tok::r_brace: + case tok::kw_using: + // base-clause can have simple-template-id; 'template' can't be there + case tok::kw_template: + SuggestFixIt = true; + break; + case tok::identifier: + SuggestFixIt = isConstructorDeclarator(true); + break; + default: + SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false); + break; + } + } + DiagnosticBuilder LBraceDiag = + Diag(BraceLoc, diag::err_expected_lbrace_after_base_specifiers); + if (SuggestFixIt) { + LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {"); + // Try recovering from missing { after base-clause. + PP.EnterToken(Tok); + Tok.setKind(tok::l_brace); + } else { + if (TagDecl) + Actions.ActOnTagDefinitionError(getCurScope(), TagDecl); + return; + } } } @@ -2725,7 +2893,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // C++11 [class.mem]p2: // Within the class member-specification, the class is regarded as complete - // within function bodies, default arguments, and + // within function bodies, default arguments, exception-specifications, and // brace-or-equal-initializers for non-static data members (including such // things in nested classes). if (TagDecl && NonNestedClass) { @@ -2854,7 +3022,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { /// [C++] mem-initializer-id: /// '::'[opt] nested-name-specifier[opt] class-name /// identifier -Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { +MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // parse '::'[opt] nested-name-specifier[opt] CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); @@ -2944,13 +3112,51 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { /// 'noexcept' /// 'noexcept' '(' constant-expression ')' ExceptionSpecificationType -Parser::tryParseExceptionSpecification( +Parser::tryParseExceptionSpecification(bool Delayed, SourceRange &SpecificationRange, SmallVectorImpl<ParsedType> &DynamicExceptions, SmallVectorImpl<SourceRange> &DynamicExceptionRanges, - ExprResult &NoexceptExpr) { + ExprResult &NoexceptExpr, + CachedTokens *&ExceptionSpecTokens) { ExceptionSpecificationType Result = EST_None; - + ExceptionSpecTokens = 0; + + // Handle delayed parsing of exception-specifications. + if (Delayed) { + if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept)) + return EST_None; + + // Consume and cache the starting token. + bool IsNoexcept = Tok.is(tok::kw_noexcept); + Token StartTok = Tok; + SpecificationRange = SourceRange(ConsumeToken()); + + // Check for a '('. + if (!Tok.is(tok::l_paren)) { + // If this is a bare 'noexcept', we're done. + if (IsNoexcept) { + Diag(Tok, diag::warn_cxx98_compat_noexcept_decl); + NoexceptExpr = 0; + return EST_BasicNoexcept; + } + + Diag(Tok, diag::err_expected_lparen_after) << "throw"; + return EST_DynamicNone; + } + + // Cache the tokens for the exception-specification. + ExceptionSpecTokens = new CachedTokens; + ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept' + ExceptionSpecTokens->push_back(Tok); // '(' + SpecificationRange.setEnd(ConsumeParen()); // '(' + + ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens, + /*StopAtSemi=*/true, + /*ConsumeFinalToken=*/true); + SpecificationRange.setEnd(Tok.getLocation()); + return EST_Unparsed; + } + // See if there's a dynamic specification. if (Tok.is(tok::kw_throw)) { Result = ParseDynamicExceptionSpecification(SpecificationRange, @@ -3168,9 +3374,11 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { switch (Tok.getKind()) { default: // Identifiers and keywords have identifier info attached. - if (IdentifierInfo *II = Tok.getIdentifierInfo()) { - Loc = ConsumeToken(); - return II; + if (!Tok.isAnnotation()) { + if (IdentifierInfo *II = Tok.getIdentifierInfo()) { + Loc = ConsumeToken(); + return II; + } } return nullptr; @@ -3265,7 +3473,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, 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()) { @@ -3273,7 +3480,8 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // 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; + << AttrName + << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); return false; } } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index 0e4dfb9..d0d97de 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -216,6 +216,13 @@ bool Parser::isNotExpressionStart() { return isKnownToBeDeclarationSpecifier(); } +static bool isFoldOperator(prec::Level Level) { + return Level > prec::Unknown && Level != prec::Conditional; +} +static bool isFoldOperator(tok::TokenKind Kind) { + return isFoldOperator(getBinOpPrecedence(Kind, false, true)); +} + /// \brief Parse a binary expression that starts with \p LHS and has a /// precedence of at least \p MinPrec. ExprResult @@ -247,6 +254,16 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } + // If the next token is an ellipsis, then this is a fold-expression. Leave + // it alone so we can handle it in the paren expression. + if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { + // FIXME: We can't check this via lookahead before we consume the token + // because that tickles a lexer bug. + PP.EnterToken(Tok); + Tok = OpToken; + return LHS; + } + // Special case handling for the ternary operator. ExprResult TernaryMiddle(true); if (NextTokPrec == prec::Conditional) { @@ -260,6 +277,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // 'logical-OR-expression' as we might expect. TernaryMiddle = ParseExpression(); if (TernaryMiddle.isInvalid()) { + Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); TernaryMiddle = nullptr; } @@ -328,9 +346,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { else RHS = ParseCastExpression(false); - if (RHS.isInvalid()) + if (RHS.isInvalid()) { + Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); - + } + // Remember the precedence of this operator and get the precedence of the // operator immediately to the right of the RHS. prec::Level ThisPrec = NextTokPrec; @@ -359,13 +379,14 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { static_cast<prec::Level>(ThisPrec + !isRightAssoc)); RHSIsInitList = false; - if (RHS.isInvalid()) + if (RHS.isInvalid()) { + Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); + } NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, getLangOpts().CPlusPlus11); } - assert(NextTokPrec <= ThisPrec && "Recursion didn't work!"); if (!RHS.isInvalid() && RHSIsInitList) { if (ThisPrec == prec::Assignment) { @@ -397,7 +418,9 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc, LHS.get(), TernaryMiddle.get(), RHS.get()); - } + } else + // Ensure potential typos in the RHS aren't left undiagnosed. + Actions.CorrectDelayedTyposInExpr(RHS); } } @@ -425,7 +448,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { public: CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes) : AllowNonTypes(AllowNonTypes) { - WantTypeSpecifiers = AllowTypes; + WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes; } bool ValidateCandidate(const TypoCorrection &candidate) override { @@ -688,11 +711,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, ConsumeToken(); break; + case tok::kw___super: case tok::kw_decltype: // Annotate the token and tail recurse. if (TryAnnotateTypeOrScopeToken()) return ExprError(); - assert(Tok.isNot(tok::kw_decltype)); + assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); return ParseCastExpression(isUnaryExpression, isAddressOfOperand); case tok::identifier: { // primary-expression: identifier @@ -708,11 +732,81 @@ 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() && - TryIdentKeywordUpgrade()) - return ParseCastExpression(isUnaryExpression, isAddressOfOperand, - NotCastExpr, isTypeCast); + if (Next.is(tok::l_paren) && + Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + // Build up the mapping of revertible type traits, for future use. + if (RevertibleTypeTraits.empty()) { +#define RTT_JOIN(X,Y) X##Y +#define REVERTIBLE_TYPE_TRAIT(Name) \ + RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] \ + = RTT_JOIN(tok::kw_,Name) + + REVERTIBLE_TYPE_TRAIT(__is_abstract); + REVERTIBLE_TYPE_TRAIT(__is_arithmetic); + REVERTIBLE_TYPE_TRAIT(__is_array); + REVERTIBLE_TYPE_TRAIT(__is_base_of); + REVERTIBLE_TYPE_TRAIT(__is_class); + REVERTIBLE_TYPE_TRAIT(__is_complete_type); + REVERTIBLE_TYPE_TRAIT(__is_compound); + REVERTIBLE_TYPE_TRAIT(__is_const); + REVERTIBLE_TYPE_TRAIT(__is_constructible); + REVERTIBLE_TYPE_TRAIT(__is_convertible); + REVERTIBLE_TYPE_TRAIT(__is_convertible_to); + REVERTIBLE_TYPE_TRAIT(__is_destructible); + REVERTIBLE_TYPE_TRAIT(__is_empty); + REVERTIBLE_TYPE_TRAIT(__is_enum); + REVERTIBLE_TYPE_TRAIT(__is_floating_point); + REVERTIBLE_TYPE_TRAIT(__is_final); + REVERTIBLE_TYPE_TRAIT(__is_function); + REVERTIBLE_TYPE_TRAIT(__is_fundamental); + REVERTIBLE_TYPE_TRAIT(__is_integral); + REVERTIBLE_TYPE_TRAIT(__is_interface_class); + REVERTIBLE_TYPE_TRAIT(__is_literal); + REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr); + REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference); + REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer); + REVERTIBLE_TYPE_TRAIT(__is_member_object_pointer); + REVERTIBLE_TYPE_TRAIT(__is_member_pointer); + REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable); + REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible); + REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible); + REVERTIBLE_TYPE_TRAIT(__is_object); + REVERTIBLE_TYPE_TRAIT(__is_pod); + REVERTIBLE_TYPE_TRAIT(__is_pointer); + REVERTIBLE_TYPE_TRAIT(__is_polymorphic); + REVERTIBLE_TYPE_TRAIT(__is_reference); + REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr); + REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference); + REVERTIBLE_TYPE_TRAIT(__is_same); + REVERTIBLE_TYPE_TRAIT(__is_scalar); + REVERTIBLE_TYPE_TRAIT(__is_sealed); + REVERTIBLE_TYPE_TRAIT(__is_signed); + REVERTIBLE_TYPE_TRAIT(__is_standard_layout); + REVERTIBLE_TYPE_TRAIT(__is_trivial); + REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable); + REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible); + REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable); + REVERTIBLE_TYPE_TRAIT(__is_union); + REVERTIBLE_TYPE_TRAIT(__is_unsigned); + REVERTIBLE_TYPE_TRAIT(__is_void); + REVERTIBLE_TYPE_TRAIT(__is_volatile); +#undef REVERTIBLE_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 + = RevertibleTypeTraits.find(II); + if (Known != RevertibleTypeTraits.end()) { + Tok.setKind(Known->second); + return ParseCastExpression(isUnaryExpression, isAddressOfOperand, + NotCastExpr, isTypeCast); + } + } if (Next.is(tok::coloncolon) || (!ColonIsSacred && Next.is(tok::colon)) || @@ -812,17 +906,26 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, UnqualifiedId Name; CXXScopeSpec ScopeSpec; SourceLocation TemplateKWLoc; - CastExpressionIdValidator Validator(isTypeCast != NotTypeCast, - isTypeCast != IsTypeCast); - Validator.IsAddressOfOperand = isAddressOfOperand; + Token Replacement; + auto Validator = llvm::make_unique<CastExpressionIdValidator>( + isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); + Validator->IsAddressOfOperand = isAddressOfOperand; + Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren); Name.setIdentifier(&II, ILoc); - Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, - Name, Tok.is(tok::l_paren), - isAddressOfOperand, &Validator); + Res = Actions.ActOnIdExpression( + getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), + isAddressOfOperand, std::move(Validator), + /*IsInlineAsmIdentifier=*/false, &Replacement); + if (!Res.isInvalid() && !Res.get()) { + UnconsumeToken(Replacement); + return ParseCastExpression(isUnaryExpression, isAddressOfOperand, + NotCastExpr, isTypeCast); + } break; } case tok::char_constant: // constant: character-constant case tok::wide_char_constant: + case tok::utf8_char_constant: case tok::utf16_char_constant: case tok::utf32_char_constant: Res = Actions.ActOnCharacterConstant(Tok, /*UDLScope*/getCurScope()); @@ -1261,8 +1364,12 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) { LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, Idx.get(), RLoc); - } else + } else { + (void)Actions.CorrectDelayedTyposInExpr(LHS); + (void)Actions.CorrectDelayedTyposInExpr(Idx); LHS = ExprError(); + Idx = ExprError(); + } // Match the ']'. T.consumeClose(); @@ -1285,6 +1392,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { SourceLocation OpenLoc = ConsumeToken(); if (ParseSimpleExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) { + (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } @@ -1335,6 +1443,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (Tok.isNot(tok::r_paren)) { if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall, LHS.get())) { + (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } } @@ -1433,8 +1542,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /*AllowDestructorName=*/true, /*AllowConstructorName=*/ getLangOpts().MicrosoftExt, - ObjectType, TemplateKWLoc, Name)) + ObjectType, TemplateKWLoc, Name)) { + (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); + } if (!LHS.isInvalid()) LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, @@ -1918,11 +2029,15 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { /// cast-expression: [C99 6.5.4] /// '(' type-name ')' cast-expression /// [ARC] bridged-cast-expression -/// /// [ARC] bridged-cast-expression: /// (__bridge type-name) cast-expression /// (__bridge_transfer type-name) cast-expression /// (__bridge_retained type-name) cast-expression +/// fold-expression: [C++1z] +/// '(' cast-expression fold-operator '...' ')' +/// '(' '...' fold-operator cast-expression ')' +/// '(' cast-expression fold-operator '...' +/// fold-operator cast-expression ')' /// \endverbatim ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, @@ -1969,16 +2084,21 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // unless they've already reported an error. if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { Diag(Tok, diag::ext_gnu_statement_expr); - Actions.ActOnStartStmtExpr(); - StmtResult Stmt(ParseCompoundStatement(true)); - ExprType = CompoundStmt; - - // If the substmt parsed correctly, build the AST node. - if (!Stmt.isInvalid()) { - Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation()); + if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) { + Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope)); } else { - Actions.ActOnStmtExprError(); + Actions.ActOnStartStmtExpr(); + + StmtResult Stmt(ParseCompoundStatement(true)); + ExprType = CompoundStmt; + + // If the substmt parsed correctly, build the AST node. + if (!Stmt.isInvalid()) { + Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation()); + } else { + Actions.ActOnStmtExprError(); + } } } else if (ExprType >= CompoundLiteral && BridgeCast) { tok::TokenKind tokenKind = Tok.getKind(); @@ -2111,24 +2231,36 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Diag(Tok, diag::err_expected_lbrace_in_compound_literal); return ExprError(); } + } else if (Tok.is(tok::ellipsis) && + isFoldOperator(NextToken().getKind())) { + return ParseFoldExpression(ExprResult(), T); } else if (isTypeCast) { // Parse the expression-list. InMessageExpressionRAIIObject InMessage(*this, false); - + ExprVector ArgExprs; CommaLocsTy CommaLocs; if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) { + // FIXME: If we ever support comma expressions as operands to + // fold-expressions, we'll need to allow multiple ArgExprs here. + if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) && + NextToken().is(tok::ellipsis)) + return ParseFoldExpression(Result, T); + ExprType = SimpleExpr; Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(), ArgExprs); } } else { InMessageExpressionRAIIObject InMessage(*this, false); - + Result = ParseExpression(MaybeTypeCast); ExprType = SimpleExpr; + if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) + return ParseFoldExpression(Result, T); + // Don't build a paren expression unless we actually match a ')'. if (!Result.isInvalid() && Tok.is(tok::r_paren)) Result = @@ -2286,6 +2418,59 @@ ExprResult Parser::ParseGenericSelectionExpression() { Types, Exprs); } +/// \brief Parse A C++1z fold-expression after the opening paren and optional +/// left-hand-side expression. +/// +/// \verbatim +/// fold-expression: +/// ( cast-expression fold-operator ... ) +/// ( ... fold-operator cast-expression ) +/// ( cast-expression fold-operator ... fold-operator cast-expression ) +ExprResult Parser::ParseFoldExpression(ExprResult LHS, + BalancedDelimiterTracker &T) { + if (LHS.isInvalid()) { + T.skipToEnd(); + return true; + } + + tok::TokenKind Kind = tok::unknown; + SourceLocation FirstOpLoc; + if (LHS.isUsable()) { + Kind = Tok.getKind(); + assert(isFoldOperator(Kind) && "missing fold-operator"); + FirstOpLoc = ConsumeToken(); + } + + assert(Tok.is(tok::ellipsis) && "not a fold-expression"); + SourceLocation EllipsisLoc = ConsumeToken(); + + ExprResult RHS; + if (Tok.isNot(tok::r_paren)) { + if (!isFoldOperator(Tok.getKind())) + return Diag(Tok.getLocation(), diag::err_expected_fold_operator); + + if (Kind != tok::unknown && Tok.getKind() != Kind) + Diag(Tok.getLocation(), diag::err_fold_operator_mismatch) + << SourceRange(FirstOpLoc); + Kind = Tok.getKind(); + ConsumeToken(); + + RHS = ParseExpression(); + if (RHS.isInvalid()) { + T.skipToEnd(); + return true; + } + } + + Diag(EllipsisLoc, getLangOpts().CPlusPlus1z + ? diag::warn_cxx14_compat_fold_expression + : diag::ext_fold_expression); + + T.consumeClose(); + return Actions.ActOnCXXFoldExpr(T.getOpenLocation(), LHS.get(), Kind, + EllipsisLoc, RHS.get(), T.getCloseLocation()); +} + /// ParseExpressionList - Used for C/C++ (argument-)expression-list. /// /// \verbatim @@ -2342,10 +2527,19 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, } if (Tok.isNot(tok::comma)) - return SawError; + break; // Move to the next argument, remember where the comma was. CommaLocs.push_back(ConsumeToken()); } + if (SawError) { + // Ensure typos get diagnosed when errors were encountered while parsing the + // expression list. + for (auto &E : Exprs) { + ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E); + if (Expr.isUsable()) E = Expr.get(); + } + } + return SawError; } /// ParseSimpleExpressionList - A simple comma-separated list of expressions, @@ -2477,6 +2671,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*RefQualifierLoc=*/NoLoc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, /*ESpecLoc=*/NoLoc, @@ -2484,6 +2679,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, CaretLoc, CaretLoc, ParamInfo), attrs, CaretLoc); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 83121a8..355503c 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -108,35 +108,37 @@ void Parser::CheckForLParenAfterColonColon() { if (!Tok.is(tok::l_paren)) return; - SourceLocation l_parenLoc = ConsumeParen(), r_parenLoc; - Token Tok1 = getCurToken(); - if (!Tok1.is(tok::identifier) && !Tok1.is(tok::star)) + Token LParen = Tok; + Token NextTok = GetLookAheadToken(1); + Token StarTok = NextTok; + // Check for (identifier or (*identifier + Token IdentifierTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : StarTok; + if (IdentifierTok.isNot(tok::identifier)) return; - - if (Tok1.is(tok::identifier)) { - Token Tok2 = GetLookAheadToken(1); - if (Tok2.is(tok::r_paren)) { + // Eat the '('. + ConsumeParen(); + Token RParen; + // Do we have a ')' ? + NextTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : GetLookAheadToken(1); + if (NextTok.is(tok::r_paren)) { + RParen = NextTok; + // Eat the '*' if it is present. + if (StarTok.is(tok::star)) ConsumeToken(); - PP.EnterToken(Tok1); - r_parenLoc = ConsumeParen(); - } - } else if (Tok1.is(tok::star)) { - Token Tok2 = GetLookAheadToken(1); - if (Tok2.is(tok::identifier)) { - Token Tok3 = GetLookAheadToken(2); - if (Tok3.is(tok::r_paren)) { - ConsumeToken(); - ConsumeToken(); - PP.EnterToken(Tok2); - PP.EnterToken(Tok1); - r_parenLoc = ConsumeParen(); - } - } - } - - Diag(l_parenLoc, diag::err_paren_after_colon_colon) - << FixItHint::CreateRemoval(l_parenLoc) - << FixItHint::CreateRemoval(r_parenLoc); + // Eat the identifier. + ConsumeToken(); + // Add the identifier token back. + PP.EnterToken(IdentifierTok); + // Add the '*' back if it was present. + if (StarTok.is(tok::star)) + PP.EnterToken(StarTok); + // Eat the ')'. + ConsumeParen(); + } + + Diag(LParen.getLocation(), diag::err_paren_after_colon_colon) + << FixItHint::CreateRemoval(LParen.getLocation()) + << FixItHint::CreateRemoval(RParen.getLocation()); } /// \brief Parse global scope or nested-name-specifier if present. @@ -217,13 +219,29 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (NextKind == tok::kw_new || NextKind == tok::kw_delete) return false; - // '::' - Global scope qualifier. - if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS)) - return true; + if (NextKind == tok::l_brace) { + // It is invalid to have :: {, consume the scope qualifier and pretend + // like we never saw it. + Diag(ConsumeToken(), diag::err_expected) << tok::identifier; + } else { + // '::' - Global scope qualifier. + if (Actions.ActOnCXXGlobalScopeSpecifier(ConsumeToken(), SS)) + return true; - CheckForLParenAfterColonColon(); + CheckForLParenAfterColonColon(); - HasScopeSpecifier = true; + HasScopeSpecifier = true; + } + } + + if (Tok.is(tok::kw___super)) { + SourceLocation SuperLoc = ConsumeToken(); + if (!Tok.is(tok::coloncolon)) { + Diag(Tok.getLocation(), diag::err_expected_coloncolon_after_super); + return true; + } + + return Actions.ActOnSuperScopeSpecifier(SuperLoc, ConsumeToken(), SS); } bool CheckForDestructor = false; @@ -232,7 +250,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, *MayBePseudoDestructor = false; } - if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) { + if (!HasScopeSpecifier && + (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))) { DeclSpec DS(AttrFactory); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation EndLoc = ParseDecltypeSpecifier(DS); @@ -423,11 +442,22 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, Next.setKind(tok::coloncolon); } } - + + if (Next.is(tok::coloncolon) && GetLookAheadToken(2).is(tok::l_brace)) { + // It is invalid to have :: {, consume the scope qualifier and pretend + // like we never saw it. + Token Identifier = Tok; // Stash away the identifier. + ConsumeToken(); // Eat the identifier, current token is now '::'. + Diag(PP.getLocForEndOfToken(ConsumeToken()), diag::err_expected) + << tok::identifier; + UnconsumeToken(Identifier); // Stick the identifier back. + Next = NextToken(); // Point Next at the '{' token. + } + if (Next.is(tok::coloncolon)) { if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde) && - !Actions.isNonTypeNestedNameSpecifier(getCurScope(), SS, Tok.getLocation(), - II, ObjectType)) { + !Actions.isNonTypeNestedNameSpecifier( + getCurScope(), SS, Tok.getLocation(), II, ObjectType)) { *MayBePseudoDestructor = true; return false; } @@ -556,6 +586,28 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } +ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand, + Token &Replacement) { + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*ObjectType=*/ParsedType(), TemplateKWLoc, Name)) + return ExprError(); + + // This is only the direct operand of an & operator if it is not + // followed by a postfix-expression suffix. + if (isAddressOfOperand && isPostfixExpressionSuffixStart()) + isAddressOfOperand = false; + + return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, + Tok.is(tok::l_paren), isAddressOfOperand, + nullptr, /*IsInlineAsmIdentifier=*/false, + &Replacement); +} + /// ParseCXXIdExpression - Handle id-expression. /// /// id-expression: @@ -606,24 +658,17 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); - SourceLocation TemplateKWLoc; - UnqualifiedId Name; - if (ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/false, - /*AllowConstructorName=*/false, - /*ObjectType=*/ ParsedType(), - TemplateKWLoc, - Name)) - return ExprError(); - - // This is only the direct operand of an & operator if it is not - // followed by a postfix-expression suffix. - if (isAddressOfOperand && isPostfixExpressionSuffixStart()) - isAddressOfOperand = false; - - return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, - Tok.is(tok::l_paren), isAddressOfOperand); + Token Replacement; + ExprResult Result = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement); + if (Result.isUnset()) { + // If the ExprResult is valid but null, then typo correction suggested a + // keyword replacement that needs to be reparsed. + UnconsumeToken(Replacement); + Result = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement); + } + assert(!Result.isUnset() && "Typo correction suggested a keyword replacement " + "for a previous keyword suggestion"); + return Result; } /// ParseLambdaExpression - Parse a C++11 lambda expression. @@ -1007,6 +1052,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); Actions.PushLambdaScope(); + TypeResult TrailingReturnType; if (Tok.is(tok::l_paren)) { ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | @@ -1050,10 +1096,13 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SmallVector<ParsedType, 2> DynamicExceptions; SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; - ESpecType = tryParseExceptionSpecification(ESpecRange, + CachedTokens *ExceptionSpecTokens; + ESpecType = tryParseExceptionSpecification(/*Delayed=*/false, + ESpecRange, DynamicExceptions, DynamicExceptionRanges, - NoexceptExpr); + NoexceptExpr, + ExceptionSpecTokens); if (ESpecType != EST_None) DeclEndLoc = ESpecRange.getEnd(); @@ -1064,7 +1113,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SourceLocation FunLocalRangeEnd = DeclEndLoc; // Parse trailing-return-type[opt]. - TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { FunLocalRangeEnd = Tok.getLocation(); SourceRange Range; @@ -1086,6 +1134,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*RefQualifierLoc=*/NoLoc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange.getBegin(), DynamicExceptions.data(), @@ -1093,6 +1142,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + /*ExceptionSpecTokens*/nullptr, LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); @@ -1132,12 +1182,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( MaybeParseCXX11Attributes(Attr, &DeclEndLoc); // Parse the return type, if there is one. - TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { SourceRange Range; TrailingReturnType = ParseTrailingReturnType(Range); if (Range.getEnd().isValid()) - DeclEndLoc = Range.getEnd(); + DeclEndLoc = Range.getEnd(); } SourceLocation NoLoc; @@ -1153,6 +1202,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*RefQualifierLoc=*/NoLoc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, /*ESpecLoc=*/NoLoc, @@ -1160,6 +1210,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, DeclLoc, DeclEndLoc, D, TrailingReturnType), Attr, DeclEndLoc); @@ -1183,9 +1234,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( StmtResult Stmt(ParseCompoundStatementBody()); BodyScope.Exit(); - if (!Stmt.isInvalid()) + if (!Stmt.isInvalid() && !TrailingReturnType.isInvalid()) return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope()); - + Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); return ExprError(); } @@ -1389,7 +1440,7 @@ ExprResult Parser::ParseCXXUuidof() { /// ::[opt] nested-name-specifier[opt] ~type-name /// ExprResult -Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, +Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, ParsedType ObjectType) { @@ -2452,10 +2503,29 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, return true; } + // If the user wrote ~T::T, correct it to T::~T. + if (!TemplateSpecified && NextToken().is(tok::coloncolon)) { + if (SS.isSet()) { + AnnotateScopeToken(SS, /*NewAnnotation*/true); + SS.clear(); + } + if (ParseOptionalCXXScopeSpecifier(SS, ObjectType, EnteringContext)) + return true; + if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon)) { + Diag(TildeLoc, diag::err_destructor_tilde_scope); + return true; + } + + // Recover as if the tilde had been written before the identifier. + Diag(TildeLoc, diag::err_destructor_tilde_scope) + << FixItHint::CreateRemoval(TildeLoc) + << FixItHint::CreateInsertion(Tok.getLocation(), "~"); + } + // Parse the class-name (or template-name in a simple-template-id). IdentifierInfo *ClassName = Tok.getIdentifierInfo(); SourceLocation ClassNameLoc = ConsumeToken(); - + if (TemplateSpecified || Tok.is(tok::less)) { Result.setDestructorName(TildeLoc, ParsedType(), ClassNameLoc); return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, @@ -2463,7 +2533,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, EnteringContext, ObjectType, Result, TemplateSpecified); } - + // Note that this is a destructor name. ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName, ClassNameLoc, getCurScope(), diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp index 8536420..7fe9862 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp @@ -423,9 +423,11 @@ ExprResult Parser::ParseBraceInitializer() { if (Tok.is(tok::ellipsis)) SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken()); - + + SubElt = Actions.CorrectDelayedTyposInExpr(SubElt.get()); + // If we couldn't parse the subelement, bail out. - if (!SubElt.isInvalid()) { + if (SubElt.isUsable()) { 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 7fe72ec..a597a16 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -79,7 +79,7 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { SingleDecl = ParseObjCPropertyDynamic(AtLoc); break; case tok::objc_import: - if (getLangOpts().Modules) + if (getLangOpts().Modules || getLangOpts().DebuggerSupport) return ParseModuleImport(AtLoc); Diag(AtLoc, diag::err_atimport); SkipUntil(tok::semi); @@ -307,72 +307,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, return ClsType; } -/// The Objective-C property callback. This should be defined where -/// it's used, but instead it's been lifted to here to support VS2005. -struct Parser::ObjCPropertyCallback : FieldCallback { -private: - virtual void anchor(); -public: - Parser &P; - SmallVectorImpl<Decl *> &Props; - ObjCDeclSpec &OCDS; - SourceLocation AtLoc; - SourceLocation LParenLoc; - tok::ObjCKeywordKind MethodImplKind; - - ObjCPropertyCallback(Parser &P, - SmallVectorImpl<Decl *> &Props, - ObjCDeclSpec &OCDS, SourceLocation AtLoc, - SourceLocation LParenLoc, - tok::ObjCKeywordKind MethodImplKind) : - P(P), Props(Props), OCDS(OCDS), AtLoc(AtLoc), LParenLoc(LParenLoc), - MethodImplKind(MethodImplKind) { - } - - void invoke(ParsingFieldDeclarator &FD) override { - if (FD.D.getIdentifier() == nullptr) { - P.Diag(AtLoc, diag::err_objc_property_requires_field_name) - << FD.D.getSourceRange(); - return; - } - if (FD.BitfieldSize) { - P.Diag(AtLoc, diag::err_objc_property_bitfield) - << FD.D.getSourceRange(); - return; - } - - // Install the property declarator into interfaceDecl. - IdentifierInfo *SelName = - OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); - - Selector GetterSel = - P.PP.getSelectorTable().getNullarySelector(SelName); - IdentifierInfo *SetterName = OCDS.getSetterName(); - Selector SetterSel; - if (SetterName) - SetterSel = P.PP.getSelectorTable().getSelector(1, &SetterName); - else - SetterSel = - SelectorTable::constructSetterSelector(P.PP.getIdentifierTable(), - P.PP.getSelectorTable(), - FD.D.getIdentifier()); - bool isOverridingProperty = false; - Decl *Property = - P.Actions.ActOnProperty(P.getCurScope(), AtLoc, LParenLoc, - FD, OCDS, - GetterSel, SetterSel, - &isOverridingProperty, - MethodImplKind); - if (!isOverridingProperty) - Props.push_back(Property); - - FD.complete(Property); - } -}; - -void Parser::ObjCPropertyCallback::anchor() { -} - /// objc-interface-decl-list: /// empty /// objc-interface-decl-list objc-property-decl [OBJC2] @@ -511,12 +445,44 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, ParseObjCPropertyAttribute(OCDS); } - ObjCPropertyCallback Callback(*this, allProperties, - OCDS, AtLoc, LParenLoc, MethodImplKind); + auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) { + if (FD.D.getIdentifier() == nullptr) { + Diag(AtLoc, diag::err_objc_property_requires_field_name) + << FD.D.getSourceRange(); + return; + } + if (FD.BitfieldSize) { + Diag(AtLoc, diag::err_objc_property_bitfield) + << FD.D.getSourceRange(); + return; + } + + // Install the property declarator into interfaceDecl. + IdentifierInfo *SelName = + OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); + + Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName); + IdentifierInfo *SetterName = OCDS.getSetterName(); + Selector SetterSel; + if (SetterName) + SetterSel = PP.getSelectorTable().getSelector(1, &SetterName); + else + SetterSel = SelectorTable::constructSetterSelector( + PP.getIdentifierTable(), PP.getSelectorTable(), + FD.D.getIdentifier()); + bool isOverridingProperty = false; + Decl *Property = Actions.ActOnProperty( + getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel, + &isOverridingProperty, MethodImplKind); + if (!isOverridingProperty) + allProperties.push_back(Property); + + FD.complete(Property); + }; // Parse all the comma separated declarators. ParsingDeclSpec DS(*this); - ParseStructDeclaration(DS, Callback); + ParseStructDeclaration(DS, ObjCPropertyCallback); ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); break; @@ -1338,35 +1304,22 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, Sema::PCC_ObjCInstanceVariableList); return cutOffParsing(); } - - struct ObjCIvarCallback : FieldCallback { - Parser &P; - Decl *IDecl; - tok::ObjCKeywordKind visibility; - SmallVectorImpl<Decl *> &AllIvarDecls; - - ObjCIvarCallback(Parser &P, Decl *IDecl, tok::ObjCKeywordKind V, - SmallVectorImpl<Decl *> &AllIvarDecls) : - P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) { - } - void invoke(ParsingFieldDeclarator &FD) override { - P.Actions.ActOnObjCContainerStartDefinition(IDecl); - // Install the declarator into the interface decl. - Decl *Field - = P.Actions.ActOnIvar(P.getCurScope(), - FD.D.getDeclSpec().getSourceRange().getBegin(), - FD.D, FD.BitfieldSize, visibility); - P.Actions.ActOnObjCContainerFinishDefinition(); - if (Field) - AllIvarDecls.push_back(Field); - FD.complete(Field); - } - } Callback(*this, interfaceDecl, visibility, AllIvarDecls); - + auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) { + Actions.ActOnObjCContainerStartDefinition(interfaceDecl); + // Install the declarator into the interface decl. + Decl *Field = Actions.ActOnIvar( + getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, + FD.BitfieldSize, visibility); + Actions.ActOnObjCContainerFinishDefinition(); + if (Field) + AllIvarDecls.push_back(Field); + FD.complete(Field); + }; + // Parse all the comma separated declarators. ParsingDeclSpec DS(*this); - ParseStructDeclaration(DS, Callback); + ParseStructDeclaration(DS, ObjCIvarCallback); if (Tok.is(tok::semi)) { ConsumeToken(); @@ -2071,7 +2024,13 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool)) return ParseObjCAutoreleasePoolStmt(AtLoc); - + + if (Tok.isObjCAtKeyword(tok::objc_import) && + getLangOpts().DebuggerSupport) { + SkipUntil(tok::semi); + return Actions.ActOnNullStmt(Tok.getLocation()); + } + ExprResult Res(ParseExpressionWithLeadingAt(AtLoc)); if (Res.isInvalid()) { // If the expression is invalid, skip ahead to the next semicolon. Not @@ -2217,7 +2176,10 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) { // objc-receiver: // expression - ExprResult Receiver = ParseExpression(); + // Make sure any typos in the receiver are corrected or diagnosed, so that + // proper recovery can happen. FIXME: Perhaps filter the corrected expr to + // only the things that are valid ObjC receivers? + ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression()); if (Receiver.isInvalid()) return true; @@ -2394,7 +2356,7 @@ ExprResult Parser::ParseObjCMessageExpression() { } // Otherwise, an arbitrary expression can be the receiver of a send. - ExprResult Res(ParseExpression()); + ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression()); if (Res.isInvalid()) { SkipUntil(tok::r_square, StopAtSemi); return Res; @@ -2446,7 +2408,7 @@ ExprResult Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, SourceLocation SuperLoc, ParsedType ReceiverType, - ExprArg ReceiverExpr) { + Expr *ReceiverExpr) { InMessageExpressionRAIIObject InMessage(*this, true); if (Tok.is(tok::code_completion)) { @@ -2553,6 +2515,8 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, SourceLocation commaLoc = ConsumeToken(); // Eat the ','. /// Parse the expression after ',' ExprResult Res(ParseAssignmentExpression()); + if (Tok.is(tok::colon)) + Res = Actions.CorrectDelayedTyposInExpr(Res); if (Res.isInvalid()) { if (Tok.is(tok::colon)) { Diag(commaLoc, diag::note_extra_comma_message_arg) << diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp index d1544e6..764619a 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp @@ -26,23 +26,31 @@ using namespace clang; //===----------------------------------------------------------------------===// static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { + // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. + // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd + // TODO: add other combined directives in topological order. + const OpenMPDirectiveKind F[][3] = { + { OMPD_for, OMPD_simd, OMPD_for_simd }, + { OMPD_parallel, OMPD_for, OMPD_parallel_for }, + { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd }, + { OMPD_parallel, OMPD_sections, OMPD_parallel_sections } + }; 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; + for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { + if (DKind == F[i][0]) { + Tok = P.getPreprocessor().LookAhead(0); + auto SDKind = + Tok.isAnnotation() + ? OMPD_unknown + : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + if (SDKind == F[i][1]) { + P.ConsumeToken(); + DKind = F[i][2]; + } } } return DKind; @@ -88,13 +96,19 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_taskwait: case OMPD_flush: case OMPD_for: + case OMPD_for_simd: case OMPD_sections: case OMPD_section: case OMPD_single: case OMPD_master: + case OMPD_ordered: case OMPD_critical: case OMPD_parallel_for: + case OMPD_parallel_for_simd: case OMPD_parallel_sections: + case OMPD_atomic: + case OMPD_target: + case OMPD_teams: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -113,7 +127,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// 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 +/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | +/// 'for simd' | 'parallel for simd' | 'target' | 'teams' {clause} +/// annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { @@ -169,14 +185,20 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_parallel: case OMPD_simd: case OMPD_for: + case OMPD_for_simd: case OMPD_sections: case OMPD_single: case OMPD_section: case OMPD_master: case OMPD_critical: case OMPD_parallel_for: + case OMPD_parallel_for_simd: case OMPD_parallel_sections: - case OMPD_task: { + case OMPD_task: + case OMPD_ordered: + case OMPD_atomic: + case OMPD_target: + case OMPD_teams: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { @@ -337,7 +359,8 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// | 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 +/// mergeable-clause | flush-clause | read-clause | write-clause | +/// update-clause | capture-clause | seq_cst-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -368,6 +391,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); + ErrorFound = true; } Clause = ParseOpenMPSingleExprClause(CKind); @@ -382,6 +406,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); + ErrorFound = true; } Clause = ParseOpenMPSimpleClause(CKind); @@ -392,6 +417,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); + ErrorFound = true; } Clause = ParseOpenMPSingleExprWithArgClause(CKind); @@ -400,6 +426,11 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: + case OMPC_read: + case OMPC_write: + case OMPC_update: + case OMPC_capture: + case OMPC_seq_cst: // 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] @@ -407,6 +438,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); + ErrorFound = true; } Clause = ParseOpenMPClause(CKind); @@ -522,6 +554,9 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { /// mergeable-clause: /// 'mergeable' /// +/// read-clause: +/// 'read' +/// OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); ConsumeAnyToken(); @@ -680,7 +715,8 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { Tok.isNot(tok::annot_pragma_openmp_end))) { ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); // Parse variable - ExprResult VarExpr = ParseAssignmentExpression(); + ExprResult VarExpr = + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (VarExpr.isUsable()) { Vars.push_back(VarExpr.get()); } else { @@ -706,7 +742,8 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { if (MustHaveTail) { ColonLoc = Tok.getLocation(); ConsumeToken(); - ExprResult Tail = ParseAssignmentExpression(); + ExprResult Tail = + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (Tail.isUsable()) TailExpr = Tail.get(); else diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp index d3777f3..473be54 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseDiagnostic.h" @@ -228,6 +229,9 @@ void Parser::initializePragmaHandlers() { UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll")); PP.AddPragmaHandler(UnrollHintHandler.get()); + + NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll")); + PP.AddPragmaHandler(NoUnrollHintHandler.get()); } void Parser::resetPragmaHandlers() { @@ -291,6 +295,9 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler(UnrollHintHandler.get()); UnrollHintHandler.reset(); + + PP.RemovePragmaHandler(NoUnrollHintHandler.get()); + NoUnrollHintHandler.reset(); } /// \brief Handle the annotation token produced for #pragma unused(...) @@ -525,36 +532,50 @@ bool Parser::HandlePragmaMSSection(StringRef PragmaName, << PragmaName; return false; } - int SectionFlags = 0; + int SectionFlags = ASTContext::PSF_Read; + bool SectionFlagsAreDefault = true; while (Tok.is(tok::comma)) { PP.Lex(Tok); // , + // Ignore "long" and "short". + // They are undocumented, but widely used, section attributes which appear + // to do nothing. + if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) { + PP.Lex(Tok); // long/short + continue; + } + if (!Tok.isAnyIdentifier()) { PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren) << PragmaName; return false; } - Sema::PragmaSectionFlag Flag = - llvm::StringSwitch<Sema::PragmaSectionFlag>( + ASTContext::PragmaSectionFlag Flag = + llvm::StringSwitch<ASTContext::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 + .Case("read", ASTContext::PSF_Read) + .Case("write", ASTContext::PSF_Write) + .Case("execute", ASTContext::PSF_Execute) + .Case("shared", ASTContext::PSF_Invalid) + .Case("nopage", ASTContext::PSF_Invalid) + .Case("nocache", ASTContext::PSF_Invalid) + .Case("discard", ASTContext::PSF_Invalid) + .Case("remove", ASTContext::PSF_Invalid) + .Default(ASTContext::PSF_None); + if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) { + PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None ? diag::warn_pragma_invalid_specific_action : diag::warn_pragma_unsupported_action) << PragmaName << Tok.getIdentifierInfo()->getName(); return false; } SectionFlags |= Flag; + SectionFlagsAreDefault = false; PP.Lex(Tok); // Identifier } + // If no section attributes are specified, the section will be marked as + // read/write. + if (SectionFlagsAreDefault) + SectionFlags |= ASTContext::PSF_Write; if (Tok.isNot(tok::r_paren)) { PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName; return false; @@ -718,42 +739,124 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, struct PragmaLoopHintInfo { Token PragmaName; Token Option; - Token Value; - bool HasValue; + Token *Toks; + size_t TokSize; + PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {} }; -LoopHint Parser::HandlePragmaLoopHint() { +static std::string PragmaLoopHintString(Token PragmaName, Token Option) { + 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"; + } + return PragmaString; +} + +bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { 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; + IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo(); + Hint.PragmaNameLoc = IdentifierLoc::create( + Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo); + + // It is possible that the loop hint has no option identifier, such as + // #pragma unroll(4). + IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier) + ? Info->Option.getIdentifierInfo() + : nullptr; + Hint.OptionLoc = IdentifierLoc::create( + Actions.Context, Info->Option.getLocation(), OptionInfo); + + Token *Toks = Info->Toks; + size_t TokSize = Info->TokSize; + + // Return a valid hint if pragma unroll or nounroll were specified + // without an argument. + bool PragmaUnroll = PragmaNameInfo->getName() == "unroll"; + bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll"; + if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) { + ConsumeToken(); // The annotation token. + Hint.Range = Info->PragmaName.getLocation(); + return true; + } + + // The constant expression is always followed by an eof token, which increases + // the TokSize by 1. + assert(TokSize > 0 && + "PragmaLoopHintInfo::Toks must contain at least one token."); + + // If no option is specified the argument is assumed to be a constant expr. + bool StateOption = false; + if (OptionInfo) { // Pragma unroll does not specify an option. + StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) + .Case("vectorize", true) + .Case("interleave", true) + .Case("unroll", true) + .Default(false); + } + + // Verify loop hint has an argument. + if (Toks[0].is(tok::eof)) { + ConsumeToken(); // The annotation token. + Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) + << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll; + return false; + } + + // Validate the argument. + if (StateOption) { + ConsumeToken(); // The annotation token. + bool OptionUnroll = OptionInfo->isStr("unroll"); + SourceLocation StateLoc = Toks[0].getLocation(); + IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); + if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full") + : !StateInfo->isStr("enable")) && + !StateInfo->isStr("disable"))) { + Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) + << /*FullKeyword=*/OptionUnroll; + return false; + } + if (TokSize > 2) + Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << PragmaLoopHintString(Info->PragmaName, Info->Option); + Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo); } else { - Hint.Range = SourceRange(Info->PragmaName.getLocation()); - Hint.ValueLoc = nullptr; - Hint.ValueExpr = nullptr; + // Enter constant expression including eof terminator into token stream. + PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false, + /*OwnsTokens=*/false); + ConsumeToken(); // The annotation token. + + ExprResult R = ParseConstantExpression(); + + // Tokens following an error in an ill-formed constant expression will + // remain in the token stream and must be removed. + if (Tok.isNot(tok::eof)) { + Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << PragmaLoopHintString(Info->PragmaName, Info->Option); + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + } + + ConsumeToken(); // Consume the constant expression eof terminator. + + if (R.isInvalid() || + Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation())) + return false; + + // Argument is a constant expression with an integer type. + Hint.ValueExpr = R.get(); } - return Hint; + Hint.Range = SourceRange(Info->PragmaName.getLocation(), + Info->Toks[TokSize - 1].getLocation()); + return true; } // #pragma GCC visibility comes in two variants: @@ -1725,8 +1828,7 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, PP.Lex(Tok); if (Tok.is(tok::eod)) { PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument) - << "clang optimize" - << "'on' or 'off'"; + << "clang optimize" << /*Expected=*/true << "'on' or 'off'"; return; } if (Tok.isNot(tok::identifier)) { @@ -1756,44 +1858,48 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, } /// \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, +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; + SmallVector<Token, 1> ValueList; + int OpenParens = ValueInParens ? 1 : 0; + // Read constant expression. + while (Tok.isNot(tok::eod)) { + if (Tok.is(tok::l_paren)) + OpenParens++; + else if (Tok.is(tok::r_paren)) { + OpenParens--; + if (OpenParens == 0 && ValueInParens) + break; } - } - // FIXME: Value should be stored and parsed as a constant expression. - Token Value = Tok; + ValueList.push_back(Tok); + PP.Lex(Tok); + } if (ValueInParens) { - PP.Lex(Tok); + // Read ')' if (Tok.isNot(tok::r_paren)) { PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; return true; } + PP.Lex(Tok); } + Token EOFTok; + EOFTok.startToken(); + EOFTok.setKind(tok::eof); + EOFTok.setLocation(Tok.getLocation()); + ValueList.push_back(EOFTok); // Terminates expression for parsing. + + Token *TokenArray = (Token *)PP.getPreprocessorAllocator().Allocate( + ValueList.size() * sizeof(Token), llvm::alignOf<Token>()); + std::copy(ValueList.begin(), ValueList.end(), TokenArray); + Info.Toks = TokenArray; + Info.TokSize = ValueList.size(); + Info.PragmaName = PragmaName; Info.Option = Option; - Info.Value = Value; - Info.HasValue = true; return false; } @@ -1806,7 +1912,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName, /// loop-hint: /// 'vectorize' '(' loop-hint-keyword ')' /// 'interleave' '(' loop-hint-keyword ')' -/// 'unroll' '(' loop-hint-keyword ')' +/// 'unroll' '(' unroll-hint-keyword ')' /// 'vectorize_width' '(' loop-hint-value ')' /// 'interleave_count' '(' loop-hint-value ')' /// 'unroll_count' '(' loop-hint-value ')' @@ -1815,6 +1921,10 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName, /// 'enable' /// 'disable' /// +/// unroll-hint-keyword: +/// 'full' +/// 'disable' +/// /// loop-hint-value: /// constant-expression /// @@ -1829,12 +1939,10 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName, /// only works on inner loops. /// /// The unroll and unroll_count directives control the concatenation -/// unroller. Specifying unroll(enable) instructs llvm to try to +/// unroller. Specifying unroll(full) 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) { @@ -1867,17 +1975,19 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, << /*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; + // Read '(' + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; return; } + PP.Lex(Tok); + + auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; + if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true, + *Info)) + return; // Generate the loop hint token. Token LoopHintTok; @@ -1886,9 +1996,6 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, 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)) { @@ -1909,44 +2016,54 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, /// #pragma unroll /// #pragma unroll unroll-hint-value /// #pragma unroll '(' unroll-hint-value ')' +/// #pragma nounroll /// /// 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. +/// Loop unrolling hints can be specified with '#pragma unroll' or +/// '#pragma nounroll'. '#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. Specifying, '#pragma nounroll' +/// disables unrolling of the loop. void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) { - // Incoming token is "unroll" of "#pragma unroll". + // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for + // "#pragma nounroll". Token PragmaName = Tok; PP.Lex(Tok); auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo; if (Tok.is(tok::eod)) { - // Unroll pragma without an argument. + // nounroll or unroll pragma without an argument. Info->PragmaName = PragmaName; - Info->Option = PragmaName; - Info->HasValue = false; + Info->Option.startToken(); + } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "nounroll"; + return; } else { // Unroll pragma with an argument: "#pragma unroll N" or // "#pragma unroll(N)". - bool ValueInParens; - if (ParseLoopHintValue(PP, Tok, PragmaName, PragmaName, ValueInParens, - *Info)) + // Read '(' if it exists. + bool ValueInParens = Tok.is(tok::l_paren); + if (ValueInParens) + PP.Lex(Tok); + + Token Option; + Option.startToken(); + if (ParseLoopHintValue(PP, Tok, PragmaName, Option, 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(), + PP.Diag(Info->Toks[0].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"; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index ec0ca6b..2a5f840 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -185,9 +185,9 @@ Retry: if (Next.isNot(tok::coloncolon)) { // Try to limit which sets of keywords should be included in typo // correction based on what the next token is. - StatementFilterCCC Validator(Next); - if (TryAnnotateName(/*IsAddressOfOperand*/false, &Validator) - == ANK_Error) { + if (TryAnnotateName(/*IsAddressOfOperand*/ false, + llvm::make_unique<StatementFilterCCC>(Next)) == + ANK_Error) { // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); @@ -207,7 +207,7 @@ Retry: default: { if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext, + DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd, Attrs); return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd); } @@ -424,27 +424,11 @@ StmtResult Parser::ParseSEHTryBlock() { /// seh-finally-block /// StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { - if (Tok.isNot(tok::l_brace)) + 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(/*isStmtExpr=*/false, + Scope::DeclScope | Scope::SEHTryScope)); if(TryBlock.isInvalid()) return TryBlock; @@ -466,9 +450,7 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { return Actions.ActOnSEHTryBlock(false /* IsCXXTry */, TryLoc, TryBlock.get(), - Handler.get(), - SEHTryIndex, - SEHTryParentIndex); + Handler.get()); } /// ParseSEHExceptBlock - Handle __except @@ -660,6 +642,11 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { ExprResult LHS; if (!MissingCase) { LHS = ParseConstantExpression(); + if (!getLangOpts().CPlusPlus11) { + LHS = Actions.CorrectDelayedTyposInExpr(LHS, [this](class Expr *E) { + return Actions.VerifyIntegerConstantExpression(E); + }); + } if (LHS.isInvalid()) { // If constant-expression is parsed unsuccessfully, recover by skipping // current case statement (moving to the colon that ends it). @@ -974,8 +961,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ExtensionRAIIObject O(Diags); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy Res = ParseDeclaration(Stmts, - Declarator::BlockContext, DeclEnd, + DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd, attrs); R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd); } else { @@ -1534,9 +1520,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { else ForRangeInit.RangeExpr = ParseExpression(); - Diag(Loc, getLangOpts().CPlusPlus1z - ? diag::warn_cxx1y_compat_for_range_identifier - : diag::ext_for_range_identifier) + Diag(Loc, diag::err_for_range_identifier) << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus1z) ? FixItHint::CreateInsertion(Loc, "auto &&") : FixItHint()); @@ -1554,9 +1538,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - StmtVector Stmts; DeclGroupPtrTy DG = ParseSimpleDeclaration( - Stmts, Declarator::ForContext, DeclEnd, attrs, false, + Declarator::ForContext, DeclEnd, attrs, false, MightBeForRangeStmt ? &ForRangeInit : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInit.ParsedForRangeDecl()) { @@ -1582,7 +1565,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { } } else { ProhibitAttributes(attrs); - Value = ParseExpression(); + Value = Actions.CorrectDelayedTyposInExpr(ParseExpression()); ForEach = isTokIdentifier_in(); @@ -1818,7 +1801,7 @@ StmtResult Parser::ParseReturnStatement() { diag::ext_generalized_initializer_lists) << R.get()->getSourceRange(); } else - R = ParseExpression(); + R = ParseExpression(); if (R.isInvalid()) { SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); return StmtError(); @@ -1835,10 +1818,11 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, // Get loop hints and consume annotated token. while (Tok.is(tok::annot_pragma_loop_hint)) { - LoopHint Hint = HandlePragmaLoopHint(); - ConsumeToken(); + LoopHint Hint; + if (!HandlePragmaLoopHint(Hint)) + continue; - ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.ValueLoc, + ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.StateLoc, ArgsUnion(Hint.ValueExpr)}; TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr, Hint.PragmaNameLoc->Loc, ArgHints, 4, @@ -1975,23 +1959,10 @@ StmtResult Parser::ParseCXXTryBlock() { StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); - // FIXME: Possible draft standard bug: attribute-specifier should be allowed? - 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(); - } + StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, + Scope::DeclScope | Scope::TryScope | + (FnTry ? Scope::FnTryCatchScope : 0))); if (TryBlock.isInvalid()) return TryBlock; @@ -2016,9 +1987,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { return Actions.ActOnSEHTryBlock(true /* IsCXXTry */, TryLoc, TryBlock.get(), - Handler.get(), - SEHTryIndex, - SEHTryParentIndex); + Handler.get()); } else { StmtVector Handlers; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp index f7e8307..7bf4da6 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp @@ -93,6 +93,15 @@ public: return Info.OpDecl; } + StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM, + llvm::SMLoc Location, + bool Create) override { + SourceLocation Loc = translateLocation(LSM, Location); + LabelDecl *Label = + TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create); + return Label->getMSAsmLabel(); + } + bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset) override { return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset, @@ -133,14 +142,13 @@ private: } } - void handleDiagnostic(const llvm::SMDiagnostic &D) { + SourceLocation translateLocation(const llvm::SourceMgr &LSM, llvm::SMLoc SMLoc) { // 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(); + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc)); + unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart(); // Figure out which token that offset points into. const unsigned *TokOffsetPtr = @@ -157,6 +165,12 @@ private: Loc = Tok.getLocation(); Loc = Loc.getLocWithOffset(Offset - TokOffset); } + return Loc; + } + + void handleDiagnostic(const llvm::SMDiagnostic &D) { + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + SourceLocation Loc = translateLocation(LSM, D.getLoc()); TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); } }; @@ -322,6 +336,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { SourceLocation EndLoc = AsmLoc; SmallVector<Token, 4> AsmToks; + bool SingleLineMode = true; unsigned BraceNesting = 0; unsigned short savedBraceCount = BraceCount; bool InAsmComment = false; @@ -333,6 +348,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { if (Tok.is(tok::l_brace)) { // Braced inline asm: consume the opening brace. + SingleLineMode = false; BraceNesting = 1; EndLoc = ConsumeBrace(); LBraceLocs.push_back(EndLoc); @@ -364,30 +380,39 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { } else if (!InAsmComment && Tok.is(tok::semi)) { // A semicolon in an asm is the start of a comment. InAsmComment = true; - if (BraceNesting) { + if (!SingleLineMode) { // 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) { + } else if (SingleLineMode || 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) + // If this is a single-line __asm, we're done, except if the next + // line begins with an __asm too, in which case we finish a comment + // if needed and then keep processing the next line as a single + // line __asm. + bool isAsm = Tok.is(tok::kw_asm); + if (SingleLineMode && !isAsm) break; // We're no longer in a comment. InAsmComment = false; + if (isAsm) { + LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second); + SkippedStartOfLine = Tok.isAtStartOfLine(); + } } 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; + // In MSVC mode, braces only participate in brace matching and + // separating the asm statements. This is an intentional + // departure from the Apple gcc behavior. + if (!BraceNesting) + break; } } if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) && @@ -398,7 +423,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { BraceNesting--; // Finish if all of the opened braces in the inline asm section were // consumed. - if (BraceNesting == 0) + if (BraceNesting == 0 && !SingleLineMode) break; else { LBraceLocs.pop_back(); @@ -487,11 +512,13 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { llvm::SourceMgr TempSrcMgr; llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); - llvm::MemoryBuffer *Buffer = + MOFI->InitMCObjectFileInfo(TT, llvm::Reloc::Default, llvm::CodeModel::Default, + Ctx); + std::unique_ptr<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()); + TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc()); std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); std::unique_ptr<llvm::MCAsmParser> Parser( @@ -590,7 +617,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { } DeclSpec DS(AttrFactory); SourceLocation Loc = Tok.getLocation(); - ParseTypeQualifierListOpt(DS, true, false); + ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed); // GNU asms accept, but warn, about type-qualifiers other than volatile. if (DS.getTypeQualifiers() & DeclSpec::TQ_const) @@ -747,7 +774,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, // Read the parenthesized expression. BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - ExprResult Res(ParseExpression()); + ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression()); T.consumeClose(); if (Res.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index fa6401f..53de72c 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -166,6 +166,14 @@ Parser::ParseSingleDeclarationAfterTemplate( assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && "Template information required"); + if (Tok.is(tok::kw_static_assert)) { + // A static_assert declaration may not be templated. + Diag(Tok.getLocation(), diag::err_templated_invalid_declaration) + << TemplateInfo.getSourceRange(); + // Parse the static_assert declaration to improve error recovery. + return ParseStaticAssertDeclaration(DeclEnd); + } + if (Context == Declarator::MemberContext) { // We are parsing a member template. ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo, @@ -223,6 +231,16 @@ Parser::ParseSingleDeclarationAfterTemplate( if (DeclaratorInfo.isFunctionDeclarator() && isStartOfFunctionDefinition(DeclaratorInfo)) { + + // Function definitions are only allowed at file scope and in C++ classes. + // The C++ inline method definition case is handled elsewhere, so we only + // need to handle the file scope definition case. + if (Context != Declarator::FileContext) { + Diag(Tok, diag::err_function_definition_not_allowed); + SkipMalformedDecl(); + return nullptr; + } + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { // Recover by ignoring the 'typedef'. This was probably supposed to be // the 'typename' keyword, which we should have already suggested adding @@ -553,7 +571,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { if (Tok.is(tok::kw_typename)) { Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z - ? diag::warn_cxx1y_compat_template_template_param_typename + ? diag::warn_cxx14_compat_template_template_param_typename : diag::ext_template_template_param_typename) << (!getLangOpts().CPlusPlus1z ? FixItHint::CreateReplacement(Tok.getLocation(), "class") @@ -668,7 +686,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); - DefaultArg = ParseAssignmentExpression(); + DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (DefaultArg.isInvalid()) SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch); } @@ -1327,7 +1345,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); // Recreate the containing function DeclContext. - Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FunD)); + Sema::ContextRAII FunctionSavedContext(Actions, + Actions.getContainingDC(FunD)); Actions.ActOnStartOfFunctionDef(getCurScope(), FunD); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index 8514af2..abf16fa 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -195,7 +195,9 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { } } - if (TryAnnotateCXXScopeToken()) + if ((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) && + TryAnnotateCXXScopeToken()) return TPResult::Error; if (Tok.is(tok::annot_cxxscope)) ConsumeToken(); @@ -837,6 +839,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, Tok.is(tok::kw___stdcall) || Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___thiscall) || + Tok.is(tok::kw___vectorcall) || Tok.is(tok::kw___unaligned)) return TPResult::True; // attributes indicate declaration TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); @@ -891,6 +894,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::numeric_constant: case tok::char_constant: case tok::wide_char_constant: + case tok::utf8_char_constant: case tok::utf16_char_constant: case tok::utf32_char_constant: case tok::string_literal: @@ -984,9 +988,11 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___vectorcall: case tok::kw___unaligned: case tok::kw___vector: case tok::kw___pixel: + case tok::kw___bool: case tok::kw__Atomic: case tok::kw___unknown_anytype: return TPResult::False; @@ -1004,6 +1010,28 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) { != TentativelyDeclaredIdentifiers.end(); } +namespace { +class TentativeParseCCC : public CorrectionCandidateCallback { +public: + TentativeParseCCC(const Token &Next) { + WantRemainingKeywords = false; + WantTypeSpecifiers = Next.is(tok::l_paren) || Next.is(tok::r_paren) || + Next.is(tok::greater) || Next.is(tok::l_brace) || + Next.is(tok::identifier); + } + + bool ValidateCandidate(const TypoCorrection &Candidate) override { + // Reject any candidate that only resolves to instance members since they + // aren't viable as standalone identifiers instead of member references. + if (Candidate.isResolved() && !Candidate.isKeyword() && + std::all_of(Candidate.begin(), Candidate.end(), + [](NamedDecl *ND) { return ND->isCXXInstanceMember(); })) + return false; + + return CorrectionCandidateCallback::ValidateCandidate(Candidate); + } +}; +} /// 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 @@ -1129,11 +1157,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // a parse error one way or another. In that case, tell the caller that // this is ambiguous. Typo-correct to type and expression keywords and // to types and identifiers, in order to try to recover from errors. - CorrectionCandidateCallback TypoCorrection; - TypoCorrection.WantRemainingKeywords = false; - TypoCorrection.WantTypeSpecifiers = Next.isNot(tok::arrow); switch (TryAnnotateName(false /* no nested name specifier */, - &TypoCorrection)) { + llvm::make_unique<TentativeParseCCC>(Next))) { case ANK_Error: return TPResult::Error; case ANK_TentativeDecl: @@ -1181,6 +1206,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::False; } // Fall through. + case tok::kw___super: case tok::kw_decltype: // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. @@ -1250,6 +1276,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: + case tok::kw___vectorcall: case tok::kw___w64: case tok::kw___sptr: case tok::kw___uptr: diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 37ce157..7ccd209 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -510,6 +510,13 @@ namespace { }; } +void Parser::LateTemplateParserCleanupCallback(void *P) { + // While this RAII helper doesn't bracket any actual work, the destructor will + // clean up annotations that were created during ActOnEndOfTranslationUnit + // when incremental processing is enabled. + DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(((Parser *)P)->TemplateIds); +} + /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the /// action tells us to. This returns true if the EOF was encountered. bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { @@ -542,7 +549,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { case tok::eof: // Late template parsing can begin. if (getLangOpts().DelayedTemplateParsing) - Actions.SetLateTemplateParser(LateTemplateParserCallback, this); + Actions.SetLateTemplateParser(LateTemplateParserCallback, + PP.isIncrementalProcessingEnabled() ? + LateTemplateParserCleanupCallback : nullptr, + this); if (!PP.isIncrementalProcessingEnabled()) Actions.ActOnEndOfTranslationUnit(); //else don't tell Sema that we ended parsing: more input might come. @@ -624,8 +634,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, HandlePragmaOpenCLExtension(); return DeclGroupPtrTy(); case tok::annot_pragma_openmp: - ParseOpenMPDeclarativeDirective(); - return DeclGroupPtrTy(); + return ParseOpenMPDeclarativeDirective(); case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); return DeclGroupPtrTy(); @@ -697,8 +706,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // A function definition cannot start with any of these keywords. { SourceLocation DeclEnd; - StmtVector Stmts; - return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); } case tok::kw_static: @@ -708,8 +716,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 0; SourceLocation DeclEnd; - StmtVector Stmts; - return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); } goto dont_know; @@ -720,8 +727,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // Inline namespaces. Allowed as an extension even in C++03. if (NextKind == tok::kw_namespace) { SourceLocation DeclEnd; - StmtVector Stmts; - return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); } // Parse (then ignore) 'inline' prior to a template instantiation. This is @@ -730,8 +736,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 1; SourceLocation DeclEnd; - StmtVector Stmts; - return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); } } goto dont_know; @@ -885,7 +890,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, return Actions.ConvertDeclToDeclGroup(TheDecl); } - return ParseDeclGroup(DS, Declarator::FileContext, true); + return ParseDeclGroup(DS, Declarator::FileContext); } Parser::DeclGroupPtrTy @@ -922,7 +927,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs, Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, LateParsedAttrList *LateParsedAttrs) { - // Poison the SEH identifiers so they are flagged as illegal in function bodies + // Poison SEH identifiers so they are flagged as illegal in function bodies. PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); @@ -1218,27 +1223,24 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { /// [GNU] asm-string-literal: /// string-literal /// -Parser::ExprResult Parser::ParseAsmStringLiteral() { - switch (Tok.getKind()) { - case tok::string_literal: - break; - case tok::utf8_string_literal: - case tok::utf16_string_literal: - case tok::utf32_string_literal: - case tok::wide_string_literal: { - SourceLocation L = Tok.getLocation(); +ExprResult Parser::ParseAsmStringLiteral() { + if (!isTokenStringLiteral()) { + Diag(Tok, diag::err_expected_string_literal) + << /*Source='in...'*/0 << "'asm'"; + return ExprError(); + } + + ExprResult AsmString(ParseStringLiteralExpression()); + if (!AsmString.isInvalid()) { + const auto *SL = cast<StringLiteral>(AsmString.get()); + if (!SL->isAscii()) { Diag(Tok, diag::err_asm_operand_wide_string_literal) - << (Tok.getKind() == tok::wide_string_literal) - << SourceRange(L, L); + << SL->isWide() + << SL->getSourceRange(); return ExprError(); } - default: - Diag(Tok, diag::err_expected_string_literal) - << /*Source='in...'*/0 << "'asm'"; - return ExprError(); } - - return ParseStringLiteralExpression(); + return AsmString; } /// ParseSimpleAsm @@ -1246,7 +1248,7 @@ Parser::ExprResult Parser::ParseAsmStringLiteral() { /// [GNU] simple-asm-expr: /// 'asm' '(' asm-string-literal ')' /// -Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { +ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { assert(Tok.is(tok::kw_asm) && "Not an asm!"); SourceLocation Loc = ConsumeToken(); @@ -1321,7 +1323,7 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { /// no typo correction will be performed. Parser::AnnotatedNameKind Parser::TryAnnotateName(bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC) { + std::unique_ptr<CorrectionCandidateCallback> CCC) { assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope)); const bool EnteringContext = false; @@ -1359,9 +1361,9 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, // after a scope specifier, because in general we can't recover from typos // 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 : nullptr); + Sema::NameClassification Classification = Actions.ClassifyName( + getCurScope(), SS, Name, NameLoc, Next, IsAddressOfOperand, + SS.isEmpty() ? std::move(CCC) : nullptr); switch (Classification.getKind()) { case Sema::NC_Error: @@ -1431,34 +1433,16 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, } bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { - assert(!Tok.is(tok::identifier) && !Tok.isAnnotation()); + assert(Tok.isNot(tok::identifier)); Diag(Tok, diag::ext_keyword_as_ident) << PP.getSpelling(Tok) << DisableKeyword; - if (DisableKeyword) { - IdentifierInfo *II = Tok.getIdentifierInfo(); - ContextualKeywords[II] = Tok.getKind(); - II->RevertTokenIDToIdentifier(); - } + if (DisableKeyword) + Tok.getIdentifierInfo()->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 @@ -1482,10 +1466,11 @@ bool Parser::TryIdentKeywordUpgrade() { /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { - assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) - || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) - || Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) - && "Cannot be a type or scope token!"); + assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) || + Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) || + Tok.is(tok::kw___super)) && + "Cannot be a type or scope token!"); if (Tok.is(tok::kw_typename)) { // MSVC lets you do stuff like: @@ -1694,7 +1679,8 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { "Call sites of this function should be guarded by checking for C++"); assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) || - Tok.is(tok::kw_decltype)) && "Cannot be a type or scope token!"); + Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super)) && + "Cannot be a type or scope token!"); CXXScopeSpec SS; if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) @@ -1739,7 +1725,8 @@ SourceLocation Parser::handleUnexpectedCodeCompletionToken() { for (Scope *S = getCurScope(); S; S = S->getParent()) { if (S->getFlags() & Scope::FnScope) { - Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_RecoveryInFunction); + Actions.CodeCompleteOrdinaryName(getCurScope(), + Sema::PCC_RecoveryInFunction); cutOffParsing(); return PrevTokLocation; } @@ -1756,13 +1743,6 @@ SourceLocation Parser::handleUnexpectedCodeCompletionToken() { return PrevTokLocation; } -// Anchor the Parser::FieldCallback vtable to this translation unit. -// We use a spurious method instead of the destructor because -// destroying FieldCallbacks can actually be slightly -// performance-sensitive. -void Parser::FieldCallback::_anchor() { -} - // Code-completion pass-through functions void Parser::CodeCompleteDirective(bool InConditional) { @@ -1784,7 +1764,7 @@ void Parser::CodeCompletePreprocessorExpression() { void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned ArgumentIndex) { - Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo, + Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo, ArgumentIndex); } @@ -1806,8 +1786,9 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { } // Parse nested-name-specifier. - ParseOptionalCXXScopeSpecifier(Result.SS, ParsedType(), - /*EnteringContext=*/false); + if (getLangOpts().CPlusPlus) + ParseOptionalCXXScopeSpecifier(Result.SS, ParsedType(), + /*EnteringContext=*/false); // Check nested-name specifier. if (Result.SS.isInvalid()) { @@ -1828,7 +1809,7 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { // Check if the symbol exists. switch (Actions.CheckMicrosoftIfExistsSymbol(getCurScope(), Result.KeywordLoc, - Result.IsIfExists, Result.SS, + Result.IsIfExists, Result.SS, Result.Name)) { case Sema::IER_Exists: Result.Behavior = Result.IsIfExists ? IEB_Parse : IEB_Skip; diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h index 4f5f3ab..a0c9c1f 100644 --- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h +++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H -#define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H +#ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H +#define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" |