diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp | 63 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp | 361 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | 429 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp | 145 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp | 74 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp | 180 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp | 18 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp | 59 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 70 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp | 16 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp | 45 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp | 71 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 74 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h | 22 |
15 files changed, 1122 insertions, 507 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index 59b491a..ea67a52 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -26,12 +26,10 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, AttributeList *AccessAttrs, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, - FunctionDefinitionKind DefinitionKind, + const VirtSpecifiers& VS, ExprResult& Init) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) || - Tok.is(tok::equal)) && + assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) && "Current token not a '{', ':', '=', or 'try'!"); MultiTemplateParamsArg TemplateParams( @@ -40,7 +38,6 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); NamedDecl *FnD; - D.setFunctionDefinitionKind(DefinitionKind); if (D.getDeclSpec().isFriendSpecified()) FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, TemplateParams); @@ -71,17 +68,24 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, bool Delete = false; SourceLocation KWLoc; + SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1); if (TryConsumeToken(tok::kw_delete, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_deleted_function : diag::ext_deleted_function); Actions.SetDeclDeleted(FnD, KWLoc); Delete = true; + if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) { + DeclAsFunction->setRangeEnd(KWEndLoc); + } } else if (TryConsumeToken(tok::kw_default, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_defaulted_function : diag::ext_defaulted_function); Actions.SetDeclDefaulted(FnD, KWLoc); + if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) { + DeclAsFunction->setRangeEnd(KWEndLoc); + } } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); } @@ -97,12 +101,12 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, return FnD; } - + // In delayed template parsing mode, if we are within a class template // or if we are about to parse function member template then consume // the tokens and store them for parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && - DefinitionKind == FDK_Definition && + D.getFunctionDefinitionKind() == FDK_Definition && !D.getDeclSpec().isConstexprSpecified() && !(FnD && FnD->getAsFunction() && FnD->getAsFunction()->getReturnType()->getContainedAutoType()) && @@ -186,7 +190,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, /// declaration. Now lex its initializer and store its tokens for parsing /// after the class is complete. void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) { - assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) && + assert(Tok.isOneOf(tok::l_brace, tok::equal) && "Current token not a '{' or '='!"); LateParsedMemberInitializer *MI = @@ -306,9 +310,10 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | Scope::FunctionDeclarationScope | Scope::DeclScope); for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { + auto Param = cast<ParmVarDecl>(LM.DefaultArgs[I].Param); // Introduce the parameter into scope. - Actions.ActOnDelayedCXXMethodParameter(getCurScope(), - LM.DefaultArgs[I].Param); + bool HasUnparsed = Param->hasUnparsedDefaultArg(); + Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param); if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { // Mark the end of the default argument so that we know when to stop when // we parse it later on. @@ -316,9 +321,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { Token DefArgEnd; DefArgEnd.startToken(); DefArgEnd.setKind(tok::eof); - DefArgEnd.setLocation(LastDefaultArgToken.getLocation().getLocWithOffset( - LastDefaultArgToken.getLength())); - DefArgEnd.setEofData(LM.DefaultArgs[I].Param); + DefArgEnd.setLocation(LastDefaultArgToken.getEndLoc()); + DefArgEnd.setEofData(Param); Toks->push_back(DefArgEnd); // Parse the default argument from its saved token stream. @@ -336,7 +340,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // used. EnterExpressionEvaluationContext Eval(Actions, Sema::PotentiallyEvaluatedIfUsed, - LM.DefaultArgs[I].Param); + Param); ExprResult DefArgResult; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { @@ -346,11 +350,9 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { DefArgResult = ParseAssignmentExpression(); DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult); if (DefArgResult.isInvalid()) { - Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param, - EqualLoc); + Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); } else { - if (Tok.isNot(tok::eof) || - Tok.getEofData() != LM.DefaultArgs[I].Param) { + if (Tok.isNot(tok::eof) || Tok.getEofData() != 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. @@ -359,7 +361,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { << SourceRange(Tok.getLocation(), (*Toks)[Toks->size() - 3].getLocation()); } - Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, + Actions.ActOnParamDefaultArgument(Param, EqualLoc, DefArgResult.get()); } @@ -368,11 +370,21 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { while (Tok.isNot(tok::eof)) ConsumeAnyToken(); - if (Tok.is(tok::eof) && Tok.getEofData() == LM.DefaultArgs[I].Param) + if (Tok.is(tok::eof) && Tok.getEofData() == Param) ConsumeAnyToken(); delete Toks; LM.DefaultArgs[I].Toks = nullptr; + } else if (HasUnparsed) { + assert(Param->hasInheritedDefaultArg()); + FunctionDecl *Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl(); + ParmVarDecl *OldParam = Old->getParamDecl(I); + assert (!OldParam->hasUnparsedDefaultArg()); + if (OldParam->hasUninstantiatedDefaultArg()) + Param->setUninstantiatedDefaultArg( + Param->getUninstantiatedDefaultArg()); + else + Param->setDefaultArg(OldParam->getInit()); } } @@ -383,9 +395,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { Token ExceptionSpecEnd; ExceptionSpecEnd.startToken(); ExceptionSpecEnd.setKind(tok::eof); - ExceptionSpecEnd.setLocation( - LastExceptionSpecToken.getLocation().getLocWithOffset( - LastExceptionSpecToken.getLength())); + ExceptionSpecEnd.setLocation(LastExceptionSpecToken.getEndLoc()); ExceptionSpecEnd.setEofData(LM.Method); Toks->push_back(ExceptionSpecEnd); @@ -490,8 +500,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { Token BodyEnd; BodyEnd.startToken(); BodyEnd.setKind(tok::eof); - BodyEnd.setLocation( - LastBodyToken.getLocation().getLocWithOffset(LastBodyToken.getLength())); + BodyEnd.setLocation(LastBodyToken.getEndLoc()); BodyEnd.setEofData(LM.D); LM.Toks.push_back(BodyEnd); // Append the current token at the end of the new token stream so that it @@ -501,7 +510,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { // Consume the previously pushed token. ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) + assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try) && "Inline method not starting with '{', ':' or 'try'"); // Parse the method body. Function body parsing code is similar enough @@ -816,7 +825,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { } } - if (Tok.is(tok::identifier) || Tok.is(tok::kw_template)) { + if (Tok.isOneOf(tok::identifier, tok::kw_template)) { Toks.push_back(Tok); ConsumeToken(); } else if (Tok.is(tok::code_completion)) { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 4d05e16..1c52552 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -285,7 +285,7 @@ unsigned Parser::ParseAttributeArgsCommon( if (AttrKind == AttributeList::UnknownAttribute || AttrKind == AttributeList::IgnoredAttribute) { const Token &Next = NextToken(); - IsIdentifierArg = Next.is(tok::r_paren) || Next.is(tok::comma); + IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma); } if (IsIdentifierArg) @@ -529,64 +529,72 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, /// [MS] extended-decl-modifier-seq: /// extended-decl-modifier[opt] /// extended-decl-modifier extended-decl-modifier-seq -void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) { +void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, + SourceLocation *End) { + assert((getLangOpts().MicrosoftExt || getLangOpts().Borland || + getLangOpts().CUDA) && + "Incorrect language options for parsing __declspec"); assert(Tok.is(tok::kw___declspec) && "Not a declspec!"); - ConsumeToken(); - BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec", - tok::r_paren)) - return; - - // An empty declspec is perfectly legal and should not warn. Additionally, - // you can specify multiple attributes per declspec. - while (Tok.isNot(tok::r_paren)) { - // Attribute not present. - if (TryConsumeToken(tok::comma)) - continue; - - // We expect either a well-known identifier or a generic string. Anything - // else is a malformed declspec. - bool IsString = Tok.getKind() == tok::string_literal ? true : false; - if (!IsString && Tok.getKind() != tok::identifier && - Tok.getKind() != tok::kw_restrict) { - Diag(Tok, diag::err_ms_declspec_type); - T.skipToEnd(); + while (Tok.is(tok::kw___declspec)) { + ConsumeToken(); + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec", + tok::r_paren)) return; - } - IdentifierInfo *AttrName; - SourceLocation AttrNameLoc; - if (IsString) { - SmallString<8> StrBuffer; - bool Invalid = false; - StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid); - if (Invalid) { + // An empty declspec is perfectly legal and should not warn. Additionally, + // you can specify multiple attributes per declspec. + while (Tok.isNot(tok::r_paren)) { + // Attribute not present. + if (TryConsumeToken(tok::comma)) + continue; + + // We expect either a well-known identifier or a generic string. Anything + // else is a malformed declspec. + bool IsString = Tok.getKind() == tok::string_literal; + if (!IsString && Tok.getKind() != tok::identifier && + Tok.getKind() != tok::kw_restrict) { + Diag(Tok, diag::err_ms_declspec_type); T.skipToEnd(); return; } - AttrName = PP.getIdentifierInfo(Str); - AttrNameLoc = ConsumeStringToken(); - } else { - AttrName = Tok.getIdentifierInfo(); - AttrNameLoc = ConsumeToken(); - } - bool AttrHandled = false; + IdentifierInfo *AttrName; + SourceLocation AttrNameLoc; + if (IsString) { + SmallString<8> StrBuffer; + bool Invalid = false; + StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid); + if (Invalid) { + T.skipToEnd(); + return; + } + AttrName = PP.getIdentifierInfo(Str); + AttrNameLoc = ConsumeStringToken(); + } else { + AttrName = Tok.getIdentifierInfo(); + AttrNameLoc = ConsumeToken(); + } + + bool AttrHandled = false; - // Parse attribute arguments. - if (Tok.is(tok::l_paren)) - AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs); - else if (AttrName->getName() == "property") - // The property attribute must have an argument list. - Diag(Tok.getLocation(), diag::err_expected_lparen_after) - << AttrName->getName(); + // Parse attribute arguments. + if (Tok.is(tok::l_paren)) + AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs); + else if (AttrName->getName() == "property") + // The property attribute must have an argument list. + Diag(Tok.getLocation(), diag::err_expected_lparen_after) + << AttrName->getName(); - if (!AttrHandled) - Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Declspec); + if (!AttrHandled) + Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + AttributeList::AS_Declspec); + } + T.consumeClose(); + if (End) + *End = T.getCloseLocation(); } - T.consumeClose(); } void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { @@ -679,6 +687,28 @@ void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { AttributeList::AS_Keyword); } +void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { + // Treat these like attributes, even though they're type specifiers. + while (true) { + switch (Tok.getKind()) { + case tok::kw___nonnull: + case tok::kw___nullable: + case tok::kw___null_unspecified: { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + SourceLocation AttrNameLoc = ConsumeToken(); + if (!getLangOpts().ObjC1) + Diag(AttrNameLoc, diag::ext_nullability) + << AttrName; + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + AttributeList::AS_Keyword); + break; + } + default: + return; + } + } +} + static bool VersionNumberSeparator(const char Separator) { return (Separator == '.' || Separator == '_'); } @@ -1360,6 +1390,46 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) { } } +// As an exception to the rule, __declspec(align(...)) before the +// class-key affects the type instead of the variable. +void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs, + DeclSpec &DS, + Sema::TagUseKind TUK) { + if (TUK == Sema::TUK_Reference) + return; + + ParsedAttributes &PA = DS.getAttributes(); + AttributeList *AL = PA.getList(); + AttributeList *Prev = nullptr; + while (AL) { + AttributeList *Next = AL->getNext(); + + // We only consider attributes using the appropriate '__declspec' spelling, + // this behavior doesn't extend to any other spellings. + if (AL->getKind() == AttributeList::AT_Aligned && + AL->isDeclspecAttribute()) { + // Stitch the attribute into the tag's attribute list. + AL->setNext(nullptr); + Attrs.add(AL); + + // Remove the attribute from the variable's attribute list. + if (Prev) { + // Set the last variable attribute's next attribute to be the attribute + // after the current one. + Prev->setNext(Next); + } else { + // Removing the head of the list requires us to reset the head to the + // next attribute. + PA.set(Next); + } + } else { + Prev = AL; + } + + AL = Next; + } +} + /// ParseDeclaration - Parse a full 'declaration', which consists of /// declaration-specifiers, some number of declarators, and a semicolon. /// 'Context' should be a Declarator::TheContext value. This returns the @@ -1551,7 +1621,7 @@ void Parser::SkipMalformedDecl() { // a malformed class or function definition or similar. ConsumeBrace(); SkipUntil(tok::r_brace); - if (Tok.is(tok::comma) || Tok.is(tok::l_brace) || Tok.is(tok::kw_try)) { + if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) { // This declaration isn't over yet. Keep skipping. continue; } @@ -1657,7 +1727,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // 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); + Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try); Diag(Loc, diag::err_c11_noreturn_misplaced) << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint()) @@ -1691,11 +1761,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } if (isDeclarationSpecifier()) { - // If there is an invalid declaration specifier right after the function - // prototype, then we must be in a missing semicolon case where this isn't - // actually a body. Just fall through into the code that handles it as a - // prototype, and let the top-level code handle the erroneous declspec - // where it would otherwise expect a comma or semicolon. + // If there is an invalid declaration specifier right after the + // function prototype, then we must be in a missing semicolon case + // where this isn't actually a body. Just fall through into the code + // that handles it as a prototype, and let the top-level code handle + // the erroneous declspec where it would otherwise expect a comma or + // semicolon. } else { Diag(Tok, diag::err_expected_fn_body); SkipUntil(tok::semi); @@ -1993,7 +2064,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl); } - if (ParseExpressionList(Exprs, CommaLocs)) { + if (ParseExpressionList(Exprs, CommaLocs, [&] { + Actions.CodeCompleteConstructor(getCurScope(), + cast<VarDecl>(ThisDecl)->getType()->getCanonicalTypeInternal(), + ThisDecl->getLocation(), Exprs); + })) { Actions.ActOnInitializerError(ThisDecl); SkipUntil(tok::r_paren, StopAtSemi); @@ -2123,9 +2198,9 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, /// int (x) /// static bool isValidAfterIdentifierInDeclarator(const Token &T) { - return T.is(tok::l_square) || T.is(tok::l_paren) || T.is(tok::r_paren) || - T.is(tok::semi) || T.is(tok::comma) || T.is(tok::equal) || - T.is(tok::kw_asm) || T.is(tok::l_brace) || T.is(tok::colon); + return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi, + tok::comma, tok::equal, tok::kw_asm, tok::l_brace, + tok::colon); } @@ -2385,7 +2460,7 @@ ExprResult Parser::ParseAlignArgument(SourceLocation Start, /// [C++11] 'alignas' '(' assignment-expression ...[opt] ')' void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, SourceLocation *EndLoc) { - assert((Tok.is(tok::kw_alignas) || Tok.is(tok::kw__Alignas)) && + assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) && "Not an alignment-specifier!"); IdentifierInfo *KWName = Tok.getIdentifierInfo(); @@ -2428,8 +2503,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); if (getLangOpts().CPlusPlus && - (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || - Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) && + Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype, + tok::annot_template_id) && TryAnnotateCXXScopeToken(EnteringContext)) { SkipMalformedDecl(); return true; @@ -2442,7 +2517,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, // Determine whether the following tokens could possibly be a // declarator. bool MightBeDeclarator = true; - if (Tok.is(tok::kw_typename) || Tok.is(tok::annot_typename)) { + if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) { // A declarator-id can't start with 'typename'. MightBeDeclarator = false; } else if (AfterScope.is(tok::annot_template_id)) { @@ -2457,9 +2532,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, // These tokens cannot come after the declarator-id in a // simple-declaration, and are likely to come after a type-specifier. - if (Next.is(tok::star) || Next.is(tok::amp) || Next.is(tok::ampamp) || - Next.is(tok::identifier) || Next.is(tok::annot_cxxscope) || - Next.is(tok::coloncolon)) { + if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier, + tok::annot_cxxscope, tok::coloncolon)) { // Missing a semicolon. MightBeDeclarator = false; } else if (HasScope) { @@ -2564,7 +2638,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); bool AttrsLastTime = false; ParsedAttributesWithRange attrs(AttrFactory); - const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); + // We use Sema's policy to get bool macros right. + const PrintingPolicy &Policy = Actions.getPrintingPolicy(); while (1) { bool isInvalid = false; bool isStorageClass = false; @@ -2866,14 +2941,27 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DS.isTypeAltiVecVector()) goto DoneWithDeclSpec; + if (DSContext == DSC_objc_method_result && isObjCInstancetype()) { + ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc); + assert(TypeRep); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, + DiagID, TypeRep, Policy); + if (isInvalid) + break; + + DS.SetRangeEnd(Loc); + ConsumeToken(); + continue; + } + ParsedType TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope()); // MSVC: If we weren't able to parse a default template argument, and it's - // just a simple identifier, create a DependentNameType. This will allow us - // to defer the name lookup to template instantiation time, as long we forge a - // NestedNameSpecifier for the current context. + // just a simple identifier, create a DependentNameType. This will allow + // us to defer the name lookup to template instantiation time, as long we + // forge a NestedNameSpecifier for the current context. if (!TypeRep && DSContext == DSC_template_type_arg && getLangOpts().MSVCCompat && getCurScope()->isTemplateParamScope()) { TypeRep = Actions.ActOnDelayedDefaultTemplateArg( @@ -2950,7 +3038,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Microsoft declspec support. case tok::kw___declspec: - ParseMicrosoftDeclSpec(DS.getAttributes()); + ParseMicrosoftDeclSpecs(DS.getAttributes()); continue; // Microsoft single token adornments. @@ -2987,6 +3075,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseOpenCLAttributes(DS.getAttributes()); continue; + // Nullability type specifiers. + case tok::kw___nonnull: + case tok::kw___nullable: + case tok::kw___null_unspecified: + ParseNullabilityTypeSpecifiers(DS.getAttributes()); + continue; + // storage-class-specifier case tok::kw_typedef: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc, @@ -3594,16 +3689,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, ParsedAttributesWithRange attrs(AttrFactory); MaybeParseGNUAttributes(attrs); MaybeParseCXX11Attributes(attrs); - - // If declspecs exist after tag, parse them. - while (Tok.is(tok::kw___declspec)) - ParseMicrosoftDeclSpec(attrs); + MaybeParseMicrosoftDeclSpecs(attrs); SourceLocation ScopedEnumKWLoc; bool IsScopedUsingClassTag = false; // In C++11, recognize 'enum class' and 'enum struct'. - if (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct)) { + if (Tok.isOneOf(tok::kw_class, tok::kw_struct)) { Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum : diag::ext_scoped_enum); IsScopedUsingClassTag = Tok.is(tok::kw_class); @@ -3616,8 +3708,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // They are allowed afterwards, though. MaybeParseGNUAttributes(attrs); MaybeParseCXX11Attributes(attrs); - while (Tok.is(tok::kw___declspec)) - ParseMicrosoftDeclSpec(attrs); + MaybeParseMicrosoftDeclSpecs(attrs); } // C++11 [temp.explicit]p12: @@ -3644,11 +3735,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // if a fixed underlying type is allowed. ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType); - if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), + CXXScopeSpec Spec; + if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), /*EnteringContext=*/true)) return; - if (SS.isSet() && Tok.isNot(tok::identifier)) { + if (Spec.isSet() && Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected) << tok::identifier; if (Tok.isNot(tok::l_brace)) { // Has no name and is not a definition. @@ -3657,6 +3749,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } } + + SS = Spec; } // Must have either 'enum name' or 'enum {...}'. @@ -3842,6 +3936,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } + handleDeclspecAlignBeforeClassKey(attrs, DS, TUK); + + Sema::SkipBodyInfo SkipBody; + if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) && + NextToken().is(tok::identifier)) + SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(), + NextToken().getIdentifierInfo(), + NextToken().getLocation()); + bool Owned = false; bool IsDependent = false; const char *PrevSpec = nullptr; @@ -3851,7 +3954,22 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, - DSC == DSC_type_specifier); + DSC == DSC_type_specifier, &SkipBody); + + if (SkipBody.ShouldSkip) { + assert(TUK == Sema::TUK_Definition && "can only skip a definition"); + + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); + T.skipToEnd(); + + if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, + NameLoc.isValid() ? NameLoc : StartLoc, + PrevSpec, DiagID, TagDecl, Owned, + Actions.getASTContext().getPrintingPolicy())) + Diag(StartLoc, DiagID) << PrevSpec; + return; + } if (IsDependent) { // This enum has a dependent nested-name-specifier. Handle it as a @@ -3923,6 +4041,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { Diag(Tok, diag::error_empty_enum); SmallVector<Decl *, 32> EnumConstantDecls; + SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags; Decl *LastEnumConstDecl = nullptr; @@ -3953,7 +4072,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { SourceLocation EqualLoc; ExprResult AssignedVal; - ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); + EnumAvailabilityDiags.emplace_back(*this); if (TryConsumeToken(tok::equal, EqualLoc)) { AssignedVal = ParseConstantExpression(); @@ -3967,7 +4086,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { IdentLoc, Ident, attrs.getList(), EqualLoc, AssignedVal.get()); - PD.complete(EnumConstDecl); + EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); LastEnumConstDecl = EnumConstDecl; @@ -4023,6 +4142,14 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { getCurScope(), attrs.getList()); + // Now handle enum constant availability diagnostics. + assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); + for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) { + ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); + EnumAvailabilityDiags[i].redelay(); + PD.complete(EnumConstantDecls[i]); + } + EnumScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getCloseLocation()); @@ -4199,6 +4326,10 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___pascal: case tok::kw___unaligned: + case tok::kw___nonnull: + case tok::kw___nullable: + case tok::kw___null_unspecified: + case tok::kw___private: case tok::kw___local: case tok::kw___global: @@ -4372,6 +4503,10 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___pascal: case tok::kw___unaligned: + case tok::kw___nonnull: + case tok::kw___nullable: + case tok::kw___null_unspecified: + case tok::kw___private: case tok::kw___local: case tok::kw___global: @@ -4397,7 +4532,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { } // Parse the constructor name. - if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { + if (Tok.isOneOf(tok::identifier, tok::annot_template_id)) { // We already know that we have a constructor name; just consume // the token. ConsumeToken(); @@ -4601,6 +4736,14 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, continue; } goto DoneWithTypeQuals; + + // Nullability type specifiers. + case tok::kw___nonnull: + case tok::kw___nullable: + case tok::kw___null_unspecified: + ParseNullabilityTypeSpecifiers(DS.getAttributes()); + continue; + case tok::kw___attribute: if (AttrReqs & AR_GNUAttributesParsedAndRejected) // When GNU attributes are expressly forbidden, diagnose their usage. @@ -4773,7 +4916,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(), DS.getVolatileSpecLoc(), - DS.getRestrictSpecLoc()), + DS.getRestrictSpecLoc(), + DS.getAtomicSpecLoc()), DS.getAttributes(), SourceLocation()); else @@ -4916,7 +5060,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } if (D.getCXXScopeSpec().isValid()) { - if (Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec())) + if (Actions.ShouldEnterDeclaratorScope(getCurScope(), + D.getCXXScopeSpec())) // Change the declaration context for name lookup, until this function // is exited (and the declarator has been parsed). DeclScopeObj.EnterDeclaratorScope(); @@ -4953,8 +5098,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // the l_paren token. } - if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) || - Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) { + if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id, + tok::tilde)) { // We found something that indicates the start of an unqualified-id. // Parse that unqualified-id. bool AllowConstructorName; @@ -4968,6 +5113,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { AllowConstructorName = (D.getContext() == Declarator::MemberContext); SourceLocation TemplateKWLoc; + bool HadScope = D.getCXXScopeSpec().isValid(); if (ParseUnqualifiedId(D.getCXXScopeSpec(), /*EnteringContext=*/true, /*AllowDestructorName=*/true, @@ -4981,6 +5127,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.SetIdentifier(nullptr, Tok.getLocation()); D.setInvalidType(true); } else { + // ParseUnqualifiedId might have parsed a scope specifier during error + // recovery. If it did so, enter that scope. + if (!HadScope && D.getCXXScopeSpec().isValid() && + Actions.ShouldEnterDeclaratorScope(getCurScope(), + D.getCXXScopeSpec())) + DeclScopeObj.EnterDeclaratorScope(); + // Parsed the unqualified-id; update range information and move along. if (D.getSourceRange().getBegin().isInvalid()) D.SetRangeBegin(D.getName().getSourceRange().getBegin()); @@ -5022,7 +5175,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // If there was an error parsing parenthesized declarator, declarator // scope may have been entered before. Don't do it again. if (!D.isInvalidType() && - Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec())) + Actions.ShouldEnterDeclaratorScope(getCurScope(), + D.getCXXScopeSpec())) // Change the declaration context for name lookup, until this function // is exited (and the declarator has been parsed). DeclScopeObj.EnterDeclaratorScope(); @@ -5048,7 +5202,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { << (D.getDeclSpec().isEmpty() ? SourceRange() : D.getDeclSpec().getSourceRange()); } else if (getLangOpts().CPlusPlus) { - if (Tok.is(tok::period) || Tok.is(tok::arrow)) + if (Tok.isOneOf(tok::period, tok::arrow)) Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); else { SourceLocation Loc = D.getCXXScopeSpec().getEndLoc(); @@ -5310,7 +5464,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (getLangOpts().CPlusPlus) { // FIXME: Accept these components in any order, and produce fixits to // correct the order if the user gets it wrong. Ideally we should deal - // with the virt-specifier-seq and pure-specifier in the same way. + // with the pure-specifier in the same way. // Parse cv-qualifier-seq[opt]. ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, @@ -5323,15 +5477,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, } // Parse ref-qualifier[opt]. - if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_ref_qualifier : - diag::ext_ref_qualifier); - - RefQualifierIsLValueRef = Tok.is(tok::amp); - RefQualifierLoc = ConsumeToken(); + if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) EndLoc = RefQualifierLoc; - } // C++11 [expr.prim.general]p3: // If a declaration declares a member function or member function @@ -5427,6 +5574,22 @@ void Parser::ParseFunctionDeclarator(Declarator &D, FnAttrs, EndLoc); } +/// ParseRefQualifier - Parses a member function ref-qualifier. Returns +/// true if a ref-qualifier is found. +bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef, + SourceLocation &RefQualifierLoc) { + if (Tok.isOneOf(tok::amp, tok::ampamp)) { + Diag(Tok, getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_ref_qualifier : + diag::ext_ref_qualifier); + + RefQualifierIsLValueRef = Tok.is(tok::amp); + RefQualifierLoc = ConsumeToken(); + return true; + } + return false; +} + /// isFunctionDeclaratorIdentifierList - This parameter list may have an /// identifier list form for a K&R-style function: void foo(a,b,c) /// diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 87d9909..47778b8 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -558,6 +558,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // Maybe this is an alias-declaration. TypeResult TypeAlias; bool IsAliasDecl = Tok.is(tok::equal); + Decl *DeclFromDeclSpec = nullptr; if (IsAliasDecl) { // If we had any misplaced attributes from earlier, this is where they // should have been written. @@ -612,10 +613,12 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) << FixItHint::CreateRemoval(SS.getRange()); - TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind ? - Declarator::AliasTemplateContext : - Declarator::AliasDeclContext, AS, OwnedType, - &Attrs); + TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind + ? Declarator::AliasTemplateContext + : Declarator::AliasDeclContext, + AS, &DeclFromDeclSpec, &Attrs); + if (OwnedType) + *OwnedType = DeclFromDeclSpec; } else { // C++11 attributes are not allowed on a using-declaration, but GNU ones // are. @@ -664,7 +667,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, UsingLoc, Name, Attrs.getList(), - TypeAlias); + TypeAlias, DeclFromDeclSpec); } return Actions.ActOnUsingDeclaration(getCurScope(), AS, @@ -682,7 +685,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, /// _Static_assert ( constant-expression , string-literal ) ; /// Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ - assert((Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) && + assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) && "Not a static_assert declaration"); if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11) @@ -750,7 +753,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ /// 'decltype' ( 'auto' ) [C++1y] /// SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { - assert((Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) + assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype) && "Not a decltype specifier"); ExprResult Result; @@ -796,7 +799,10 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // The operand of the decltype specifier is an unevaluated operand. EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, nullptr,/*IsDecltype=*/true); - Result = Actions.CorrectDelayedTyposInExpr(ParseExpression()); + Result = + Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) { + return E->hasPlaceholderType() ? ExprError() : E; + }); if (Result.isInvalid()) { DS.SetTypeSpecError(); if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) { @@ -937,7 +943,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Parse decltype-specifier // tok == kw_decltype is just error recovery, it can only happen when SS // isn't empty - if (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype)) { + if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) { if (SS.isNotEmpty()) Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype) << FixItHint::CreateRemoval(SS.getRange()); @@ -1052,9 +1058,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, } void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { - while (Tok.is(tok::kw___single_inheritance) || - Tok.is(tok::kw___multiple_inheritance) || - Tok.is(tok::kw___virtual_inheritance)) { + while (Tok.isOneOf(tok::kw___single_inheritance, + tok::kw___multiple_inheritance, + tok::kw___virtual_inheritance)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, @@ -1223,15 +1229,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, ParsedAttributesWithRange attrs(AttrFactory); // If attributes exist after tag, parse them. MaybeParseGNUAttributes(attrs); - - // If declspecs exist after tag, parse them. - while (Tok.is(tok::kw___declspec)) - ParseMicrosoftDeclSpec(attrs); + MaybeParseMicrosoftDeclSpecs(attrs); // Parse inheritance specifiers. - if (Tok.is(tok::kw___single_inheritance) || - Tok.is(tok::kw___multiple_inheritance) || - Tok.is(tok::kw___virtual_inheritance)) + if (Tok.isOneOf(tok::kw___single_inheritance, + tok::kw___multiple_inheritance, + tok::kw___virtual_inheritance)) ParseMicrosoftInheritanceClassAttributes(attrs); // If C++0x attributes exist here, parse them. @@ -1247,55 +1250,55 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, 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))) + Tok.isOneOf(tok::kw___is_abstract, + tok::kw___is_arithmetic, + tok::kw___is_array, + tok::kw___is_base_of, + tok::kw___is_class, + tok::kw___is_complete_type, + tok::kw___is_compound, + tok::kw___is_const, + tok::kw___is_constructible, + tok::kw___is_convertible, + tok::kw___is_convertible_to, + tok::kw___is_destructible, + tok::kw___is_empty, + tok::kw___is_enum, + tok::kw___is_floating_point, + tok::kw___is_final, + tok::kw___is_function, + tok::kw___is_fundamental, + tok::kw___is_integral, + tok::kw___is_interface_class, + tok::kw___is_literal, + tok::kw___is_lvalue_expr, + tok::kw___is_lvalue_reference, + tok::kw___is_member_function_pointer, + tok::kw___is_member_object_pointer, + tok::kw___is_member_pointer, + tok::kw___is_nothrow_assignable, + tok::kw___is_nothrow_constructible, + tok::kw___is_nothrow_destructible, + tok::kw___is_object, + tok::kw___is_pod, + tok::kw___is_pointer, + tok::kw___is_polymorphic, + tok::kw___is_reference, + tok::kw___is_rvalue_expr, + tok::kw___is_rvalue_reference, + tok::kw___is_same, + tok::kw___is_scalar, + tok::kw___is_sealed, + tok::kw___is_signed, + tok::kw___is_standard_layout, + tok::kw___is_trivial, + tok::kw___is_trivially_assignable, + tok::kw___is_trivially_constructible, + tok::kw___is_trivially_copyable, + tok::kw___is_union, + tok::kw___is_unsigned, + tok::kw___is_void, + 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 @@ -1310,11 +1313,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // is a base-specifier-list. ColonProtectionRAIIObject X(*this); - if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) + CXXScopeSpec Spec; + bool HasValidSpec = true; + if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), EnteringContext)) { DS.SetTypeSpecError(); - if (SS.isSet()) - if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) + HasValidSpec = false; + } + if (Spec.isSet()) + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) { Diag(Tok, diag::err_expected) << tok::identifier; + HasValidSpec = false; + } + if (HasValidSpec) + SS = Spec; } TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; @@ -1465,7 +1476,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } } - if (Tok.is(tok::l_brace) || Tok.is(tok::colon)) + if (Tok.isOneOf(tok::l_brace, tok::colon)) TUK = Sema::TUK_Definition; else TUK = Sema::TUK_Reference; @@ -1539,6 +1550,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TypeResult TypeResult = true; // invalid bool Owned = false; + Sema::SkipBodyInfo SkipBody; if (TemplateId) { // Explicit specialization, class template partial specialization, // or explicit instantiation. @@ -1625,7 +1637,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, *TemplateId, attrs.getList(), MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, - TemplateParams ? TemplateParams->size() : 0)); + TemplateParams ? TemplateParams->size() : 0), + &SkipBody); } } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Sema::TUK_Declaration) { @@ -1677,6 +1690,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TParams = MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); + handleDeclspecAlignBeforeClassKey(attrs, DS, TUK); + // Declaration or definition of a class type TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs.getList(), AS, @@ -1684,7 +1699,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TParams, Owned, IsDependent, SourceLocation(), false, clang::TypeResult(), - DSC == DSC_type_specifier); + DSC == DSC_type_specifier, + &SkipBody); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -1700,7 +1716,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, assert(Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || isCXX11FinalKeyword()); - if (getLangOpts().CPlusPlus) + if (SkipBody.ShouldSkip) + SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, + TagOrTempResult.get()); + else if (getLangOpts().CPlusPlus) ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, TagOrTempResult.get()); else @@ -1882,51 +1901,40 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const { /// the class definition. void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, Decl *ThisDecl) { - // We just declared a member function. If this member function - // 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, we'll need a + // late parse + bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed; + + if (!NeedLateParse) { + // Look ahead to see if there are any default args + for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) { + auto Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param); + if (Param->hasUnparsedDefaultArg()) { + NeedLateParse = true; + break; + } + } + } - // If there was a late-parsed exception-specification, hold onto its tokens. - if (FTI.getExceptionSpecType() == EST_Unparsed) { + if (NeedLateParse) { // Push this method onto the stack of late-parsed method // declarations. - LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); + auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); getCurrentClass().LateParsedDeclarations.push_back(LateMethod); LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); - // Stash the exception-specification tokens in the late-pased mthod. + // Stash the exception-specification tokens in the late-pased method. LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; FTI.ExceptionSpecTokens = 0; - // Reserve space for the parameters. + // Push tokens for each parameter. Those that do not have + // defaults will be NULL. LateMethod->DefaultArgs.reserve(FTI.NumParams); - } - - for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) { - if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) { - if (!LateMethod) { - // Push this method onto the stack of late-parsed method - // declarations. - LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); - getCurrentClass().LateParsedDeclarations.push_back(LateMethod); - LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); - - // Add all of the parameters prior to this one (they don't - // have default arguments). - LateMethod->DefaultArgs.reserve(FTI.NumParams); - for (unsigned I = 0; I < ParamIdx; ++I) - LateMethod->DefaultArgs.push_back( - LateParsedDefaultArgument(FTI.Params[I].Param)); - } - - // Add this parameter to the list of parameters (it may or may - // not have a default argument). + for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument( - FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens)); - } + FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens)); } } @@ -2019,7 +2027,7 @@ bool Parser::isCXX11FinalKeyword() const { /// \brief Parse a C++ member-declarator up to, but not including, the optional /// brace-or-equal-initializer or pure-specifier. -void Parser::ParseCXXMemberDeclaratorBeforeInitializer( +bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize, LateParsedAttrList &LateParsedAttrs) { // member-declarator: @@ -2037,10 +2045,13 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( BitfieldSize = ParseConstantExpression(); if (BitfieldSize.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - } else + } else { ParseOptionalCXX11VirtSpecifierSeq( VS, getCurrentClass().IsInterface, DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); + if (!VS.isUnset()) + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); + } // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { @@ -2071,6 +2082,78 @@ void Parser::ParseCXXMemberDeclaratorBeforeInitializer( Diag(Attr->getLoc(), diag::warn_gcc_attribute_location); Attr = Attr->getNext(); } + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); + } + } + + // If this has neither a name nor a bit width, something has gone seriously + // wrong. Skip until the semi-colon or }. + if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) { + // If so, skip until the semi-colon or a }. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + return true; + } + return false; +} + +/// \brief Look for declaration specifiers possibly occurring after C++11 +/// virt-specifier-seq and diagnose them. +void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( + Declarator &D, + VirtSpecifiers &VS) { + DeclSpec DS(AttrFactory); + + // GNU-style and C++11 attributes are not allowed here, but they will be + // handled by the caller. Diagnose everything else. + ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false); + D.ExtendWithDeclSpec(DS); + + if (D.isFunctionDeclarator()) { + auto &Function = D.getFunctionTypeInfo(); + if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) { + auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual, + const char *FixItName, + SourceLocation SpecLoc, + unsigned* QualifierLoc) { + FixItHint Insertion; + if (DS.getTypeQualifiers() & TypeQual) { + if (!(Function.TypeQuals & TypeQual)) { + std::string Name(FixItName); + Name += " "; + Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name.c_str()); + Function.TypeQuals |= TypeQual; + *QualifierLoc = SpecLoc.getRawEncoding(); + } + Diag(SpecLoc, diag::err_declspec_after_virtspec) + << FixItName + << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) + << FixItHint::CreateRemoval(SpecLoc) + << Insertion; + } + }; + DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(), + &Function.ConstQualifierLoc); + DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(), + &Function.VolatileQualifierLoc); + DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(), + &Function.RestrictQualifierLoc); + } + + // Parse ref-qualifiers. + bool RefQualifierIsLValueRef = true; + SourceLocation RefQualifierLoc; + if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) { + const char *Name = (RefQualifierIsLValueRef ? "& " : "&& "); + FixItHint Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name); + Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef; + Function.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); + + Diag(RefQualifierLoc, diag::err_declspec_after_virtspec) + << (RefQualifierIsLValueRef ? "&" : "&&") + << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) + << FixItHint::CreateRemoval(RefQualifierLoc) + << Insertion; + D.SetRangeEnd(RefQualifierLoc); } } } @@ -2137,8 +2220,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Access declarations. bool MalformedTypeSpec = false; if (!TemplateInfo.Kind && - (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || - Tok.is(tok::kw___super))) { + Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw___super)) { if (TryAnnotateCXXScopeToken()) MalformedTypeSpec = true; @@ -2191,7 +2273,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // 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))) { + Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { SourceLocation DeclEnd; ParseStaticAssertDeclaration(DeclEnd); return; @@ -2298,14 +2380,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, bool ExpectSemi = true; // Parse the first declarator. - ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, - LateParsedAttrs); - - // If this has neither a name nor a bit width, something has gone seriously - // wrong. Skip until the semi-colon or }. - if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) { - // If so, skip until the semi-colon or a }. - SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + if (ParseCXXMemberDeclaratorBeforeInitializer( + DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) { TryConsumeToken(tok::semi); return; } @@ -2334,7 +2410,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus11) { DefinitionKind = FDK_Definition; } else if (DeclaratorInfo.isFunctionDeclarator()) { - if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) { + if (Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)) { DefinitionKind = FDK_Definition; } else if (Tok.is(tok::equal)) { const Token &KW = NextToken(); @@ -2344,6 +2420,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DefinitionKind = FDK_Deleted; } } + DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind); // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains // to a friend declaration, that declaration shall be a definition. @@ -2354,7 +2431,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ProhibitAttributes(FnAttrs); } - if (DefinitionKind) { + if (DefinitionKind != FDK_Declaration) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params); ConsumeBrace(); @@ -2376,7 +2453,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, - VS, DefinitionKind, Init); + VS, Init); if (FunDecl) { for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { @@ -2402,7 +2479,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, while (1) { InClassInitStyle HasInClassInit = ICIS_NoInit; - if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) { + if (Tok.isOneOf(tok::equal, tok::l_brace) && !HasInitializer) { if (BitfieldSize.get()) { Diag(Tok, diag::err_bitfield_member_init); SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); @@ -2530,16 +2607,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Parse the next declarator. DeclaratorInfo.clear(); VS.clear(); - BitfieldSize = true; - Init = true; + BitfieldSize = ExprResult(/*Invalid=*/false); + Init = ExprResult(/*Invalid=*/false); HasInitializer = false; DeclaratorInfo.setCommaLoc(CommaLoc); // GNU attributes are allowed before the second and subsequent declarator. MaybeParseGNUAttributes(DeclaratorInfo); - ParseCXXMemberDeclaratorBeforeInitializer(DeclaratorInfo, VS, BitfieldSize, - LateParsedAttrs); + if (ParseCXXMemberDeclaratorBeforeInitializer( + DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) + break; } if (ExpectSemi && @@ -2578,7 +2656,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, /// be a constant-expression. ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc) { - assert((Tok.is(tok::equal) || Tok.is(tok::l_brace)) + assert(Tok.isOneOf(tok::equal, tok::l_brace) && "Data member initializer not starting with '=' or '{'"); EnterExpressionEvaluationContext Context(Actions, @@ -2592,8 +2670,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, // An initializer of '= delete p, foo' will never be parsed, because // a top-level comma always ends the initializer expression. const Token &Next = NextToken(); - if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) || - Next.is(tok::eof)) { + if (IsFunction || Next.isOneOf(tok::semi, tok::comma, tok::eof)) { if (IsFunction) Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) << 1 /* delete */; @@ -2617,6 +2694,56 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, return ParseInitializer(); } +void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, + SourceLocation AttrFixitLoc, + unsigned TagType, Decl *TagDecl) { + // Skip the optional 'final' keyword. + if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) { + assert(isCXX11FinalKeyword() && "not a class definition"); + ConsumeToken(); + + // Diagnose any C++11 attributes after 'final' keyword. + // We deliberately discard these attributes. + ParsedAttributesWithRange Attrs(AttrFactory); + CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc); + + // This can only happen if we had malformed misplaced attributes; + // we only get called if there is a colon or left-brace after the + // attributes. + if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace)) + return; + } + + // Skip the base clauses. This requires actually parsing them, because + // otherwise we can't be sure where they end (a left brace may appear + // within a template argument). + if (Tok.is(tok::colon)) { + // Enter the scope of the class so that we can correctly parse its bases. + ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope); + ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true, + TagType == DeclSpec::TST_interface); + auto OldContext = + Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl); + + // Parse the bases but don't attach them to the class. + ParseBaseClause(nullptr); + + Actions.ActOnTagFinishSkippedDefinition(OldContext); + + if (!Tok.is(tok::l_brace)) { + Diag(PP.getLocForEndOfToken(PrevTokLocation), + diag::err_expected_lbrace_after_base_specifiers); + return; + } + } + + // Skip the body. + assert(Tok.is(tok::l_brace)); + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); + T.skipToEnd(); +} + /// ParseCXXMemberSpecification - Parse the class definition. /// /// member-specification: @@ -2787,8 +2914,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // Each iteration of this loop reads one member-declaration. - if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) || - Tok.is(tok::kw___if_not_exists))) { + if (getLangOpts().MicrosoftExt && Tok.isOneOf(tok::kw___if_exists, + tok::kw___if_not_exists)) { ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); continue; } @@ -2911,6 +3038,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, ParseLexedMemberInitializers(getCurrentClass()); ParseLexedMethodDefs(getCurrentClass()); PrevTokLocation = SavedPrevTokLocation; + + // We've finished parsing everything, including default argument + // initializers. + Actions.ActOnFinishCXXMemberDefaultArgs(TagDecl); } if (TagDecl) @@ -2965,9 +3096,11 @@ void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) { /// mem-initializer ...[opt] /// mem-initializer ...[opt] , mem-initializer-list void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { - assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'"); + assert(Tok.is(tok::colon) && + "Constructor initializer always starts with ':'"); - // Poison the SEH identifiers so they are flagged as illegal in constructor initializers + // Poison the SEH identifiers so they are flagged as illegal in constructor + // initializers. PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); SourceLocation ColonLoc = ConsumeToken(); @@ -2993,7 +3126,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { break; // If the next token looks like a base or member initializer, assume that // we're just missing a comma. - else if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) { + else if (Tok.isOneOf(tok::identifier, tok::coloncolon)) { SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation); Diag(Loc, diag::err_ctor_init_missing_comma) << FixItHint::CreateInsertion(Loc, ", "); @@ -3396,7 +3529,9 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { // Alternative tokens do not have identifier info, but their spelling // starts with an alphabetical character. SmallString<8> SpellingBuf; - StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf); + SourceLocation SpellingLoc = + PP.getSourceManager().getSpellingLoc(Tok.getLocation()); + StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf); if (isLetter(Spelling[0])) { Loc = ConsumeToken(); return &PP.getIdentifierTable().get(Spelling); @@ -3474,7 +3609,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // The attribute was allowed to have arguments, but none were provided // even though the attribute parsed successfully. This is an error. Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; - return false; } else if (!Attr->getMaxArgs()) { // The attribute parsed successfully, but was not allowed to have any // arguments. It doesn't matter whether any were provided -- the @@ -3482,7 +3616,6 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) << AttrName << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); - return false; } } } @@ -3645,7 +3778,7 @@ SourceLocation Parser::SkipCXX11Attributes() { return EndLoc; } -/// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr] +/// Parse one or more Microsoft-style attributes [Attr] /// /// [MS] ms-attribute: /// '[' token-seq ']' @@ -3657,13 +3790,17 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, SourceLocation *endLoc) { assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list"); - while (Tok.is(tok::l_square)) { + do { // FIXME: If this is actually a C++11 attribute, parse it as one. - ConsumeBracket(); + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + if (Tok.is(tok::r_square)) + Diag(T.getOpenLocation(), diag::err_empty_attribute_block); SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch); - if (endLoc) *endLoc = Tok.getLocation(); - ExpectAndConsume(tok::r_square); - } + T.consumeClose(); + if (endLoc) + *endLoc = T.getCloseLocation(); + } while (Tok.is(tok::l_square)); } void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, @@ -3695,7 +3832,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. - if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { + if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); continue; } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index d0d97de..da759c7 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -347,7 +347,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { RHS = ParseCastExpression(false); if (RHS.isInvalid()) { + // FIXME: Errors generated by the delayed typo correction should be + // printed before errors from parsing the RHS, not after. Actions.CorrectDelayedTyposInExpr(LHS); + if (TernaryMiddle.isUsable()) + TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle); LHS = ExprError(); } @@ -380,7 +384,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { RHSIsInitList = false; if (RHS.isInvalid()) { + // FIXME: Errors generated by the delayed typo correction should be + // printed before errors from ParseRHSOfBinaryExpression, not after. Actions.CorrectDelayedTyposInExpr(LHS); + if (TernaryMiddle.isUsable()) + TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle); LHS = ExprError(); } @@ -446,8 +454,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, namespace { class CastExpressionIdValidator : public CorrectionCandidateCallback { public: - CastExpressionIdValidator(bool AllowTypes, bool AllowNonTypes) - : AllowNonTypes(AllowNonTypes) { + CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes) + : NextToken(Next), AllowNonTypes(AllowNonTypes) { WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes; } @@ -458,11 +466,23 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { if (isa<TypeDecl>(ND)) return WantTypeSpecifiers; - return AllowNonTypes && - CorrectionCandidateCallback::ValidateCandidate(candidate); + + if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate)) + return false; + + if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period)) + return true; + + for (auto *C : candidate) { + NamedDecl *ND = C->getUnderlyingDecl(); + if (isa<ValueDecl>(ND) && !isa<FunctionDecl>(ND)) + return true; + } + return false; } private: + Token NextToken; bool AllowNonTypes; }; } @@ -808,11 +828,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } } - if (Next.is(tok::coloncolon) || - (!ColonIsSacred && Next.is(tok::colon)) || - Next.is(tok::less) || - Next.is(tok::l_paren) || - Next.is(tok::l_brace)) { + if ((!ColonIsSacred && Next.is(tok::colon)) || + Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren, + tok::l_brace)) { // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse. if (TryAnnotateTypeOrScopeToken()) return ExprError(); @@ -908,14 +926,20 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, SourceLocation TemplateKWLoc; Token Replacement; auto Validator = llvm::make_unique<CastExpressionIdValidator>( - isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); + Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); Validator->IsAddressOfOperand = isAddressOfOperand; - Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren); + if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) { + Validator->WantExpressionKeywords = false; + Validator->WantRemainingKeywords = false; + } else { + Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren); + } Name.setIdentifier(&II, ILoc); Res = Actions.ActOnIdExpression( getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), isAddressOfOperand, std::move(Validator), - /*IsInlineAsmIdentifier=*/false, &Replacement); + /*IsInlineAsmIdentifier=*/false, + Tok.is(tok::r_paren) ? nullptr : &Replacement); if (!Res.isInvalid() && !Res.get()) { UnconsumeToken(Replacement); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, @@ -1441,10 +1465,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall, - LHS.get())) { + if (ParseExpressionList(ArgExprs, CommaLocs, [&] { + Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs); + })) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); + } else if (LHS.isInvalid()) { + for (auto &E : ArgExprs) + Actions.CorrectDelayedTyposInExpr(E); } } } @@ -1453,7 +1481,19 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (LHS.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); } else if (Tok.isNot(tok::r_paren)) { - PT.consumeClose(); + bool HadDelayedTypo = false; + if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get()) + HadDelayedTypo = true; + for (auto &E : ArgExprs) + if (Actions.CorrectDelayedTyposInExpr(E).get() != E) + HadDelayedTypo = true; + // If there were delayed typos in the LHS or ArgExprs, call SkipUntil + // instead of PT.consumeClose() to avoid emitting extra diagnostics for + // the unmatched l_paren. + if (HadDelayedTypo) + SkipUntil(tok::r_paren, StopAtSemi); + else + PT.consumeClose(); LHS = ExprError(); } else { assert((ArgExprs.size() == 0 || @@ -1510,14 +1550,14 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { cutOffParsing(); return ExprError(); } - + if (MayBePseudoDestructor && !LHS.isInvalid()) { LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS, ObjectType); break; } - // Either the action has told is that this cannot be a + // Either the action has told us that this cannot be a // pseudo-destructor expression (based on the type of base // expression), or we didn't see a '~' in the right place. We // can still parse a destructor name here, but in that case it @@ -1526,7 +1566,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // FIXME: Add support for explicit call of template constructor. SourceLocation TemplateKWLoc; UnqualifiedId Name; - if (getLangOpts().ObjC2 && OpKind == tok::period && Tok.is(tok::kw_class)) { + if (getLangOpts().ObjC2 && OpKind == tok::period && + Tok.is(tok::kw_class)) { // Objective-C++: // After a '.' in a member access expression, treat the keyword // 'class' as if it were an identifier. @@ -1551,8 +1592,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, OpKind, SS, TemplateKWLoc, Name, CurParsedObjCImpl ? CurParsedObjCImpl->Dcl - : nullptr, - Tok.is(tok::l_paren)); + : nullptr); break; } case tok::plusplus: // postfix-expression: postfix-expression '++' @@ -1596,10 +1636,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, ParsedType &CastTy, SourceRange &CastRange) { - assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) || - OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) || - OpTok.is(tok::kw__Alignof) || OpTok.is(tok::kw_vec_step)) && - "Not a typeof/sizeof/alignof/vec_step expression!"); + assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof, + tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step) && + "Not a typeof/sizeof/alignof/vec_step expression!"); ExprResult Operand; @@ -1607,8 +1646,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, if (Tok.isNot(tok::l_paren)) { // If construct allows a form without parenthesis, user may forget to put // pathenthesis around type name. - if (OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) || - OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) { + if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, + tok::kw__Alignof)) { if (isTypeIdUnambiguously()) { DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); @@ -1682,9 +1721,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, /// [C++11] 'alignof' '(' type-id ')' /// \endverbatim ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { - assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) || - Tok.is(tok::kw_alignof) || Tok.is(tok::kw__Alignof) || - Tok.is(tok::kw_vec_step)) && + assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, + tok::kw__Alignof, tok::kw_vec_step) && "Not a sizeof/alignof/vec_step expression!"); Token OpTok = Tok; ConsumeToken(); @@ -1735,7 +1773,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { RParenLoc); } - if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) + if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::warn_cxx98_compat_alignof); EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, @@ -1750,8 +1788,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { CastRange); UnaryExprOrTypeTrait ExprKind = UETT_SizeOf; - if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof) || - OpTok.is(tok::kw__Alignof)) + if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof)) ExprKind = UETT_AlignOf; else if (OpTok.is(tok::kw_vec_step)) ExprKind = UETT_VecStep; @@ -1763,7 +1800,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { CastTy.getAsOpaquePtr(), CastRange); - if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) + if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo(); // If we get here, the operand to the sizeof/alignof was an expresion. @@ -2064,10 +2101,10 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Diagnose use of bridge casts in non-arc mode. bool BridgeCast = (getLangOpts().ObjC2 && - (Tok.is(tok::kw___bridge) || - Tok.is(tok::kw___bridge_transfer) || - Tok.is(tok::kw___bridge_retained) || - Tok.is(tok::kw___bridge_retain))); + Tok.isOneOf(tok::kw___bridge, + tok::kw___bridge_transfer, + tok::kw___bridge_retained, + tok::kw___bridge_retain)); if (BridgeCast && !getLangOpts().ObjCAutoRefCount) { if (!TryConsumeToken(tok::kw___bridge)) { StringRef BridgeCastName = Tok.getName(); @@ -2088,6 +2125,17 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) { Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope)); } else { + // Find the nearest non-record decl context. Variables declared in a + // statement expression behave as if they were declared in the enclosing + // function, block, or other code construct. + DeclContext *CodeDC = Actions.CurContext; + while (CodeDC->isRecord() || isa<EnumDecl>(CodeDC)) { + CodeDC = CodeDC->getParent(); + assert(CodeDC && !CodeDC->isFileContext() && + "statement expr not in code context"); + } + Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false); + Actions.ActOnStartStmtExpr(); StmtResult Stmt(ParseCompoundStatement(true)); @@ -2256,6 +2304,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, InMessageExpressionRAIIObject InMessage(*this, false); Result = ParseExpression(MaybeTypeCast); + if (!getLangOpts().CPlusPlus && MaybeTypeCast && Result.isUsable()) { + // Correct typos in non-C++ code earlier so that implicit-cast-like + // expressions are parsed correctly. + Result = Actions.CorrectDelayedTyposInExpr(Result); + } ExprType = SimpleExpr; if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) @@ -2354,7 +2407,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { // C11 6.5.1.1p3 "The controlling expression of a generic selection is // not evaluated." EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); - ControllingExpr = ParseAssignmentExpression(); + ControllingExpr = + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (ControllingExpr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); @@ -2400,7 +2454,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { // FIXME: These expressions should be parsed in a potentially potentially // evaluated context. - ExprResult ER(ParseAssignmentExpression()); + ExprResult ER( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); if (ER.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); @@ -2493,17 +2548,14 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS, /// [C++0x] assignment-expression /// [C++0x] braced-init-list /// \endverbatim -bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, +bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, SmallVectorImpl<SourceLocation> &CommaLocs, - void (Sema::*Completer)(Scope *S, - Expr *Data, - ArrayRef<Expr *> Args), - Expr *Data) { + std::function<void()> Completer) { bool SawError = false; while (1) { if (Tok.is(tok::code_completion)) { if (Completer) - (Actions.*Completer)(getCurScope(), Data, Exprs); + Completer(); else Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); cutOffParsing(); @@ -2588,9 +2640,6 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) { Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext); ParseDeclarator(DeclaratorInfo); - // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes. - DeclaratorInfo.takeAttributes(DS.getAttributes(), SourceLocation()); - MaybeParseGNUAttributes(DeclaratorInfo); // Inform sema that we are starting a block. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 67496ed..7fb4b5e 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -118,6 +118,7 @@ void Parser::CheckForLParenAfterColonColon() { // Eat the '('. ConsumeParen(); Token RParen; + RParen.setLocation(SourceLocation()); // Do we have a ')' ? NextTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : GetLookAheadToken(1); if (NextTok.is(tok::r_paren)) { @@ -194,6 +195,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (Tok.is(tok::annot_cxxscope)) { assert(!LastII && "want last identifier but have already annotated scope"); + assert(!MayBePseudoDestructor && "unexpected annot_cxxscope"); Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); @@ -208,6 +210,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, SS = TemplateId->SS; } + // Has to happen before any "return false"s in this function. + bool CheckForDestructor = false; + if (MayBePseudoDestructor && *MayBePseudoDestructor) { + CheckForDestructor = true; + *MayBePseudoDestructor = false; + } + if (LastII) *LastII = nullptr; @@ -244,14 +253,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return Actions.ActOnSuperScopeSpecifier(SuperLoc, ConsumeToken(), SS); } - bool CheckForDestructor = false; - if (MayBePseudoDestructor && *MayBePseudoDestructor) { - CheckForDestructor = true; - *MayBePseudoDestructor = false; - } - if (!HasScopeSpecifier && - (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))) { + Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) { DeclSpec DS(AttrFactory); SourceLocation DeclLoc = Tok.getLocation(); SourceLocation EndLoc = ParseDecltypeSpecifier(DS); @@ -484,7 +487,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // as the name in a nested-name-specifier. Token Identifier = Tok; SourceLocation IdLoc = ConsumeToken(); - assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) && + assert(Tok.isOneOf(tok::coloncolon, tok::colon) && "NextToken() not working properly!"); Token ColonColon = Tok; SourceLocation CCLoc = ConsumeToken(); @@ -659,7 +662,8 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); Token Replacement; - ExprResult Result = tryParseCXXIdExpression(SS, isAddressOfOperand, 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. @@ -888,7 +892,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, Parens.getCloseLocation(), Exprs); } - } else if (Tok.is(tok::l_brace) || Tok.is(tok::equal)) { + } else if (Tok.isOneOf(tok::l_brace, tok::equal)) { // Each lambda init-capture forms its own full expression, which clears // Actions.MaybeODRUseExprs. So create an expression evaluation context // to save the necessary state, and restore it later. @@ -1090,6 +1094,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // compatible with GCC. MaybeParseGNUAttributes(Attr, &DeclEndLoc); + // MSVC-style attributes must be parsed before the mutable specifier to be + // compatible with MSVC. + MaybeParseMicrosoftDeclSpecs(Attr, &DeclEndLoc); + // Parse 'mutable'[opt]. SourceLocation MutableLoc; if (TryConsumeToken(tok::kw_mutable, MutableLoc)) @@ -1151,8 +1159,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); - } else if (Tok.is(tok::kw_mutable) || Tok.is(tok::arrow) || - Tok.is(tok::kw___attribute) || + } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute) || (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { // It's common to forget that one needs '()' before 'mutable', an attribute // specifier, or the result type. Deal with this. @@ -1485,9 +1492,8 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, ParseDecltypeSpecifier(DS); if (DS.getTypeSpecType() == TST_error) return ExprError(); - return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, - OpKind, TildeLoc, DS, - Tok.is(tok::l_paren)); + return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind, + TildeLoc, DS); } if (!Tok.is(tok::identifier)) { @@ -1510,11 +1516,9 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, /*AssumeTemplateName=*/true)) return ExprError(); - return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, - OpLoc, OpKind, - SS, FirstTypeName, CCLoc, - TildeLoc, SecondTypeName, - Tok.is(tok::l_paren)); + return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind, + SS, FirstTypeName, CCLoc, TildeLoc, + SecondTypeName); } /// ParseCXXBoolLiteral - This handles the C++ Boolean literals. @@ -1602,7 +1606,11 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { CommaLocsTy CommaLocs; if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(Exprs, CommaLocs)) { + if (ParseExpressionList(Exprs, CommaLocs, [&] { + Actions.CodeCompleteConstructor(getCurScope(), + TypeRep.get()->getCanonicalTypeInternal(), + DS.getLocEnd(), Exprs); + })) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2509,14 +2517,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, } // If the user wrote ~T::T, correct it to T::~T. + DeclaratorScopeObj DeclScopeObj(*this, SS); if (!TemplateSpecified && NextToken().is(tok::coloncolon)) { + // Don't let ParseOptionalCXXScopeSpecifier() "correct" + // `int A; struct { ~A::A(); };` to `int A; struct { ~A:A(); };`, + // it will confuse this recovery logic. + ColonProtectionRAIIObject ColonRAII(*this, false); + 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)) { + if (SS.isNotEmpty()) + ObjectType = ParsedType(); + if (Tok.isNot(tok::identifier) || NextToken().is(tok::coloncolon) || + !SS.isSet()) { Diag(TildeLoc, diag::err_destructor_tilde_scope); return true; } @@ -2525,6 +2542,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, Diag(TildeLoc, diag::err_destructor_tilde_scope) << FixItHint::CreateRemoval(TildeLoc) << FixItHint::CreateInsertion(Tok.getLocation(), "~"); + + // Temporarily enter the scope for the rest of this function. + if (Actions.ShouldEnterDeclaratorScope(getCurScope(), SS)) + DeclScopeObj.EnterDeclaratorScope(); } // Parse the class-name (or template-name in a simple-template-id). @@ -2668,7 +2689,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { ConstructorLParen = T.getOpenLocation(); if (Tok.isNot(tok::r_paren)) { CommaLocsTy CommaLocs; - if (ParseExpressionList(ConstructorArgs, CommaLocs)) { + if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] { + ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), + DeclaratorInfo).get(); + Actions.CodeCompleteConstructor(getCurScope(), + TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getLocEnd(), + ConstructorArgs); + })) { SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); return ExprError(); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp index 7fe9862..42287d6 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp @@ -148,7 +148,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { Diag(NameLoc, diag::ext_gnu_old_style_field_designator) << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc), - NewSyntax.str()); + NewSyntax); Designation D; D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp index a597a16..e4f7911 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" +#include "clang/AST/ASTContext.h" #include "clang/Basic/CharInfo.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" @@ -240,7 +241,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, SmallVector<Decl *, 8> ProtocolRefs; SmallVector<SourceLocation, 8> ProtocolLocs; if (Tok.is(tok::less) && - ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, + ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true, LAngleLoc, EndProtoLoc)) return nullptr; @@ -286,7 +287,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, SmallVector<SourceLocation, 8> ProtocolLocs; SourceLocation LAngleLoc, EndProtoLoc; if (Tok.is(tok::less) && - ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, + ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true, LAngleLoc, EndProtoLoc)) return nullptr; @@ -307,6 +308,37 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, return ClsType; } +/// Add an attribute for a context-sensitive type nullability to the given +/// declarator. +static void addContextSensitiveTypeNullability(Parser &P, + Declarator &D, + NullabilityKind nullability, + SourceLocation nullabilityLoc, + bool &addedToDeclSpec) { + // Create the attribute. + auto getNullabilityAttr = [&]() -> AttributeList * { + return D.getAttributePool().create( + P.getNullabilityKeyword(nullability), + SourceRange(nullabilityLoc), + nullptr, SourceLocation(), + nullptr, 0, + AttributeList::AS_ContextSensitiveKeyword); + }; + + if (D.getNumTypeObjects() > 0) { + // Add the attribute to the declarator chunk nearest the declarator. + auto nullabilityAttr = getNullabilityAttr(); + DeclaratorChunk &chunk = D.getTypeObject(0); + nullabilityAttr->setNext(chunk.getAttrListRef()); + chunk.getAttrListRef() = nullabilityAttr; + } else if (!addedToDeclSpec) { + // Otherwise, just put it on the declaration specifiers (if one + // isn't there already). + D.getMutableDeclSpec().addAttributes(getNullabilityAttr()); + addedToDeclSpec = true; + } +} + /// objc-interface-decl-list: /// empty /// objc-interface-decl-list objc-property-decl [OBJC2] @@ -330,7 +362,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, while (1) { // If this is a method prototype, parse it. - if (Tok.is(tok::minus) || Tok.is(tok::plus)) { + if (Tok.isOneOf(tok::minus, tok::plus)) { if (Decl *methodPrototype = ParseObjCMethodPrototype(MethodImplKind, false)) allMethods.push_back(methodPrototype); @@ -445,6 +477,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, ParseObjCPropertyAttribute(OCDS); } + bool addedToDeclSpec = false; auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) { if (FD.D.getIdentifier() == nullptr) { Diag(AtLoc, diag::err_objc_property_requires_field_name) @@ -457,6 +490,13 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, return; } + // Map a nullability property attribute to a context-sensitive keyword + // attribute. + if (OCDS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) + addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(), + OCDS.getNullabilityLoc(), + addedToDeclSpec); + // Install the property declarator into interfaceDecl. IdentifierInfo *SelName = OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); @@ -510,6 +550,24 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables); } +/// Diagnose redundant or conflicting nullability information. +static void diagnoseRedundantPropertyNullability(Parser &P, + ObjCDeclSpec &DS, + NullabilityKind nullability, + SourceLocation nullabilityLoc){ + if (DS.getNullability() == nullability) { + P.Diag(nullabilityLoc, diag::warn_nullability_duplicate) + << static_cast<unsigned>(nullability) << true + << SourceRange(DS.getNullabilityLoc()); + return; + } + + P.Diag(nullabilityLoc, diag::err_nullability_conflicting) + << static_cast<unsigned>(nullability) << true + << static_cast<unsigned>(DS.getNullability()) << true + << SourceRange(DS.getNullabilityLoc()); +} + /// Parse property attribute declarations. /// /// property-attr-decl: '(' property-attrlist ')' @@ -529,6 +587,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, /// strong /// weak /// unsafe_unretained +/// nonnull +/// nullable +/// null_unspecified +/// null_resettable /// void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { assert(Tok.getKind() == tok::l_paren); @@ -614,6 +676,37 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter); DS.setGetterName(SelIdent); } + } else if (II->isStr("nonnull")) { + if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) + diagnoseRedundantPropertyNullability(*this, DS, + NullabilityKind::NonNull, + Tok.getLocation()); + DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); + DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull); + } else if (II->isStr("nullable")) { + if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) + diagnoseRedundantPropertyNullability(*this, DS, + NullabilityKind::Nullable, + Tok.getLocation()); + DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); + DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable); + } else if (II->isStr("null_unspecified")) { + if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) + diagnoseRedundantPropertyNullability(*this, DS, + NullabilityKind::Unspecified, + Tok.getLocation()); + DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); + DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified); + } else if (II->isStr("null_resettable")) { + if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) + diagnoseRedundantPropertyNullability(*this, DS, + NullabilityKind::Unspecified, + Tok.getLocation()); + DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); + DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified); + + // Also set the null_resettable bit. + DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_null_resettable); } else { Diag(AttrName, diag::err_objc_expected_property_attr) << II; SkipUntil(tok::r_paren, StopAtSemi); @@ -641,7 +734,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { /// Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { - assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); + assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-"); tok::TokenKind methodType = Tok.getKind(); SourceLocation mLoc = ConsumeToken(); @@ -779,6 +872,17 @@ bool Parser::isTokIdentifier_in() const { /// objc-type-qualifier /// objc-type-qualifiers objc-type-qualifier /// +/// objc-type-qualifier: +/// 'in' +/// 'out' +/// 'inout' +/// 'oneway' +/// 'bycopy' +/// 'byref' +/// 'nonnull' +/// 'nullable' +/// 'null_unspecified' +/// void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, Declarator::TheContext Context) { assert(Context == Declarator::ObjCParameterContext || @@ -796,10 +900,13 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, const IdentifierInfo *II = Tok.getIdentifierInfo(); for (unsigned i = 0; i != objc_NumQuals; ++i) { - if (II != ObjCTypeQuals[i]) + if (II != ObjCTypeQuals[i] || + NextToken().is(tok::less) || + NextToken().is(tok::coloncolon)) continue; ObjCDeclSpec::ObjCDeclQualifier Qual; + NullabilityKind Nullability; switch (i) { default: llvm_unreachable("Unknown decl qualifier"); case objc_in: Qual = ObjCDeclSpec::DQ_In; break; @@ -808,8 +915,28 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break; case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break; case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break; + + case objc_nonnull: + Qual = ObjCDeclSpec::DQ_CSNullability; + Nullability = NullabilityKind::NonNull; + break; + + case objc_nullable: + Qual = ObjCDeclSpec::DQ_CSNullability; + Nullability = NullabilityKind::Nullable; + break; + + case objc_null_unspecified: + Qual = ObjCDeclSpec::DQ_CSNullability; + Nullability = NullabilityKind::Unspecified; + break; } + + // FIXME: Diagnose redundant specifiers. DS.setObjCDeclQualifier(Qual); + if (Qual == ObjCDeclSpec::DQ_CSNullability) + DS.setNullability(Tok.getLocation(), Nullability); + ConsumeToken(); II = nullptr; break; @@ -878,17 +1005,28 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, ParseObjCTypeQualifierList(DS, context); ParsedType Ty; - if (isTypeSpecifierQualifier()) { + if (isTypeSpecifierQualifier() || isObjCInstancetype()) { // Parse an abstract declarator. DeclSpec declSpec(AttrFactory); declSpec.setObjCQualifiers(&DS); - ParseSpecifierQualifierList(declSpec); + DeclSpecContext dsContext = DSC_normal; + if (context == Declarator::ObjCResultContext) + dsContext = DSC_objc_method_result; + ParseSpecifierQualifierList(declSpec, AS_none, dsContext); declSpec.SetRangeEnd(Tok.getLocation()); Declarator declarator(declSpec, context); ParseDeclarator(declarator); // If that's not invalid, extract a type. if (!declarator.isInvalidType()) { + // Map a nullability specifier to a context-sensitive keyword attribute. + bool addedToDeclSpec = false; + if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) + addContextSensitiveTypeNullability(*this, declarator, + DS.getNullability(), + DS.getNullabilityLoc(), + addedToDeclSpec); + TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator); if (!type.isInvalid()) Ty = type.get(); @@ -898,15 +1036,6 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, if (context == Declarator::ObjCParameterContext) takeDeclAttributes(*paramAttrs, declarator); } - } else if (context == Declarator::ObjCResultContext && - Tok.is(tok::identifier)) { - if (!Ident_instancetype) - Ident_instancetype = PP.getIdentifierInfo("instancetype"); - - if (Tok.getIdentifierInfo() == Ident_instancetype) { - Ty = Actions.ActOnObjCInstanceType(Tok.getLocation()); - ConsumeToken(); - } } if (Tok.is(tok::r_paren)) @@ -1151,7 +1280,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, bool Parser:: ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, SmallVectorImpl<SourceLocation> &ProtocolLocs, - bool WarnOnDeclarations, + bool WarnOnDeclarations, bool ForObjCContainer, SourceLocation &LAngleLoc, SourceLocation &EndLoc) { assert(Tok.is(tok::less) && "expected <"); @@ -1186,7 +1315,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, return true; // Convert the list of protocols identifiers into a list of protocol decls. - Actions.FindProtocolDeclaration(WarnOnDeclarations, + Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer, &ProtocolIdents[0], ProtocolIdents.size(), Protocols); return false; @@ -1201,6 +1330,7 @@ bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) { SmallVector<Decl *, 8> ProtocolDecl; SmallVector<SourceLocation, 8> ProtocolLocs; bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, + false, LAngleLoc, EndProtoLoc); DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), ProtocolLocs.data(), LAngleLoc); @@ -1308,6 +1438,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) { Actions.ActOnObjCContainerStartDefinition(interfaceDecl); // Install the declarator into the interface decl. + FD.D.setObjCIvar(true); Decl *Field = Actions.ActOnIvar( getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, FD.BitfieldSize, visibility); @@ -1416,7 +1547,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, SmallVector<Decl *, 8> ProtocolRefs; SmallVector<SourceLocation, 8> ProtocolLocs; if (Tok.is(tok::less) && - ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, + ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true, LAngleLoc, EndProtoLoc)) return DeclGroupPtrTy(); @@ -2169,8 +2300,8 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { InMessageExpressionRAIIObject InMessage(*this, true); - if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || - Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) + if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename, + tok::annot_cxxscope)) TryAnnotateTypeOrScopeToken(); if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) { @@ -2264,7 +2395,7 @@ bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) { const Token &AfterNext = GetLookAheadToken(2); - if (AfterNext.is(tok::colon) || AfterNext.is(tok::r_square)) { + if (AfterNext.isOneOf(tok::colon, tok::r_square)) { if (Tok.is(tok::identifier)) TryAnnotateTypeOrScopeToken(); @@ -2890,9 +3021,8 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { // Consume the previously pushed token. ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); - assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || - Tok.is(tok::colon)) && - "Inline objective-c method not starting with '{' or 'try' or ':'"); + assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) && + "Inline objective-c method not starting with '{' or 'try' or ':'"); // Enter a scope for the method or c-function body. ParseScope BodyScope(this, parseMethod diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp index 764619a..a3c3c5d 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp @@ -94,6 +94,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: + case OMPD_taskgroup: case OMPD_flush: case OMPD_for: case OMPD_for_simd: @@ -128,7 +129,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | -/// 'for simd' | 'parallel for simd' | 'target' | 'teams' {clause} +/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup' +/// {clause} /// annot_pragma_openmp_end /// StmtResult @@ -198,7 +200,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_ordered: case OMPD_atomic: case OMPD_target: - case OMPD_teams: { + case OMPD_teams: + case OMPD_taskgroup: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { @@ -223,6 +226,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { ParseScope OMPDirectiveScope(this, ScopeFlags); Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); + Actions.StartOpenMPClauses(); while (Tok.isNot(tok::annot_pragma_openmp_end)) { OpenMPClauseKind CKind = Tok.isAnnotation() @@ -242,6 +246,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { if (Tok.is(tok::comma)) ConsumeToken(); } + Actions.EndOpenMPClauses(); // End location of the directive. EndLoc = Tok.getLocation(); // Consume final annot_pragma_openmp_end. @@ -257,13 +262,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { // Parse statement AssociatedStmt = ParseStatement(); Actions.ActOnFinishOfCompoundStmt(); - if (!AssociatedStmt.isUsable()) { - Actions.ActOnCapturedRegionError(); - CreateDirective = false; - } else { - AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get()); - CreateDirective = AssociatedStmt.isUsable(); - } + AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); + CreateDirective = AssociatedStmt.isUsable(); } if (CreateDirective) Directive = Actions.ActOnOpenMPExecutableDirective( diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp index 473be54..892d3c6 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp @@ -198,9 +198,12 @@ void Parser::initializePragmaHandlers() { OpenMPHandler.reset(new PragmaNoOpenMPHandler()); PP.AddPragmaHandler(OpenMPHandler.get()); - if (getLangOpts().MicrosoftExt) { + if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { MSCommentHandler.reset(new PragmaCommentHandler(Actions)); PP.AddPragmaHandler(MSCommentHandler.get()); + } + + if (getLangOpts().MicrosoftExt) { MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions)); PP.AddPragmaHandler(MSDetectMismatchHandler.get()); MSPointersToMembers.reset(new PragmaMSPointersToMembers()); @@ -261,9 +264,12 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler(OpenMPHandler.get()); OpenMPHandler.reset(); - if (getLangOpts().MicrosoftExt) { + if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { PP.RemovePragmaHandler(MSCommentHandler.get()); MSCommentHandler.reset(); + } + + if (getLangOpts().MicrosoftExt) { PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); MSDetectMismatchHandler.reset(); PP.RemovePragmaHandler(MSPointersToMembers.get()); @@ -793,8 +799,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { "PragmaLoopHintInfo::Toks must contain at least one token."); // If no option is specified the argument is assumed to be a constant expr. + bool OptionUnroll = false; bool StateOption = false; - if (OptionInfo) { // Pragma unroll does not specify an option. + if (OptionInfo) { // Pragma Unroll does not specify an option. + OptionUnroll = OptionInfo->isStr("unroll"); StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) .Case("vectorize", true) .Case("interleave", true) @@ -806,19 +814,20 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { if (Toks[0].is(tok::eof)) { ConsumeToken(); // The annotation token. Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) - << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll; + << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll; 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"))) { + if (!StateInfo || + ((OptionUnroll ? !StateInfo->isStr("full") + : !StateInfo->isStr("enable") && + !StateInfo->isStr("assume_safety")) && + !StateInfo->isStr("disable"))) { Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) << /*FullKeyword=*/OptionUnroll; return false; @@ -900,6 +909,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, << "visibility"; return; } + SourceLocation EndLoc = Tok.getLocation(); PP.LexUnexpandedToken(Tok); if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) @@ -911,6 +921,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, Toks[0].startToken(); Toks[0].setKind(tok::annot_pragma_vis); Toks[0].setLocation(VisLoc); + Toks[0].setAnnotationEndLoc(EndLoc); Toks[0].setAnnotationValue( const_cast<void*>(static_cast<const void*>(VisType))); PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, @@ -1030,6 +1041,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Toks[0].startToken(); Toks[0].setKind(tok::annot_pragma_pack); Toks[0].setLocation(PackLoc); + Toks[0].setAnnotationEndLoc(RParenLoc); Toks[0].setAnnotationValue(static_cast<void*>(Info)); PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); @@ -1048,6 +1060,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); return; } + SourceLocation EndLoc = Tok.getLocation(); const IdentifierInfo *II = Tok.getIdentifierInfo(); if (II->isStr("on")) { Kind = Sema::PMSST_ON; @@ -1073,6 +1086,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, Toks[0].startToken(); Toks[0].setKind(tok::annot_pragma_msstruct); Toks[0].setLocation(MSStructTok.getLocation()); + Toks[0].setAnnotationEndLoc(EndLoc); Toks[0].setAnnotationValue(reinterpret_cast<void*>( static_cast<uintptr_t>(Kind))); PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, @@ -1128,6 +1142,7 @@ static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, return; } + SourceLocation EndLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) @@ -1142,6 +1157,7 @@ static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, Toks[0].startToken(); Toks[0].setKind(tok::annot_pragma_align); Toks[0].setLocation(FirstTok.getLocation()); + Toks[0].setAnnotationEndLoc(EndLoc); Toks[0].setAnnotationValue(reinterpret_cast<void*>( static_cast<uintptr_t>(Kind))); PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, @@ -1285,6 +1301,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP, pragmaUnusedTok.startToken(); pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); pragmaUnusedTok.setLocation(WeakLoc); + pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation()); Toks[1] = WeakName; Toks[2] = AliasName; PP.EnterTokenStream(Toks, 3, @@ -1297,6 +1314,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP, pragmaUnusedTok.startToken(); pragmaUnusedTok.setKind(tok::annot_pragma_weak); pragmaUnusedTok.setLocation(WeakLoc); + pragmaUnusedTok.setAnnotationEndLoc(WeakLoc); Toks[1] = WeakName; PP.EnterTokenStream(Toks, 2, /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); @@ -1342,6 +1360,7 @@ void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, pragmaRedefTok.startToken(); pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); pragmaRedefTok.setLocation(RedefLoc); + pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation()); Toks[1] = RedefName; Toks[2] = AliasName; PP.EnterTokenStream(Toks, 3, @@ -1364,6 +1383,7 @@ PragmaFPContractHandler::HandlePragma(Preprocessor &PP, Toks[0].startToken(); Toks[0].setKind(tok::annot_pragma_fp_contract); Toks[0].setLocation(Tok.getLocation()); + Toks[0].setAnnotationEndLoc(Tok.getLocation()); Toks[0].setAnnotationValue(reinterpret_cast<void*>( static_cast<uintptr_t>(OOS))); PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, @@ -1423,6 +1443,7 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, Toks[0].setKind(tok::annot_pragma_opencl_extension); Toks[0].setLocation(NameLoc); Toks[0].setAnnotationValue(data.getOpaqueValue()); + Toks[0].setAnnotationEndLoc(StateLoc); PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); @@ -1471,7 +1492,7 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, Token *Toks = new Token[Pragma.size()]; std::copy(Pragma.begin(), Pragma.end(), Toks); PP.EnterTokenStream(Toks, Pragma.size(), - /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); + /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true); } /// \brief Handle '#pragma pointers_to_members' @@ -1554,6 +1575,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, return; } + SourceLocation EndLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) @@ -1565,6 +1587,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, AnnotTok.startToken(); AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); AnnotTok.setLocation(PointersToMembersLoc); + AnnotTok.setAnnotationEndLoc(EndLoc); AnnotTok.setAnnotationValue( reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); PP.EnterToken(AnnotTok); @@ -1644,6 +1667,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp"; return; } + SourceLocation EndLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) @@ -1656,6 +1680,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, AnnotTok.startToken(); AnnotTok.setKind(tok::annot_pragma_ms_vtordisp); AnnotTok.setLocation(VtorDispLoc); + AnnotTok.setAnnotationEndLoc(EndLoc); AnnotTok.setAnnotationValue(reinterpret_cast<void *>( static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF)))); PP.EnterToken(AnnotTok); @@ -1672,10 +1697,13 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP, AnnotTok.startToken(); AnnotTok.setKind(tok::annot_pragma_ms_pragma); AnnotTok.setLocation(Tok.getLocation()); + AnnotTok.setAnnotationEndLoc(Tok.getLocation()); SmallVector<Token, 8> TokenVector; // Suck up all of the tokens before the eod. - for (; Tok.isNot(tok::eod); PP.Lex(Tok)) + for (; Tok.isNot(tok::eod); PP.Lex(Tok)) { TokenVector.push_back(Tok); + AnnotTok.setAnnotationEndLoc(Tok.getLocation()); + } // Add a sentinal EoF token to the end of the list. TokenVector.push_back(EoF); // We must allocate this array with new because EnterTokenStream is going to @@ -1786,6 +1814,14 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP, return; } + // On PS4, issue a warning about any pragma comments other than + // #pragma comment lib. + if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) + << II->getName(); + return; + } + // Read the optional string if present. PP.Lex(Tok); std::string ArgumentString; @@ -1920,6 +1956,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, /// loop-hint-keyword: /// 'enable' /// 'disable' +/// 'assume_safety' /// /// unroll-hint-keyword: /// 'full' @@ -1994,6 +2031,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, LoopHintTok.startToken(); LoopHintTok.setKind(tok::annot_pragma_loop_hint); LoopHintTok.setLocation(PragmaName.getLocation()); + LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation()); LoopHintTok.setAnnotationValue(static_cast<void *>(Info)); TokenList.push_back(LoopHintTok); } @@ -2076,6 +2114,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, TokenArray[0].startToken(); TokenArray[0].setKind(tok::annot_pragma_loop_hint); TokenArray[0].setLocation(PragmaName.getLocation()); + TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation()); TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index 2a5f840..b658cef 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -119,15 +119,12 @@ namespace { class StatementFilterCCC : public CorrectionCandidateCallback { public: StatementFilterCCC(Token nextTok) : NextToken(nextTok) { - WantTypeSpecifiers = nextTok.is(tok::l_paren) || nextTok.is(tok::less) || - nextTok.is(tok::identifier) || nextTok.is(tok::star) || - nextTok.is(tok::amp) || nextTok.is(tok::l_square); - WantExpressionKeywords = nextTok.is(tok::l_paren) || - nextTok.is(tok::identifier) || - nextTok.is(tok::arrow) || nextTok.is(tok::period); - WantRemainingKeywords = nextTok.is(tok::l_paren) || nextTok.is(tok::semi) || - nextTok.is(tok::identifier) || - nextTok.is(tok::l_brace); + WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square, + tok::identifier, tok::star, tok::amp); + WantExpressionKeywords = + nextTok.isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period); + WantRemainingKeywords = + nextTok.isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace); WantCXXNamedCasts = false; } @@ -408,12 +405,6 @@ StmtResult Parser::ParseExprStatement() { return Actions.ActOnExprStmt(Expr); } -StmtResult Parser::ParseSEHTryBlock() { - assert(Tok.is(tok::kw___try) && "Expected '__try'"); - SourceLocation Loc = ConsumeToken(); - return ParseSEHTryBlockCommon(Loc); -} - /// ParseSEHTryBlockCommon /// /// seh-try-block: @@ -423,8 +414,11 @@ StmtResult Parser::ParseSEHTryBlock() { /// seh-except-block /// seh-finally-block /// -StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { - if(Tok.isNot(tok::l_brace)) +StmtResult Parser::ParseSEHTryBlock() { + assert(Tok.is(tok::kw___try) && "Expected '__try'"); + SourceLocation TryLoc = ConsumeToken(); + + if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, @@ -441,7 +435,7 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { SourceLocation Loc = ConsumeToken(); Handler = ParseSEHFinallyBlock(Loc); } else { - return StmtError(Diag(Tok,diag::err_seh_expected_handler)); + return StmtError(Diag(Tok, diag::err_seh_expected_handler)); } if(Handler.isInvalid()) @@ -466,14 +460,21 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { if (ExpectAndConsume(tok::l_paren)) return StmtError(); - ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope); + ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope | + Scope::SEHExceptScope); if (getLangOpts().Borland) { Ident__exception_info->setIsPoisoned(false); Ident___exception_info->setIsPoisoned(false); Ident_GetExceptionInfo->setIsPoisoned(false); } - ExprResult FilterExpr(ParseExpression()); + + ExprResult FilterExpr; + { + ParseScopeFlags FilterScope(this, getCurScope()->getFlags() | + Scope::SEHFilterScope); + FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression()); + } if (getLangOpts().Borland) { Ident__exception_info->setIsPoisoned(true); @@ -487,6 +488,9 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { if (ExpectAndConsume(tok::r_paren)) return StmtError(); + if (Tok.isNot(tok::l_brace)) + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); + StmtResult Block(ParseCompoundStatement()); if(Block.isInvalid()) @@ -500,16 +504,24 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { /// seh-finally-block: /// '__finally' compound-statement /// -StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) { +StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) { PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false), raii2(Ident___abnormal_termination, false), raii3(Ident_AbnormalTermination, false); + if (Tok.isNot(tok::l_brace)) + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); + + ParseScope FinallyScope(this, 0); + Actions.ActOnStartSEHFinallyBlock(); + StmtResult Block(ParseCompoundStatement()); - if(Block.isInvalid()) + if(Block.isInvalid()) { + Actions.ActOnAbortSEHFinallyBlock(); return Block; + } - return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.get()); + return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc, Block.get()); } /// Handle __leave @@ -1253,7 +1265,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { // We have incremented the mangling number for the SwitchScope and the // InnerScope, which is one too many. if (C99orCXX) - getCurScope()->decrementMSLocalManglingNumber(); + getCurScope()->decrementMSManglingNumber(); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1412,7 +1424,7 @@ bool Parser::isForRangeIdentifier() { if (Next.is(tok::colon)) return true; - if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) { + if (Next.isOneOf(tok::l_square, tok::kw_alignas)) { TentativeParsingAction PA(*this); ConsumeToken(); SkipCXX11Attributes(); @@ -1674,6 +1686,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { FirstPart.get(), Collection.get(), T.getCloseLocation()); + } else { + // In OpenMP loop region loop control variable must be captured and be + // private. Perform analysis of first part (if any). + if (getLangOpts().OpenMP && FirstPart.isUsable()) { + Actions.ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get()); + } } // C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if @@ -1695,7 +1713,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // It will only be incremented if the body contains other things that would // normally increment the mangling number (like a compound statement). if (C99orCXXorObjC) - getCurScope()->decrementMSLocalManglingNumber(); + getCurScope()->decrementMSManglingNumber(); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp index 7bf4da6..8cdae6a 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp @@ -512,8 +512,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { llvm::SourceMgr TempSrcMgr; llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); - MOFI->InitMCObjectFileInfo(TT, llvm::Reloc::Default, llvm::CodeModel::Default, - Ctx); + MOFI->InitMCObjectFileInfo(TheTriple, llvm::Reloc::Default, + llvm::CodeModel::Default, Ctx); std::unique_ptr<llvm::MemoryBuffer> Buffer = llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); @@ -530,7 +530,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions)); std::unique_ptr<llvm::MCInstPrinter> IP( - TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI)); + TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI)); // Change to the Intel dialect. Parser->setAssemblerDialect(1); @@ -615,6 +615,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { msAsm = true; return ParseMicrosoftAsmStatement(AsmLoc); } + DeclSpec DS(AttrFactory); SourceLocation Loc = Tok.getLocation(); ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed); @@ -639,6 +640,15 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { T.consumeOpen(); ExprResult AsmString(ParseAsmStringLiteral()); + + // Check if GNU-style InlineAsm is disabled. + // Error on anything other than empty string. + if (!(getLangOpts().GNUAsm || AsmString.isInvalid())) { + const auto *SL = cast<StringLiteral>(AsmString.get()); + if (!SL->getString().trim().empty()) + Diag(Loc, diag::err_gnu_inline_asm_disabled); + } + if (AsmString.isInvalid()) { // Consume up to and including the closing paren. T.skipToEnd(); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 53de72c..a811678 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" @@ -61,7 +62,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, SourceLocation &DeclEnd, AccessSpecifier AS, AttributeList *AccessAttrs) { - assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) && + assert(Tok.isOneOf(tok::kw_export, tok::kw_template) && "Token does not start a template declaration."); // Enter template-parameter scope. @@ -134,7 +135,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, } else { LastParamListWasEmpty = true; } - } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template)); + } while (Tok.isOneOf(tok::kw_export, tok::kw_template)); // Parse the actual template declaration. return ParseSingleDeclarationAfterTemplate(Context, @@ -366,7 +367,7 @@ Parser::ParseTemplateParameterList(unsigned Depth, // Did we find a comma or the end of the template parameter list? if (Tok.is(tok::comma)) { ConsumeToken(); - } else if (Tok.is(tok::greater) || Tok.is(tok::greatergreater)) { + } else if (Tok.isOneOf(tok::greater, tok::greatergreater)) { // Don't consume this... that's done by template parser. break; } else { @@ -483,7 +484,7 @@ Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) { /// 'typename' ...[opt][C++0x] identifier[opt] /// 'typename' identifier[opt] '=' type-id Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { - assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) && + assert(Tok.isOneOf(tok::kw_class, tok::kw_typename) && "A type-parameter starts with 'class' or 'typename'"); // Consume the 'class' or 'typename' keyword. @@ -505,8 +506,8 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); - } else if (Tok.is(tok::equal) || Tok.is(tok::comma) || - Tok.is(tok::greater) || Tok.is(tok::greatergreater)) { + } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater, + tok::greatergreater)) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. } else { @@ -566,7 +567,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { // or greater appear immediately or after 'struct'. In the latter case, // replace the keyword with 'class'. if (!TryConsumeToken(tok::kw_class)) { - bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct); + bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct); const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok; if (Tok.is(tok::kw_typename)) { Diag(Tok.getLocation(), @@ -576,9 +577,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { << (!getLangOpts().CPlusPlus1z ? FixItHint::CreateReplacement(Tok.getLocation(), "class") : FixItHint()); - } else if (Next.is(tok::identifier) || Next.is(tok::comma) || - Next.is(tok::greater) || Next.is(tok::greatergreater) || - Next.is(tok::ellipsis)) { + } else if (Next.isOneOf(tok::identifier, tok::comma, tok::greater, + tok::greatergreater, tok::ellipsis)) { Diag(Tok.getLocation(), diag::err_class_on_template_template_param) << (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class") : FixItHint::CreateInsertion(Tok.getLocation(), "class ")); @@ -603,8 +603,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); - } else if (Tok.is(tok::equal) || Tok.is(tok::comma) || - Tok.is(tok::greater) || Tok.is(tok::greatergreater)) { + } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater, + tok::greatergreater)) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. } else { @@ -793,16 +793,15 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, Token Next = NextToken(); if ((RemainingToken == tok::greater || RemainingToken == tok::greatergreater) && - (Next.is(tok::greater) || Next.is(tok::greatergreater) || - Next.is(tok::greatergreatergreater) || Next.is(tok::equal) || - Next.is(tok::greaterequal) || Next.is(tok::greatergreaterequal) || - Next.is(tok::equalequal)) && + Next.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater, tok::equal, tok::greaterequal, + tok::greatergreaterequal, tok::equalequal) && areTokensAdjacent(Tok, Next)) Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; if (getLangOpts().CPlusPlus11 && - (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater))) + Tok.isOneOf(tok::greatergreater, tok::greatergreatergreater)) DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) DiagId = diag::err_right_angle_bracket_equal_needs_space; @@ -1054,8 +1053,7 @@ void Parser::AnnotateTemplateIdTokenAsType() { /// \brief Determine whether the given token can end a template argument. static bool isEndOfTemplateArgument(Token Tok) { - return Tok.is(tok::comma) || Tok.is(tok::greater) || - Tok.is(tok::greatergreater); + return Tok.isOneOf(tok::comma, tok::greater, tok::greatergreater); } /// \brief Parse a C++ template template argument. @@ -1216,7 +1214,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { ConsumeToken(); // If we have a '>' or a ',' then this is a template argument list. - return Tok.is(tok::greater) || Tok.is(tok::comma); + return Tok.isOneOf(tok::greater, tok::comma); } /// ParseTemplateArgumentList - Parse a C++ template-argument-list @@ -1301,7 +1299,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); // To restore the context after late parsing. - Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext); + Sema::ContextRAII GlobalSavedContext( + Actions, Actions.Context.getTranslationUnitDecl()); SmallVector<ParseScope*, 4> TemplateParamScopeStack; @@ -1337,8 +1336,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { // Consume the previously pushed token. ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) - && "Inline method not starting with '{', ':' or 'try'"); + assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try) && + "Inline method not starting with '{', ':' or 'try'"); // Parse the method body. Function body parsing code is similar enough // to be re-used for method bodies as well. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index abf16fa..d63cf24 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -179,8 +179,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { ConsumeToken(); // Skip attributes. - while (Tok.is(tok::l_square) || Tok.is(tok::kw___attribute) || - Tok.is(tok::kw___declspec) || Tok.is(tok::kw_alignas)) { + while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec, + tok::kw_alignas)) { if (Tok.is(tok::l_square)) { ConsumeBracket(); if (!SkipUntil(tok::r_square)) @@ -195,8 +195,8 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { } } - if ((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || - Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id)) && + if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype, + tok::annot_template_id) && TryAnnotateCXXScopeToken()) return TPResult::Error; if (Tok.is(tok::annot_cxxscope)) @@ -289,7 +289,7 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() { return TPR; // [GNU] simple-asm-expr[opt] attributes[opt] - if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) + if (Tok.isOneOf(tok::kw_asm, tok::kw___attribute)) return TPResult::True; // initializer[opt] @@ -370,8 +370,7 @@ bool Parser::isCXXConditionDeclaration() { if (TPR == TPResult::Ambiguous) { // '=' // [GNU] simple-asm-expr[opt] attributes[opt] - if (Tok.is(tok::equal) || - Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) + if (Tok.isOneOf(tok::equal, tok::kw_asm, tok::kw___attribute)) TPR = TPResult::True; else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) TPR = TPResult::True; @@ -448,7 +447,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { // the abstract declarator we encounter a '>', '>>' (in C++0x), or // ',', this is a type-id. Otherwise, it's an expression. } else if (Context == TypeIdAsTemplateArgument && - (Tok.is(tok::greater) || Tok.is(tok::comma) || + (Tok.isOneOf(tok::greater, tok::comma) || (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) { TPR = TPResult::True; isAmbiguous = true; @@ -624,18 +623,17 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate, Parser::TPResult Parser::TryParsePtrOperatorSeq() { while (true) { - if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) + if (Tok.isOneOf(tok::coloncolon, tok::identifier)) if (TryAnnotateCXXScopeToken(true)) return TPResult::Error; - if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || - Tok.is(tok::ampamp) || + if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) || (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { // ptr-operator ConsumeToken(); - while (Tok.is(tok::kw_const) || - Tok.is(tok::kw_volatile) || - Tok.is(tok::kw_restrict)) + while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict, + tok::kw___nonnull, tok::kw___nullable, + tok::kw___null_unspecified)) ConsumeToken(); } else { return TPResult::True; @@ -803,7 +801,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, if (Tok.is(tok::ellipsis)) ConsumeToken(); - if ((Tok.is(tok::identifier) || Tok.is(tok::kw_operator) || + if ((Tok.isOneOf(tok::identifier, tok::kw_operator) || (Tok.is(tok::annot_cxxscope) && (NextToken().is(tok::identifier) || NextToken().is(tok::kw_operator)))) && mayHaveIdentifier) { @@ -833,14 +831,9 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, // '(' declarator ')' // '(' attributes declarator ')' // '(' abstract-declarator ')' - if (Tok.is(tok::kw___attribute) || - Tok.is(tok::kw___declspec) || - Tok.is(tok::kw___cdecl) || - 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)) + if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec, tok::kw___cdecl, + tok::kw___stdcall, tok::kw___fastcall, tok::kw___thiscall, + tok::kw___vectorcall, tok::kw___unaligned)) return TPResult::True; // attributes indicate declaration TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); if (TPR != TPResult::Ambiguous) @@ -1015,9 +1008,8 @@ 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); + WantTypeSpecifiers = Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater, + tok::l_brace, tok::identifier); } bool ValidateCandidate(const TypoCorrection &Candidate) override { @@ -1201,8 +1193,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::coloncolon: { // ::foo::bar const Token &Next = NextToken(); - if (Next.is(tok::kw_new) || // ::new - Next.is(tok::kw_delete)) // ::delete + if (Next.isOneOf(tok::kw_new, // ::new + tok::kw_delete)) // ::delete return TPResult::False; } // Fall through. @@ -1284,6 +1276,9 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw___ptr32: case tok::kw___forceinline: case tok::kw___unaligned: + case tok::kw___nonnull: + case tok::kw___nullable: + case tok::kw___null_unspecified: return TPResult::True; // Borland @@ -1603,12 +1598,10 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) { TPR = TPResult::False; else { const Token &Next = NextToken(); - if (Next.is(tok::amp) || Next.is(tok::ampamp) || - Next.is(tok::kw_const) || Next.is(tok::kw_volatile) || - Next.is(tok::kw_throw) || Next.is(tok::kw_noexcept) || - Next.is(tok::l_square) || isCXX11VirtSpecifier(Next) || - Next.is(tok::l_brace) || Next.is(tok::kw_try) || - Next.is(tok::equal) || Next.is(tok::arrow)) + if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile, + tok::kw_throw, tok::kw_noexcept, tok::l_square, + tok::l_brace, tok::kw_try, tok::equal, tok::arrow) || + isCXX11VirtSpecifier(Next)) // The next token cannot appear after a constructor-style initializer, // and can appear next in a function definition. This must be a function // declarator. @@ -1729,8 +1722,8 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration, // parameter-declaration-clause, and the last param is missing its default // argument. if (VersusTemplateArgument) - return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True - : TPResult::False; + return Tok.isOneOf(tok::equal, tok::r_paren) ? TPResult::True + : TPResult::False; if (Tok.is(tok::equal)) { // '=' assignment-expression @@ -1783,13 +1776,11 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { return TPResult::Error; // cv-qualifier-seq - while (Tok.is(tok::kw_const) || - Tok.is(tok::kw_volatile) || - Tok.is(tok::kw_restrict) ) + while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict)) ConsumeToken(); // ref-qualifier[opt] - if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) + if (Tok.isOneOf(tok::amp, tok::ampamp)) ConsumeToken(); // exception-specification diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 7ccd209..e32df95 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -38,6 +38,26 @@ public: return false; } }; + +/// \brief RAIIObject to destroy the contents of a SmallVector of +/// TemplateIdAnnotation pointers and clear the vector. +class DestroyTemplateIdAnnotationsRAIIObj { + SmallVectorImpl<TemplateIdAnnotation *> &Container; + +public: + DestroyTemplateIdAnnotationsRAIIObj( + SmallVectorImpl<TemplateIdAnnotation *> &Container) + : Container(Container) {} + + ~DestroyTemplateIdAnnotationsRAIIObj() { + for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I = + Container.begin(), + E = Container.end(); + I != E; ++I) + (*I)->Destroy(); + Container.clear(); + } +}; } // end anonymous namespace IdentifierInfo *Parser::getSEHExceptKeyword() { @@ -414,6 +434,15 @@ Parser::~Parser() { PP.clearCodeCompletionHandler(); + if (getLangOpts().DelayedTemplateParsing && + !PP.isIncrementalProcessingEnabled() && !TemplateIds.empty()) { + // If an ASTConsumer parsed delay-parsed templates in their + // HandleTranslationUnit() method, TemplateIds created there were not + // guarded by a DestroyTemplateIdAnnotationsRAIIObj object in + // ParseTopLevelDecl(). Destroy them here. + DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds); + } + assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?"); } @@ -434,6 +463,10 @@ void Parser::Initialize() { ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway"); ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy"); ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref"); + ObjCTypeQuals[objc_nonnull] = &PP.getIdentifierTable().get("nonnull"); + ObjCTypeQuals[objc_nullable] = &PP.getIdentifierTable().get("nullable"); + ObjCTypeQuals[objc_null_unspecified] + = &PP.getIdentifierTable().get("null_unspecified"); } Ident_instancetype = nullptr; @@ -490,26 +523,6 @@ void Parser::Initialize() { ConsumeToken(); } -namespace { - /// \brief RAIIObject to destroy the contents of a SmallVector of - /// TemplateIdAnnotation pointers and clear the vector. - class DestroyTemplateIdAnnotationsRAIIObj { - SmallVectorImpl<TemplateIdAnnotation *> &Container; - public: - DestroyTemplateIdAnnotationsRAIIObj(SmallVectorImpl<TemplateIdAnnotation *> - &Container) - : Container(Container) {} - - ~DestroyTemplateIdAnnotationsRAIIObj() { - for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I = - Container.begin(), E = Container.end(); - I != E; ++I) - (*I)->Destroy(); - Container.clear(); - } - }; -} - 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 @@ -541,8 +554,14 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { return false; case tok::annot_module_begin: + Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast<Module *>( + Tok.getAnnotationValue())); + ConsumeToken(); + return false; + case tok::annot_module_end: - // FIXME: Update visibility based on the submodule we're in. + Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast<Module *>( + Tok.getAnnotationValue())); ConsumeToken(); return false; @@ -669,8 +688,18 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, SourceLocation StartLoc = Tok.getLocation(); SourceLocation EndLoc; + ExprResult Result(ParseSimpleAsm(&EndLoc)); + // Check if GNU-style InlineAsm is disabled. + // Empty asm string is allowed because it will not introduce + // any assembly code. + if (!(getLangOpts().GNUAsm || Result.isInvalid())) { + const auto *SL = cast<StringLiteral>(Result.get()); + if (!SL->getString().trim().empty()) + Diag(StartLoc, diag::err_gnu_inline_asm_disabled); + } + ExpectAndConsume(tok::semi, diag::err_expected_after, "top-level asm block"); @@ -1048,7 +1077,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (TryConsumeToken(tok::equal)) { assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='"); - Actions.ActOnFinishFunctionBody(Res, nullptr, false); bool Delete = false; SourceLocation KWLoc; @@ -1076,6 +1104,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, SkipUntil(tok::semi); } + Stmt *GeneratedBody = Res ? Res->getBody() : nullptr; + Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false); return Res; } diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h index a0c9c1f..36d87eb 100644 --- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h +++ b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h @@ -58,6 +58,12 @@ namespace clang { Active = false; } } + SuppressAccessChecks(SuppressAccessChecks &&Other) + : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)), + State(Other.State), Active(Other.Active) { + Other.Active = false; + } + void operator=(SuppressAccessChecks &&Other) = delete; void done() { assert(Active && "trying to end an inactive suppression"); @@ -87,8 +93,8 @@ namespace clang { Sema::ParsingDeclState State; bool Popped; - ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION; - void operator=(const ParsingDeclRAIIObject &) LLVM_DELETED_FUNCTION; + ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete; + void operator=(const ParsingDeclRAIIObject &) = delete; public: enum NoParent_t { NoParent }; @@ -244,8 +250,8 @@ namespace clang { /// the way they used to be. This is used to handle __extension__ in the /// parser. class ExtensionRAIIObject { - ExtensionRAIIObject(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION; - void operator=(const ExtensionRAIIObject &) LLVM_DELETED_FUNCTION; + ExtensionRAIIObject(const ExtensionRAIIObject &) = delete; + void operator=(const ExtensionRAIIObject &) = delete; DiagnosticsEngine &Diags; public: @@ -423,7 +429,13 @@ namespace clang { if (P.Tok.is(Close)) { LClose = (P.*Consumer)(); return false; - } + } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) { + SourceLocation SemiLoc = P.ConsumeToken(); + P.Diag(SemiLoc, diag::err_unexpected_semi) + << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc)); + LClose = (P.*Consumer)(); + return false; + } return diagnoseMissingClose(); } |