diff options
Diffstat (limited to 'lib/Parse')
| -rw-r--r-- | lib/Parse/ParseAST.cpp | 34 | ||||
| -rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 10 | ||||
| -rw-r--r-- | lib/Parse/ParseDecl.cpp | 124 | ||||
| -rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 200 | ||||
| -rw-r--r-- | lib/Parse/ParseExpr.cpp | 86 | ||||
| -rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 111 | ||||
| -rw-r--r-- | lib/Parse/ParseInit.cpp | 6 | ||||
| -rw-r--r-- | lib/Parse/ParseObjc.cpp | 41 | ||||
| -rw-r--r-- | lib/Parse/ParseOpenMP.cpp | 390 | ||||
| -rw-r--r-- | lib/Parse/ParsePragma.cpp | 273 | ||||
| -rw-r--r-- | lib/Parse/ParseStmt.cpp | 151 | ||||
| -rw-r--r-- | lib/Parse/ParseTemplate.cpp | 77 | ||||
| -rw-r--r-- | lib/Parse/ParseTentative.cpp | 105 | ||||
| -rw-r--r-- | lib/Parse/Parser.cpp | 23 |
14 files changed, 1070 insertions, 561 deletions
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp index e71b5a9d1e6d0..f7703b1bfd8a0 100644 --- a/lib/Parse/ParseAST.cpp +++ b/lib/Parse/ParseAST.cpp @@ -141,26 +141,26 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); - if (!S.getPreprocessor().getCurrentLexer()) { - // If a PCH through header is specified that does not have an include in - // the source, there won't be any tokens or a Lexer. - return; - } - - P.Initialize(); - - Parser::DeclGroupPtrTy ADecl; ExternalASTSource *External = S.getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(Consumer); - for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; - AtEOF = P.ParseTopLevelDecl(ADecl)) { - // If we got a null return and something *was* parsed, ignore it. This - // is due to a top-level semicolon, an action override, or a parse error - // skipping something. - if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) - return; + // If a PCH through header is specified that does not have an include in + // the source, or a PCH is being created with #pragma hdrstop with nothing + // after the pragma, there won't be any tokens or a Lexer. + bool HaveLexer = S.getPreprocessor().getCurrentLexer(); + + if (HaveLexer) { + P.Initialize(); + Parser::DeclGroupPtrTy ADecl; + for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; + AtEOF = P.ParseTopLevelDecl(ADecl)) { + // If we got a null return and something *was* parsed, ignore it. This + // is due to a top-level semicolon, an action override, or a parse error + // skipping something. + if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) + return; + } } // Process any TopLevelDecls generated by #pragma weak. @@ -179,7 +179,7 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; - P.getActions().PrintStats(); + if (HaveLexer) P.getActions().PrintStats(); S.getASTContext().PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 5898120cab461..fde3ce00f8302 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -595,7 +595,7 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) { // to X" within the optional brace-or-equal-initializer. It shall not // appear elsewhere in the member-declarator. Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate, - /*TypeQuals=*/(unsigned)0); + Qualifiers()); for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers(); @@ -728,7 +728,7 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, case tok::semi: if (StopAtSemi) return false; - // FALL THROUGH. + LLVM_FALLTHROUGH; default: // consume this token. Toks.push_back(Tok); @@ -1108,13 +1108,13 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, goto consume_token; if (AngleCount) --AngleCount; if (KnownTemplateCount) --KnownTemplateCount; - // Fall through. + LLVM_FALLTHROUGH; case tok::greatergreater: if (!getLangOpts().CPlusPlus11) goto consume_token; if (AngleCount) --AngleCount; if (KnownTemplateCount) --KnownTemplateCount; - // Fall through. + LLVM_FALLTHROUGH; case tok::greater: if (AngleCount) --AngleCount; if (KnownTemplateCount) --KnownTemplateCount; @@ -1219,7 +1219,7 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, case tok::semi: if (CIK == CIK_DefaultInitializer) return true; // End of the default initializer. - // FALL THROUGH. + LLVM_FALLTHROUGH; default: consume_token: Toks.push_back(Tok); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6e57c7bbba913..298a2bad56c60 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -24,7 +24,6 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" -#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" @@ -754,7 +753,7 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { case tok::kw__Null_unspecified: { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - if (!getLangOpts().ObjC1) + if (!getLangOpts().ObjC) Diag(AttrNameLoc, diag::ext_nullability) << AttrName; attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, @@ -1001,6 +1000,21 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, continue; } + if (Keyword == Ident_deprecated && Platform->Ident && + Platform->Ident->isStr("swift")) { + // For swift, we deprecate for all versions. + if (Changes[Deprecated].KeywordLoc.isValid()) { + Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword + << SourceRange(Changes[Deprecated].KeywordLoc); + } + + Changes[Deprecated].KeywordLoc = KeywordLoc; + // Use a fake version here. + Changes[Deprecated].Version = VersionTuple(1); + continue; + } + if (Tok.isNot(tok::equal)) { Diag(Tok, diag::err_expected_after) << Keyword << tok::equal; SkipUntil(tok::r_paren, StopAtSemi); @@ -1412,7 +1426,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); // Allow 'this' within late-parsed attributes. - Sema::CXXThisScopeRAII ThisScope(Actions, RD, /*TypeQuals=*/0, + Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(), ND && ND->isCXXInstanceMember()); if (LA.Decls.size() == 1) { @@ -1940,7 +1954,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, Diag(Loc, diag::err_c11_noreturn_misplaced) << (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint()) - << (Fixit ? FixItHint::CreateInsertion(D.getLocStart(), "_Noreturn ") + << (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ") : FixItHint()); } } @@ -2302,20 +2316,28 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( llvm::function_ref<void()> ExprListCompleter; auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl); auto ConstructorCompleter = [&, ThisVarDecl] { - Actions.CodeCompleteConstructor( + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), - ThisDecl->getLocation(), Exprs); + ThisDecl->getLocation(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; + Actions.CodeCompleteExpression(getCurScope(), PreferredType); }; if (ThisVarDecl) { // ParseExpressionList can sometimes succeed even when ThisDecl is not // VarDecl. This is an error and it is reported in a call to // Actions.ActOnInitializerError(). However, we call - // CodeCompleteConstructor only on VarDecls, falling back to default - // completer in other cases. + // ProduceConstructorSignatureHelp only on VarDecls, falling back to + // default completer in other cases. ExprListCompleter = ConstructorCompleter; } if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) { + if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceConstructorSignatureHelp( + getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), + ThisDecl->getLocation(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; + } Actions.ActOnInitializerError(ThisDecl); SkipUntil(tok::r_paren, StopAtSemi); } else { @@ -2841,7 +2863,7 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, return false; const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy(); - Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()), + Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getEndLoc()), diag::err_expected_after) << DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi; @@ -3282,7 +3304,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Objective-C supports type arguments and protocol references // following an Objective-C object or object pointer // type. Handle either one of them. - if (Tok.is(tok::less) && getLangOpts().ObjC1) { + if (Tok.is(tok::less) && getLangOpts().ObjC) { SourceLocation NewEndLoc; TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers( Loc, TypeRep, /*consumeLastToken=*/true, @@ -3804,7 +3826,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // GCC ObjC supports types like "<SomeProtocol>" as a synonym for // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous, // but we support it. - if (DS.hasTypeSpecifier() || !getLangOpts().ObjC1) + if (DS.hasTypeSpecifier() || !getLangOpts().ObjC) goto DoneWithDeclSpec; SourceLocation StartLoc = Tok.getLocation(); @@ -3830,7 +3852,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, assert(PrevSpec && "Method did not return previous specifier!"); assert(DiagID); - if (DiagID == diag::ext_duplicate_declspec) + if (DiagID == diag::ext_duplicate_declspec || + DiagID == diag::ext_warn_duplicate_declspec) Diag(Tok, DiagID) << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); else if (DiagID == diag::err_opencl_unknown_type_specifier) { @@ -4145,15 +4168,11 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // Enum definitions should not be parsed in a trailing-return-type. bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing; - bool AllowFixedUnderlyingType = AllowDeclaration && - (getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt || - getLangOpts().ObjC2); - CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLangOpts().CPlusPlus) { // "enum foo : bar;" is not a potential typo for "enum foo::bar;" // if a fixed underlying type is allowed. - ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType); + ColonProtectionRAIIObject X(*this, AllowDeclaration); CXXScopeSpec Spec; if (ParseOptionalCXXScopeSpecifier(Spec, nullptr, @@ -4175,7 +4194,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // Must have either 'enum name' or 'enum {...}'. if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) && - !(AllowFixedUnderlyingType && Tok.is(tok::colon))) { + !(AllowDeclaration && Tok.is(tok::colon))) { Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; // Skip the rest of this declarator, up until the comma or semicolon. @@ -4208,7 +4227,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // Parse the fixed underlying type. bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope; - if (AllowFixedUnderlyingType && Tok.is(tok::colon)) { + if (AllowDeclaration && Tok.is(tok::colon)) { bool PossibleBitfield = false; if (CanBeBitfield) { // If we're in class scope, this can either be an enum declaration with @@ -4268,13 +4287,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SourceRange Range; BaseType = ParseTypeName(&Range); - if (getLangOpts().CPlusPlus11) { - Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type); - } else if (!getLangOpts().ObjC2) { - if (getLangOpts().CPlusPlus) - Diag(StartLoc, diag::ext_cxx11_enum_fixed_underlying_type) << Range; + if (!getLangOpts().ObjC) { + if (getLangOpts().CPlusPlus11) + Diag(StartLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type); + else if (getLangOpts().CPlusPlus) + Diag(StartLoc, diag::ext_cxx11_enum_fixed_underlying_type); + else if (getLangOpts().MicrosoftExt) + Diag(StartLoc, diag::ext_ms_c_enum_fixed_underlying_type); else - Diag(StartLoc, diag::ext_c_enum_fixed_underlying_type) << Range; + Diag(StartLoc, diag::ext_clang_c_enum_fixed_underlying_type); } } } @@ -4654,7 +4675,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::identifier: // foo::bar if (TryAltiVecVectorToken()) return true; - // Fall through. + LLVM_FALLTHROUGH; case tok::kw_typename: // typename T::type // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. @@ -4733,7 +4754,7 @@ bool Parser::isTypeSpecifierQualifier() { // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'. case tok::less: - return getLangOpts().ObjC1; + return getLangOpts().ObjC; case tok::kw___cdecl: case tok::kw___stdcall: @@ -4784,11 +4805,11 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::identifier: // foo::bar // Unfortunate hack to support "Class.factoryMethod" notation. - if (getLangOpts().ObjC1 && NextToken().is(tok::period)) + if (getLangOpts().ObjC && NextToken().is(tok::period)) return false; if (TryAltiVecVectorToken()) return true; - // Fall through. + LLVM_FALLTHROUGH; case tok::kw_decltype: // decltype(T())::type case tok::kw_typename: // typename T::type // Annotate typenames and C++ scope specifiers. If we get one, just @@ -4914,7 +4935,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'. case tok::less: - return getLangOpts().ObjC1; + return getLangOpts().ObjC; // typedef-name case tok::annot_typename: @@ -5363,7 +5384,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. D.AddTypeInfo(DeclaratorChunk::getMemberPointer( - SS, DS.getTypeQualifiers(), DS.getLocEnd()), + SS, DS.getTypeQualifiers(), DS.getEndLoc()), std::move(DS.getAttributes()), /* Don't replace range end. */ SourceLocation()); return; @@ -5755,7 +5776,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (D.getContext() == DeclaratorContext::MemberContext) { // Objective-C++: Detect C++ keywords and try to prevent further errors by // treating these keyword as valid member names. - if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus && + if (getLangOpts().ObjC && getLangOpts().CPlusPlus && Tok.getIdentifierInfo() && Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) { Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), @@ -6051,9 +6072,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D, DeclSpec DS(AttrFactory); bool RefQualifierIsLValueRef = true; SourceLocation RefQualifierLoc; - SourceLocation ConstQualifierLoc; - SourceLocation VolatileQualifierLoc; - SourceLocation RestrictQualifierLoc; ExceptionSpecificationType ESpecType = EST_None; SourceRange ESpecRange; SmallVector<ParsedType, 2> DynamicExceptions; @@ -6116,9 +6134,6 @@ void Parser::ParseFunctionDeclarator(Declarator &D, })); if (!DS.getSourceRange().getEnd().isInvalid()) { EndLoc = DS.getSourceRange().getEnd(); - ConstQualifierLoc = DS.getConstSpecLoc(); - VolatileQualifierLoc = DS.getVolatileSpecLoc(); - RestrictQualifierLoc = DS.getRestrictSpecLoc(); } // Parse ref-qualifier[opt]. @@ -6140,13 +6155,14 @@ void Parser::ParseFunctionDeclarator(Declarator &D, : D.getContext() == DeclaratorContext::FileContext && D.getCXXScopeSpec().isValid() && Actions.CurContext->isRecord()); - Sema::CXXThisScopeRAII ThisScope(Actions, - dyn_cast<CXXRecordDecl>(Actions.CurContext), - DS.getTypeQualifiers() | - (D.getDeclSpec().isConstexprSpecified() && - !getLangOpts().CPlusPlus14 - ? Qualifiers::Const : 0), - IsCXX11MemberFunction); + + Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers()); + if (D.getDeclSpec().isConstexprSpecified() && !getLangOpts().CPlusPlus14) + Q.addConst(); + + Sema::CXXThisScopeRAII ThisScope( + Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q, + IsCXX11MemberFunction); // Parse exception-specification[opt]. bool Delayed = D.isFirstDeclarationOfMember() && @@ -6217,15 +6233,13 @@ void Parser::ParseFunctionDeclarator(Declarator &D, D.AddTypeInfo(DeclaratorChunk::getFunction( HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(), ParamInfo.size(), EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), RefQualifierIsLValueRef, - RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, - RestrictQualifierLoc, - /*MutableLoc=*/SourceLocation(), ESpecType, ESpecRange, - DynamicExceptions.data(), DynamicExceptionRanges.data(), - DynamicExceptions.size(), + RefQualifierIsLValueRef, RefQualifierLoc, + /*MutableLoc=*/SourceLocation(), + ESpecType, ESpecRange, DynamicExceptions.data(), + DynamicExceptionRanges.data(), DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, ExceptionSpecTokens, DeclsInPrototype, StartLoc, - LocalEndLoc, D, TrailingReturnType), + LocalEndLoc, D, TrailingReturnType, &DS), std::move(FnAttrs), EndLoc); } @@ -6693,7 +6707,7 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { if (NeedParens) { // Create a DeclaratorChunk for the inserted parens. - SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd()); + SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc()); D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), SourceLocation()); } @@ -6709,11 +6723,11 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { if (!D.getIdentifier() && !NeedParens) return; - SourceLocation EndBracketLoc = TempDeclarator.getLocEnd(); + SourceLocation EndBracketLoc = TempDeclarator.getEndLoc(); // Generate the move bracket error message. SourceRange BracketRange(StartBracketLoc, EndBracketLoc); - SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd()); + SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc()); if (NeedParens) { Diag(EndLoc, diag::err_brackets_go_after_unqualified_id) diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 9ba44d07aba86..f8359f1e87d8e 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -24,7 +24,6 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" -#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -33,24 +32,25 @@ using namespace clang; /// may either be a top level namespace or a block-level namespace alias. If /// there was an inline keyword, it has already been parsed. /// -/// namespace-definition: [C++ 7.3: basic.namespace] +/// namespace-definition: [C++: namespace.def] /// named-namespace-definition /// unnamed-namespace-definition +/// nested-namespace-definition +/// +/// named-namespace-definition: +/// 'inline'[opt] 'namespace' attributes[opt] identifier '{' +/// namespace-body '}' /// /// unnamed-namespace-definition: /// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}' /// -/// named-namespace-definition: -/// original-namespace-definition -/// extension-namespace-definition -/// -/// original-namespace-definition: -/// 'inline'[opt] 'namespace' identifier attributes[opt] -/// '{' namespace-body '}' +/// nested-namespace-definition: +/// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt] +/// identifier '{' namespace-body '}' /// -/// extension-namespace-definition: -/// 'inline'[opt] 'namespace' original-namespace-name -/// '{' namespace-body '}' +/// enclosing-namespace-specifier: +/// identifier +/// enclosing-namespace-specifier '::' 'inline'[opt] identifier /// /// namespace-alias-definition: [C++ 7.3.2: namespace.alias] /// 'namespace' identifier '=' qualified-namespace-specifier ';' @@ -70,9 +70,8 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, SourceLocation IdentLoc; IdentifierInfo *Ident = nullptr; - std::vector<SourceLocation> ExtraIdentLoc; - std::vector<IdentifierInfo*> ExtraIdent; - std::vector<SourceLocation> ExtraNamespaceLoc; + InnerNamespaceInfoList ExtraNSs; + SourceLocation FirstNestedInlineLoc; ParsedAttributesWithRange attrs(AttrFactory); SourceLocation attrLoc; @@ -88,15 +87,29 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); IdentLoc = ConsumeToken(); // eat the identifier. - while (Tok.is(tok::coloncolon) && NextToken().is(tok::identifier)) { - ExtraNamespaceLoc.push_back(ConsumeToken()); - ExtraIdent.push_back(Tok.getIdentifierInfo()); - ExtraIdentLoc.push_back(ConsumeToken()); + while (Tok.is(tok::coloncolon) && + (NextToken().is(tok::identifier) || + (NextToken().is(tok::kw_inline) && + GetLookAheadToken(2).is(tok::identifier)))) { + + InnerNamespaceInfo Info; + Info.NamespaceLoc = ConsumeToken(); + + if (Tok.is(tok::kw_inline)) { + Info.InlineLoc = ConsumeToken(); + if (FirstNestedInlineLoc.isInvalid()) + FirstNestedInlineLoc = Info.InlineLoc; + } + + Info.Ident = Tok.getIdentifierInfo(); + Info.IdentLoc = ConsumeToken(); + + ExtraNSs.push_back(Info); } } // A nested namespace definition cannot have attributes. - if (!ExtraNamespaceLoc.empty() && attrLoc.isValid()) + if (!ExtraNSs.empty() && attrLoc.isValid()) Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute); // Read label attributes, if present. @@ -138,13 +151,21 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, return nullptr; } - if (ExtraIdent.empty()) { + if (ExtraNSs.empty()) { // Normal namespace definition, not a nested-namespace-definition. } else if (InlineLoc.isValid()) { Diag(InlineLoc, diag::err_inline_nested_namespace_definition); + } else if (getLangOpts().CPlusPlus2a) { + Diag(ExtraNSs[0].NamespaceLoc, + diag::warn_cxx14_compat_nested_namespace_definition); + if (FirstNestedInlineLoc.isValid()) + Diag(FirstNestedInlineLoc, + diag::warn_cxx17_compat_inline_nested_namespace_definition); } else if (getLangOpts().CPlusPlus17) { - Diag(ExtraNamespaceLoc[0], + Diag(ExtraNSs[0].NamespaceLoc, diag::warn_cxx14_compat_nested_namespace_definition); + if (FirstNestedInlineLoc.isValid()) + Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition); } else { TentativeParsingAction TPA(*this); SkipUntil(tok::r_brace, StopBeforeMatch); @@ -152,26 +173,34 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, TPA.Revert(); if (!rBraceToken.is(tok::r_brace)) { - Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) - << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); + Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition) + << SourceRange(ExtraNSs.front().NamespaceLoc, + ExtraNSs.back().IdentLoc); } else { std::string NamespaceFix; - for (std::vector<IdentifierInfo*>::iterator I = ExtraIdent.begin(), - E = ExtraIdent.end(); I != E; ++I) { - NamespaceFix += " { namespace "; - NamespaceFix += (*I)->getName(); + for (const auto &ExtraNS : ExtraNSs) { + NamespaceFix += " { "; + if (ExtraNS.InlineLoc.isValid()) + NamespaceFix += "inline "; + NamespaceFix += "namespace "; + NamespaceFix += ExtraNS.Ident->getName(); } std::string RBraces; - for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i) + for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i) RBraces += "} "; - Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) - << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(), - ExtraIdentLoc.back()), - NamespaceFix) + Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition) + << FixItHint::CreateReplacement( + SourceRange(ExtraNSs.front().NamespaceLoc, + ExtraNSs.back().IdentLoc), + NamespaceFix) << FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces); } + + // Warn about nested inline namespaces. + if (FirstNestedInlineLoc.isValid()) + Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition); } // If we're still good, complain about inline namespaces in non-C++0x now. @@ -192,8 +221,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, // Parse the contents of the namespace. This includes parsing recovery on // any improperly nested namespaces. - ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0, - InlineLoc, attrs, T); + ParseInnerNamespace(ExtraNSs, 0, InlineLoc, attrs, T); // Leave the namespace scope. NamespaceScope.Exit(); @@ -206,13 +234,11 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, } /// ParseInnerNamespace - Parse the contents of a namespace. -void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, - std::vector<IdentifierInfo *> &Ident, - std::vector<SourceLocation> &NamespaceLoc, +void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs, unsigned int index, SourceLocation &InlineLoc, ParsedAttributes &attrs, BalancedDelimiterTracker &Tracker) { - if (index == Ident.size()) { + if (index == InnerNSs.size()) { while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); @@ -233,14 +259,13 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, ParseScope NamespaceScope(this, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( - getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index], - Ident[index], Tracker.getOpenLocation(), attrs, - ImplicitUsingDirectiveDecl); + getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc, + InnerNSs[index].IdentLoc, InnerNSs[index].Ident, + Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); - ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc, - attrs, Tracker); + ParseInnerNamespace(InnerNSs, ++index, InlineLoc, attrs, Tracker); NamespaceScope.Exit(); Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation()); @@ -365,7 +390,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { case tok::r_brace: if (!NestedModules) break; - // Fall through. + LLVM_FALLTHROUGH; default: ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); @@ -2321,32 +2346,22 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( 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) { + auto DeclSpecCheck = [&](DeclSpec::TQ TypeQual, StringRef FixItName, + SourceLocation SpecLoc) { FixItHint Insertion; - if (DS.getTypeQualifiers() & TypeQual) { - if (!(Function.TypeQuals & TypeQual)) { - std::string Name(FixItName); - Name += " "; - Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name); - Function.TypeQuals |= TypeQual; - *QualifierLoc = SpecLoc.getRawEncoding(); - } - Diag(SpecLoc, diag::err_declspec_after_virtspec) + auto &MQ = Function.getOrCreateMethodQualifiers(); + if (!(MQ.getTypeQualifiers() & TypeQual)) { + std::string Name(FixItName.data()); + Name += " "; + Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name); + MQ.SetTypeQual(TypeQual, SpecLoc); + } + Diag(SpecLoc, diag::err_declspec_after_virtspec) << FixItName << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) - << FixItHint::CreateRemoval(SpecLoc) - << Insertion; - } + << 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); + DS.forEachQualifier(DeclSpecCheck); } // Parse ref-qualifiers. @@ -2410,7 +2425,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { if (Tok.is(tok::at)) { - if (getLangOpts().ObjC1 && NextToken().isObjCAtKeyword(tok::objc_defs)) + if (getLangOpts().ObjC && NextToken().isObjCAtKeyword(tok::objc_defs)) Diag(Tok, diag::err_at_defs_cxx); else Diag(Tok, diag::err_at_in_class); @@ -3449,6 +3464,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); + // FIXME: Add support for signature help inside initializer lists. ExprResult InitList = ParseBraceInitializer(); if (InitList.isInvalid()) return true; @@ -3466,7 +3482,20 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // Parse the optional expression-list. ExprVector ArgExprs; CommaLocsTy CommaLocs; - if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { + if (Tok.isNot(tok::r_paren) && + ParseExpressionList(ArgExprs, CommaLocs, [&] { + QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp( + getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II, + T.getOpenLocation()); + CalledSignatureHelp = true; + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + })) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceCtorInitMemberSignatureHelp( + getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II, + T.getOpenLocation()); + CalledSignatureHelp = true; + } SkipUntil(tok::r_paren, StopAtSemi); return true; } @@ -3776,6 +3805,28 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { } return nullptr; + case tok::numeric_constant: { + // If we got a numeric constant, check to see if it comes from a macro that + // corresponds to the predefined __clang__ macro. If it does, warn the user + // and recover by pretending they said _Clang instead. + if (Tok.getLocation().isMacroID()) { + SmallString<8> ExpansionBuf; + SourceLocation ExpansionLoc = + PP.getSourceManager().getExpansionLoc(Tok.getLocation()); + StringRef Spelling = PP.getSpelling(ExpansionLoc, ExpansionBuf); + if (Spelling == "__clang__") { + SourceRange TokRange( + ExpansionLoc, + PP.getSourceManager().getExpansionLoc(Tok.getEndLoc())); + Diag(Tok, diag::warn_wrong_clang_attr_namespace) + << FixItHint::CreateReplacement(TokRange, "_Clang"); + Loc = ConsumeToken(); + return &PP.getIdentifierTable().get("_Clang"); + } + } + return nullptr; + } + case tok::ampamp: // 'and' case tok::pipe: // 'bitor' case tok::pipepipe: // 'or' @@ -3854,7 +3905,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, return false; } - if (ScopeName && ScopeName->getName() == "gnu") { + if (ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"))) { // GNU-scoped attributes have some special cases to handle GNU-specific // behaviors. ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, @@ -3864,10 +3915,9 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, unsigned NumArgs; // Some Clang-scoped attributes have some special parsing behavior. - if (ScopeName && ScopeName->getName() == "clang") - NumArgs = - ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, Syntax); + if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"))) + NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); else NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, @@ -3875,7 +3925,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, if (!Attrs.empty() && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { - ParsedAttr &Attr = *Attrs.begin(); + ParsedAttr &Attr = Attrs.back(); // If the attribute is a standard or built-in attribute and we are // parsing an argument list, we need to determine whether this attribute // was allowed to have an argument list (such as [[deprecated]]), and how diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 2a65eec8a0f63..4bcbebcbb48ec 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -315,6 +315,19 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } + // In Objective-C++, alternative operator tokens can be used as keyword args + // in message expressions. Unconsume the token so that it can reinterpreted + // as an identifier in ParseObjCMessageExpressionBody. i.e., we support: + // [foo meth:0 and:0]; + // [foo not_eq]; + if (getLangOpts().ObjC && getLangOpts().CPlusPlus && + Tok.isOneOf(tok::colon, tok::r_square) && + OpToken.getIdentifierInfo() != nullptr) { + PP.EnterToken(Tok); + Tok = OpToken; + return LHS; + } + // Special case handling for the ternary operator. ExprResult TernaryMiddle(true); if (NextTokPrec == prec::Conditional) { @@ -380,10 +393,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { } } - // Code completion for the right-hand side of an assignment expression - // goes through a special hook that takes the left-hand side into account. - if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) { - Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get()); + // Code completion for the right-hand side of a binary expression goes + // through a special hook that takes the left-hand side into account. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteBinaryRHS(getCurScope(), LHS.get(), + OpToken.getKind()); cutOffParsing(); return ExprError(); } @@ -944,7 +958,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, SourceLocation ILoc = ConsumeToken(); // Support 'Class.property' and 'super.property' notation. - if (getLangOpts().ObjC1 && Tok.is(tok::period) && + if (getLangOpts().ObjC && Tok.is(tok::period) && (Actions.getTypeName(II, ILoc, getCurScope()) || // Allow the base to be 'super' if in an objc-method. (&II == Ident_super && getCurScope()->isInObjcMethodScope()))) { @@ -974,7 +988,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // the token sequence is ill-formed. However, if there's a ':' or ']' after // that identifier, this is probably a message send with a missing open // bracket. Treat it as such. - if (getLangOpts().ObjC1 && &II == Ident_super && !InMessageExpression && + if (getLangOpts().ObjC && &II == Ident_super && !InMessageExpression && getCurScope()->isInObjcMethodScope() && ((Tok.is(tok::identifier) && (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) || @@ -989,7 +1003,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // send that's missing the opening '['. Recovery // appropriately. Also take this path if we're performing code // completion after an Objective-C class name. - if (getLangOpts().ObjC1 && + if (getLangOpts().ObjC && ((Tok.is(tok::identifier) && !InMessageExpression) || Tok.is(tok::code_completion))) { const Token& Next = NextToken(); @@ -1162,7 +1176,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')' if (!getLangOpts().C11) Diag(Tok, diag::ext_c11_alignment) << Tok.getName(); - // fallthrough + LLVM_FALLTHROUGH; case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')' case tok::kw___alignof: // unary-expression: '__alignof' unary-expression // unary-expression: '__alignof' '(' type-name ')' @@ -1228,7 +1242,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Ty.get(), nullptr); break; } - // Fall through + LLVM_FALLTHROUGH; case tok::annot_decltype: case tok::kw_char: @@ -1416,7 +1430,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } case tok::l_square: if (getLangOpts().CPlusPlus11) { - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { // C++11 lambda expressions and Objective-C message sends both start with a // square bracket. There are three possibilities here: // we have a valid lambda expression, we have an invalid lambda @@ -1430,11 +1444,11 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = ParseLambdaExpression(); break; } - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { Res = ParseObjCMessageExpression(); break; } - // FALL THROUGH. + LLVM_FALLTHROUGH; default: NotCastExpr = true; return ExprError(); @@ -1498,7 +1512,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // If we see identifier: after an expression, and we're not already in a // message send, then this is probably a message send with a missing // opening bracket '['. - if (getLangOpts().ObjC1 && !InMessageExpression && + if (getLangOpts().ObjC && !InMessageExpression && (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) { LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), nullptr, LHS.get()); @@ -1516,7 +1530,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // actually another message send. In this case, do some look-ahead to see // if the contents of the square brackets are obviously not a valid // expression and recover by pretending there is no suffix. - if (getLangOpts().ObjC1 && Tok.isAtStartOfLine() && + if (getLangOpts().ObjC && Tok.isAtStartOfLine() && isSimpleObjCMessageExpression()) return LHS; @@ -1637,7 +1651,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { CommaLocsTy CommaLocs; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteCall(getCurScope(), LHS.get(), None); + QualType PreferredType = Actions.ProduceCallSignatureHelp( + getCurScope(), LHS.get(), None, PT.getOpenLocation()); + CalledSignatureHelp = true; + Actions.CodeCompleteExpression(getCurScope(), PreferredType); cutOffParsing(); return ExprError(); } @@ -1645,9 +1662,21 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { if (ParseExpressionList(ArgExprs, CommaLocs, [&] { - Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs); - })) { + QualType PreferredType = Actions.ProduceCallSignatureHelp( + getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation()); + CalledSignatureHelp = true; + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + })) { (void)Actions.CorrectDelayedTyposInExpr(LHS); + // If we got an error when parsing expression list, we don't call + // the CodeCompleteCall handler inside the parser. So call it here + // to make sure we get overload suggestions even when we are in the + // middle of a parameter. + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceCallSignatureHelp(getCurScope(), LHS.get(), + ArgExprs, PT.getOpenLocation()); + CalledSignatureHelp = true; + } LHS = ExprError(); } else if (LHS.isInvalid()) { for (auto &E : ArgExprs) @@ -1738,11 +1767,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { Expr *Base = LHS.get(); Expr *CorrectedBase = CorrectedLHS.get(); + if (!CorrectedBase && !getLangOpts().CPlusPlus) + CorrectedBase = Base; // Code completion for a member access expression. Actions.CodeCompleteMemberReferenceExpr( getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow, - Base && ExprStatementTokLoc == Base->getLocStart()); + Base && ExprStatementTokLoc == Base->getBeginLoc()); cutOffParsing(); return ExprError(); @@ -1763,7 +1794,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // FIXME: Add support for explicit call of template constructor. SourceLocation TemplateKWLoc; UnqualifiedId Name; - if (getLangOpts().ObjC2 && OpKind == tok::period && + if (getLangOpts().ObjC && OpKind == tok::period && Tok.is(tok::kw_class)) { // Objective-C++: // After a '.' in a member access expression, treat the keyword @@ -1779,7 +1810,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /*EnteringContext=*/false, /*AllowDestructorName=*/true, /*AllowConstructorName=*/ - getLangOpts().MicrosoftExt, + getLangOpts().MicrosoftExt && + SS.isNotEmpty(), /*AllowDeductionGuide=*/false, ObjectType, &TemplateKWLoc, Name)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); @@ -1992,8 +2024,10 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { CastRange); UnaryExprOrTypeTrait ExprKind = UETT_SizeOf; - if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof)) + if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) ExprKind = UETT_AlignOf; + else if (OpTok.is(tok::kw___alignof)) + ExprKind = UETT_PreferredAlignOf; else if (OpTok.is(tok::kw_vec_step)) ExprKind = UETT_VecStep; else if (OpTok.is(tok::kw___builtin_omp_required_simd_align)) @@ -2306,7 +2340,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, } // Diagnose use of bridge casts in non-arc mode. - bool BridgeCast = (getLangOpts().ObjC2 && + bool BridgeCast = (getLangOpts().ObjC && Tok.isOneOf(tok::kw___bridge, tok::kw___bridge_transfer, tok::kw___bridge_retained, @@ -2416,7 +2450,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // this is probably an Objective-C message send where the leading '[' is // missing. Recover as if that were the case. if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) && - !InMessageExpression && getLangOpts().ObjC1 && + !InMessageExpression && getLangOpts().ObjC && (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) { TypeResult Ty; { @@ -2502,7 +2536,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, } // Reject the cast of super idiom in ObjC. - if (Tok.is(tok::identifier) && getLangOpts().ObjC1 && + if (Tok.is(tok::identifier) && getLangOpts().ObjC && Tok.getIdentifierInfo() == Ident_super && getCurScope()->isInObjcMethodScope() && GetLookAheadToken(1).isNot(tok::period)) { @@ -2978,12 +3012,8 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*NumArgs=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, /*RefQualifierIsLvalueRef=*/true, /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 663c397ee0495..3caec6b4def6e 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -235,22 +235,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, while (true) { if (HasScopeSpecifier) { - // C++ [basic.lookup.classref]p5: - // If the qualified-id has the form - // - // ::class-name-or-namespace-name::... - // - // the class-name-or-namespace-name is looked up in global scope as a - // class-name or namespace-name. - // - // To implement this, we clear out the object type as soon as we've - // seen a leading '::' or part of a nested-name-specifier. - ObjectType = nullptr; - if (Tok.is(tok::code_completion)) { // Code completion for a nested-name-specifier, where the code // completion token follows the '::'. - Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext); + Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext, + ObjectType.get()); // Include code completion token into the range of the scope otherwise // when we try to annotate the scope tokens the dangling code completion // token will cause assertion in @@ -259,6 +248,18 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, cutOffParsing(); return true; } + + // C++ [basic.lookup.classref]p5: + // If the qualified-id has the form + // + // ::class-name-or-namespace-name::... + // + // the class-name-or-namespace-name is looked up in global scope as a + // class-name or namespace-name. + // + // To implement this, we clear out the object type as soon as we've + // seen a leading '::' or part of a nested-name-specifier. + ObjectType = nullptr; } // nested-name-specifier: @@ -774,7 +775,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // send. In that case, fail here and let the ObjC message // expression parser perform the completion. if (Tok.is(tok::code_completion) && - !(getLangOpts().ObjC1 && Intro.Default == LCD_None && + !(getLangOpts().ObjC && Intro.Default == LCD_None && !Intro.Captures.empty())) { Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, /*AfterAmpersand=*/false); @@ -790,7 +791,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, if (Tok.is(tok::code_completion)) { // If we're in Objective-C++ and we have a bare '[', then this is more // likely to be a message receiver. - if (getLangOpts().ObjC1 && first) + if (getLangOpts().ObjC && first) Actions.CodeCompleteObjCMessageReceiver(getCurScope()); else Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro, @@ -1205,12 +1206,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*hasProto=*/true, /*isAmbiguous=*/false, LParenLoc, ParamInfo.data(), ParamInfo.size(), EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType, + /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange, DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, @@ -1272,12 +1269,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, + /*RefQualifierLoc=*/NoLoc, MutableLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, @@ -1674,8 +1667,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { return Init; Expr *InitList = Init.get(); return Actions.ActOnCXXTypeConstructExpr( - TypeRep, InitList->getLocStart(), MultiExprArg(&InitList, 1), - InitList->getLocEnd(), /*ListInitialization=*/true); + TypeRep, InitList->getBeginLoc(), MultiExprArg(&InitList, 1), + InitList->getEndLoc(), /*ListInitialization=*/true); } else { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -1685,10 +1678,18 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { if (Tok.isNot(tok::r_paren)) { if (ParseExpressionList(Exprs, CommaLocs, [&] { - Actions.CodeCompleteConstructor(getCurScope(), - TypeRep.get()->getCanonicalTypeInternal(), - DS.getLocEnd(), Exprs); - })) { + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DS.getEndLoc(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + })) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DS.getEndLoc(), Exprs, T.getOpenLocation()); + CalledSignatureHelp = true; + } SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -1730,10 +1731,14 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// \param Loc The location of the start of the statement that requires this /// condition, e.g., the "for" in a for loop. /// +/// \param FRI If non-null, a for range declaration is permitted, and if +/// present will be parsed and stored here, and a null result will be returned. +/// /// \returns The parsed condition. Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, - Sema::ConditionKind CK) { + Sema::ConditionKind CK, + ForRangeInfo *FRI) { ParenBraceBracketBalancer BalancerRAIIObj(*this); if (Tok.is(tok::code_completion)) { @@ -1753,7 +1758,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, }; // Determine what kind of thing we have. - switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) { + switch (isCXXConditionDeclarationOrInitStatement(InitStmt, FRI)) { case ConditionOrInitStatement::Expression: { ProhibitAttributes(attrs); @@ -1761,7 +1766,13 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, // if (; true); if (InitStmt && Tok.is(tok::semi)) { WarnOnInit(); - SourceLocation SemiLoc = ConsumeToken(); + SourceLocation SemiLoc = Tok.getLocation(); + if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID()) { + Diag(SemiLoc, diag::warn_empty_init_statement) + << (CK == Sema::ConditionKind::Switch) + << FixItHint::CreateRemoval(SemiLoc); + } + ConsumeToken(); *InitStmt = Actions.ActOnNullStmt(SemiLoc); return ParseCXXCondition(nullptr, Loc, CK); } @@ -1791,6 +1802,15 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, return ParseCXXCondition(nullptr, Loc, CK); } + case ConditionOrInitStatement::ForRangeDecl: { + assert(FRI && "should not parse a for range declaration here"); + SourceLocation DeclStart = Tok.getLocation(), DeclEnd; + DeclGroupPtrTy DG = ParseSimpleDeclaration( + DeclaratorContext::ForContext, DeclEnd, attrs, false, FRI); + FRI->LoopVar = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); + return Sema::ConditionResult(); + } + case ConditionOrInitStatement::ConditionDecl: case ConditionOrInitStatement::Error: break; @@ -2817,13 +2837,22 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { if (Tok.isNot(tok::r_paren)) { CommaLocsTy CommaLocs; if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] { - ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), - DeclaratorInfo).get(); - Actions.CodeCompleteConstructor(getCurScope(), - TypeRep.get()->getCanonicalTypeInternal(), - DeclaratorInfo.getLocEnd(), - ConstructorArgs); - })) { + ParsedType TypeRep = + Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + CalledSignatureHelp = true; + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + })) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + ParsedType TypeRep = + Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); + Actions.ProduceConstructorSignatureHelp( + getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + CalledSignatureHelp = true; + } SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); return ExprError(); } diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 0cd550bc6a47d..7742a5087cf01 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -209,7 +209,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { // send) or send to 'super', parse this as a message send // expression. We handle C++ and C separately, since C++ requires // much more complicated parsing. - if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus) { + if (getLangOpts().ObjC && getLangOpts().CPlusPlus) { // Send to 'super'. if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && NextToken().isNot(tok::period) && @@ -242,7 +242,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { // adopt the expression for further analysis below. // FIXME: potentially-potentially evaluated expression above? Idx = ExprResult(static_cast<Expr*>(TypeOrExpr)); - } else if (getLangOpts().ObjC1 && Tok.is(tok::identifier)) { + } else if (getLangOpts().ObjC && Tok.is(tok::identifier)) { IdentifierInfo *II = Tok.getIdentifierInfo(); SourceLocation IILoc = Tok.getLocation(); ParsedType ReceiverType; @@ -312,7 +312,7 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { // tokens are '...' or ']' or an objc message send. If this is an objc // message send, handle it now. An objc-message send is the start of // an assignment-expression production. - if (getLangOpts().ObjC1 && Tok.isNot(tok::ellipsis) && + if (getLangOpts().ObjC && Tok.isNot(tok::ellipsis) && Tok.isNot(tok::r_square)) { CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig); return ParseAssignmentExprWithObjCMessageExprStart( diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 99e5edb9d4a3e..bd55f71793995 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -178,8 +178,7 @@ void Parser::CheckNestedObjCContexts(SourceLocation AtLoc) Diag(AtLoc, diag::err_objc_missing_end) << FixItHint::CreateInsertion(AtLoc, "@end\n"); if (Decl) - Diag(Decl->getLocStart(), diag::note_objc_container_start) - << (int) ock; + Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock; } /// @@ -264,7 +263,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, categoryId = Tok.getIdentifierInfo(); categoryLoc = ConsumeToken(); } - else if (!getLangOpts().ObjC2) { + else if (!getLangOpts().ObjC) { Diag(Tok, diag::err_expected) << tok::identifier; // missing category name. return nullptr; @@ -384,12 +383,12 @@ static void addContextSensitiveTypeNullability(Parser &P, if (D.getNumTypeObjects() > 0) { // Add the attribute to the declarator chunk nearest the declarator. - D.getTypeObject(0).getAttrs().addAtStart( + D.getTypeObject(0).getAttrs().addAtEnd( getNullabilityAttr(D.getAttributePool())); } else if (!addedToDeclSpec) { // Otherwise, just put it on the declaration specifiers (if one // isn't there already). - D.getMutableDeclSpec().getAttributes().addAtStart( + D.getMutableDeclSpec().getAttributes().addAtEnd( getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool())); addedToDeclSpec = true; } @@ -690,8 +689,8 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, case tok::objc_interface: Diag(AtLoc, diag::err_objc_missing_end) << FixItHint::CreateInsertion(AtLoc, "@end\n"); - Diag(CDecl->getLocStart(), diag::note_objc_container_start) - << (int) Actions.getObjCContainerKind(); + Diag(CDecl->getBeginLoc(), diag::note_objc_container_start) + << (int)Actions.getObjCContainerKind(); ConsumeToken(); break; @@ -706,7 +705,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, break; case tok::objc_property: - if (!getLangOpts().ObjC2) + if (!getLangOpts().ObjC) Diag(AtLoc, diag::err_objc_properties_require_objc2); ObjCDeclSpec OCDS; @@ -776,8 +775,8 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, } else { Diag(Tok, diag::err_objc_missing_end) << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n"); - Diag(CDecl->getLocStart(), diag::note_objc_container_start) - << (int) Actions.getObjCContainerKind(); + Diag(CDecl->getBeginLoc(), diag::note_objc_container_start) + << (int)Actions.getObjCContainerKind(); AtEnd.setBegin(Tok.getLocation()); AtEnd.setEnd(Tok.getLocation()); } @@ -1104,7 +1103,7 @@ bool Parser::isTokIdentifier_in() const { // FIXME: May have to do additional look-ahead to only allow for // valid tokens following an 'in'; such as an identifier, unary operators, // '[' etc. - return (getLangOpts().ObjC2 && Tok.is(tok::identifier) && + return (getLangOpts().ObjC && Tok.is(tok::identifier) && Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]); } @@ -1198,7 +1197,7 @@ static void takeDeclAttributes(ParsedAttributesView &attrs, for (auto &AL : llvm::reverse(from)) { if (!AL.isUsedAsTypeAttr()) { from.remove(&AL); - attrs.addAtStart(&AL); + attrs.addAtEnd(&AL); } } } @@ -1338,7 +1337,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist before the method, parse them. ParsedAttributes methodAttrs(AttrFactory); - if (getLangOpts().ObjC2) + if (getLangOpts().ObjC) MaybeParseGNUAttributes(methodAttrs); MaybeParseCXX11Attributes(methodAttrs); @@ -1365,7 +1364,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; if (Tok.isNot(tok::colon)) { // If attributes exist after the method, parse them. - if (getLangOpts().ObjC2) + if (getLangOpts().ObjC) MaybeParseGNUAttributes(methodAttrs); MaybeParseCXX11Attributes(methodAttrs); @@ -1401,7 +1400,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist before the argument name, parse them. // Regardless, collect all the attributes we've parsed so far. - if (getLangOpts().ObjC2) + if (getLangOpts().ObjC) MaybeParseGNUAttributes(paramAttrs); MaybeParseCXX11Attributes(paramAttrs); ArgInfo.ArgAttrs = paramAttrs; @@ -1485,7 +1484,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // FIXME: Add support for optional parameter list... // If attributes exist after the method, parse them. - if (getLangOpts().ObjC2) + if (getLangOpts().ObjC) MaybeParseGNUAttributes(methodAttrs); MaybeParseCXX11Attributes(methodAttrs); @@ -1551,7 +1550,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) { assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'"); - assert(getLangOpts().ObjC1 && "Protocol qualifiers only exist in Objective-C"); + assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C"); SourceLocation lAngleLoc; SmallVector<Decl *, 8> protocols; @@ -2223,7 +2222,7 @@ Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { if (P.isEofOrEom()) { P.Diag(P.Tok, diag::err_objc_missing_end) << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n"); - P.Diag(Dcl->getLocStart(), diag::note_objc_container_start) + P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start) << Sema::OCK_Implementation; } } @@ -2742,7 +2741,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Res); + return Actions.ActOnExprStmt(Res, isExprValueDiscarded()); } ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { @@ -2946,14 +2945,14 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { /// This routine will only return true for a subset of valid message-send /// expressions. bool Parser::isSimpleObjCMessageExpression() { - assert(Tok.is(tok::l_square) && getLangOpts().ObjC1 && + assert(Tok.is(tok::l_square) && getLangOpts().ObjC && "Incorrect start for isSimpleObjCMessageExpression"); return GetLookAheadToken(1).is(tok::identifier) && GetLookAheadToken(2).is(tok::identifier); } bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { - if (!getLangOpts().ObjC1 || !NextToken().is(tok::identifier) || + if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) || InMessageExpression) return false; diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index a413e96a91e7c..dd2a8aae9f2fb 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -314,7 +314,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); ExprResult CombinerResult = Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), - D->getLocation(), /*DiscardedValue=*/true); + D->getLocation(), /*DiscardedValue*/ false); Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && @@ -353,12 +353,18 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { // Check if initializer is omp_priv <init_expr> or something else. if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("omp_priv")) { - ConsumeToken(); - ParseOpenMPReductionInitializerForDecl(OmpPrivParm); + if (Actions.getLangOpts().CPlusPlus) { + InitializerResult = Actions.ActOnFinishFullExpr( + ParseAssignmentExpression().get(), D->getLocation(), + /*DiscardedValue*/ false); + } else { + ConsumeToken(); + ParseOpenMPReductionInitializerForDecl(OmpPrivParm); + } } else { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue=*/true); + /*DiscardedValue*/ false); } Actions.ActOnOpenMPDeclareReductionInitializerEnd( D, InitializerResult.get(), OmpPrivParm); @@ -415,11 +421,22 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { ExprVector Exprs; CommaLocsTy CommaLocs; - if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] { - Actions.CodeCompleteConstructor( - getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), - OmpPrivParm->getLocation(), Exprs); - })) { + SourceLocation LParLoc = T.getOpenLocation(); + if (ParseExpressionList( + Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] { + QualType PreferredType = Actions.ProduceConstructorSignatureHelp( + getCurScope(), + OmpPrivParm->getType()->getCanonicalTypeInternal(), + OmpPrivParm->getLocation(), Exprs, LParLoc); + CalledSignatureHelp = true; + Actions.CodeCompleteExpression(getCurScope(), PreferredType); + })) { + if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { + Actions.ProduceConstructorSignatureHelp( + getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), + OmpPrivParm->getLocation(), Exprs, LParLoc); + CalledSignatureHelp = true; + } Actions.ActOnInitializerError(OmpPrivParm); SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { @@ -478,7 +495,7 @@ public: Sema &Actions = P.getActions(); // Allow 'this' within late-parsed attributes. - ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0, + ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), ND && ND->isCXXInstanceMember()); // If the Decl is templatized, add template parameters to scope. @@ -627,6 +644,60 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, LinModifiers, Steps, SourceRange(Loc, EndLoc)); } +Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { + // OpenMP 4.5 syntax with list of entities. + Sema::NamedDeclSetType SameDirectiveDecls; + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; + if (Tok.is(tok::identifier)) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + StringRef ClauseName = II->getName(); + // Parse 'to|link' clauses. + if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) { + Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName; + break; + } + ConsumeToken(); + } + auto &&Callback = [this, MT, &SameDirectiveDecls]( + CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { + Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, + SameDirectiveDecls); + }; + if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, + /*AllowScopeSpecifier=*/true)) + break; + + // Consume optional ','. + if (Tok.is(tok::comma)) + ConsumeToken(); + } + SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); + ConsumeAnyToken(); + SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), + SameDirectiveDecls.end()); + if (Decls.empty()) + return DeclGroupPtrTy(); + return Actions.BuildDeclaratorGroup(Decls); +} + +void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, + SourceLocation DTLoc) { + if (DKind != OMPD_end_declare_target) { + Diag(Tok, diag::err_expected_end_declare_target); + Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; + return; + } + ConsumeAnyToken(); + if (Tok.isNot(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::warn_omp_extra_tokens_at_eol) + << getOpenMPDirectiveName(OMPD_end_declare_target); + SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); + } + // Skip the last annot_pragma_openmp_end. + ConsumeAnyToken(); +} + /// Parsing of declarative OpenMP directives. /// /// threadprivate-directive: @@ -642,6 +713,10 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, /// annot_pragma_openmp_end /// <function declaration/definition> /// +/// requires directive: +/// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] +/// annot_pragma_openmp_end +/// Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, DeclSpec::TST TagType, Decl *Tag) { @@ -670,6 +745,46 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } break; } + case OMPD_requires: { + SourceLocation StartLoc = ConsumeToken(); + SmallVector<OMPClause *, 5> Clauses; + SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> + FirstClauses(OMPC_unknown + 1); + if (Tok.is(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::err_omp_expected_clause) + << getOpenMPDirectiveName(OMPD_requires); + break; + } + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + OpenMPClauseKind CKind = Tok.isAnnotation() + ? OMPC_unknown + : getOpenMPClauseKind(PP.getSpelling(Tok)); + Actions.StartOpenMPClause(CKind); + OMPClause *Clause = + ParseOpenMPClause(OMPD_requires, CKind, !FirstClauses[CKind].getInt()); + SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, StopBeforeMatch); + FirstClauses[CKind].setInt(true); + if (Clause != nullptr) + Clauses.push_back(Clause); + if (Tok.is(tok::annot_pragma_openmp_end)) { + Actions.EndOpenMPClause(); + break; + } + // Skip ',' if any. + if (Tok.is(tok::comma)) + ConsumeToken(); + Actions.EndOpenMPClause(); + } + // Consume final annot_pragma_openmp_end + if (Clauses.size() == 0) { + Diag(Tok, diag::err_omp_expected_clause) + << getOpenMPDirectiveName(OMPD_requires); + ConsumeAnnotationToken(); + return nullptr; + } + ConsumeAnnotationToken(); + return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); + } case OMPD_declare_reduction: ConsumeToken(); if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { @@ -724,43 +839,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_declare_target: { SourceLocation DTLoc = ConsumeAnyToken(); if (Tok.isNot(tok::annot_pragma_openmp_end)) { - // OpenMP 4.5 syntax with list of entities. - Sema::NamedDeclSetType SameDirectiveDecls; - while (Tok.isNot(tok::annot_pragma_openmp_end)) { - OMPDeclareTargetDeclAttr::MapTypeTy MT = - OMPDeclareTargetDeclAttr::MT_To; - if (Tok.is(tok::identifier)) { - IdentifierInfo *II = Tok.getIdentifierInfo(); - StringRef ClauseName = II->getName(); - // Parse 'to|link' clauses. - if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, - MT)) { - Diag(Tok, diag::err_omp_declare_target_unexpected_clause) - << ClauseName; - break; - } - ConsumeToken(); - } - auto &&Callback = [this, MT, &SameDirectiveDecls]( - CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { - Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, - SameDirectiveDecls); - }; - if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, - /*AllowScopeSpecifier=*/true)) - break; - - // Consume optional ','. - if (Tok.is(tok::comma)) - ConsumeToken(); - } - SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); - ConsumeAnyToken(); - SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), - SameDirectiveDecls.end()); - if (Decls.empty()) - return DeclGroupPtrTy(); - return Actions.BuildDeclaratorGroup(Decls); + return ParseOMPDeclareTargetClauses(); } // Skip the last annot_pragma_openmp_end. @@ -771,8 +850,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( llvm::SmallVector<Decl *, 4> Decls; DKind = parseOpenMPDirectiveKind(*this); - while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target && - Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) { + while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && + Tok.isNot(tok::r_brace)) { DeclGroupPtrTy Ptr; // Here we expect to see some function declaration. if (AS == AS_none) { @@ -799,19 +878,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } } - if (DKind == OMPD_end_declare_target) { - ConsumeAnyToken(); - if (Tok.isNot(tok::annot_pragma_openmp_end)) { - Diag(Tok, diag::warn_omp_extra_tokens_at_eol) - << getOpenMPDirectiveName(OMPD_end_declare_target); - SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); - } - // Skip the last annot_pragma_openmp_end. - ConsumeAnyToken(); - } else { - Diag(Tok, diag::err_expected_end_declare_target); - Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; - } + ParseOMPEndDeclareTargetDirective(DKind, DTLoc); Actions.ActOnFinishOpenMPDeclareTargetDirective(); return Actions.BuildDeclaratorGroup(Decls); } @@ -1124,6 +1191,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( case OMPD_declare_simd: case OMPD_declare_target: case OMPD_end_declare_target: + case OMPD_requires: Diag(Tok, diag::err_omp_unexpected_directive) << 1 << getOpenMPDirectiveName(DKind); SkipUntil(tok::annot_pragma_openmp_end); @@ -1275,11 +1343,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, break; case OMPC_default: case OMPC_proc_bind: + case OMPC_atomic_default_mem_order: // OpenMP [2.14.3.1, Restrictions] // Only a single default clause may be specified on a parallel, task or // teams directive. // OpenMP [2.5, parallel Construct, Restrictions] // At most one proc_bind clause can appear on the directive. + // OpenMP [5.0, Requires directive, Restrictions] + // At most one atomic_default_mem_order clause can appear + // on the directive if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; @@ -1316,10 +1388,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_threads: case OMPC_simd: case OMPC_nogroup: + case OMPC_unified_address: + case OMPC_unified_shared_memory: + case OMPC_reverse_offload: + case OMPC_dynamic_allocators: // OpenMP [2.7.1, Restrictions, p. 9] // Only one ordered clause can appear on a loop directive. // OpenMP [2.7.1, Restrictions, C/C++, p. 4] // Only one nowait clause can appear on a for directive. + // OpenMP [5.0, Requires directive, Restrictions] + // Each of the requires clauses can appear at most once on the directive. if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; @@ -1377,7 +1455,7 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, ExprResult LHS(ParseCastExpression( /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); - Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); // Parse ')'. RLoc = Tok.getLocation(); @@ -1633,7 +1711,8 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); - Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); + Val = + Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); } // Parse ')'. @@ -1696,6 +1775,79 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, nullptr, nullptr, ReductionId); } +/// Checks if the token is a valid map-type-modifier. +static OpenMPMapModifierKind isMapModifier(Parser &P) { + Token Tok = P.getCurToken(); + if (!Tok.is(tok::identifier)) + return OMPC_MAP_MODIFIER_unknown; + + Preprocessor &PP = P.getPreprocessor(); + OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>( + getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); + return TypeModifier; +} + +/// Parse map-type-modifiers in map clause. +/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) +/// where, map-type-modifier ::= always | close +static void parseMapTypeModifiers(Parser &P, + Parser::OpenMPVarListDataTy &Data) { + Preprocessor &PP = P.getPreprocessor(); + while (P.getCurToken().isNot(tok::colon)) { + Token Tok = P.getCurToken(); + OpenMPMapModifierKind TypeModifier = isMapModifier(P); + if (TypeModifier == OMPC_MAP_MODIFIER_always || + TypeModifier == OMPC_MAP_MODIFIER_close) { + Data.MapTypeModifiers.push_back(TypeModifier); + Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); + P.ConsumeToken(); + } else { + // For the case of unknown map-type-modifier or a map-type. + // Map-type is followed by a colon; the function returns when it + // encounters a token followed by a colon. + if (Tok.is(tok::comma)) { + P.Diag(Tok, diag::err_omp_map_type_modifier_missing); + P.ConsumeToken(); + continue; + } + // Potential map-type token as it is followed by a colon. + if (PP.LookAhead(0).is(tok::colon)) + return; + P.Diag(Tok, diag::err_omp_unknown_map_type_modifier); + P.ConsumeToken(); + } + if (P.getCurToken().is(tok::comma)) + P.ConsumeToken(); + } +} + +/// Checks if the token is a valid map-type. +static OpenMPMapClauseKind isMapType(Parser &P) { + Token Tok = P.getCurToken(); + // The map-type token can be either an identifier or the C++ delete keyword. + if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) + return OMPC_MAP_unknown; + Preprocessor &PP = P.getPreprocessor(); + OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>( + getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); + return MapType; +} + +/// Parse map-type in map clause. +/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) +/// where, map-type ::= to | from | tofrom | alloc | release | delete +static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { + Token Tok = P.getCurToken(); + if (Tok.is(tok::colon)) { + P.Diag(Tok, diag::err_omp_map_type_missing); + return; + } + Data.MapType = isMapType(P); + if (Data.MapType == OMPC_MAP_unknown) + P.Diag(Tok, diag::err_omp_unknown_map_type); + P.ConsumeToken(); +} + /// Parses clauses with list. bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, @@ -1703,7 +1855,6 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPVarListDataTy &Data) { UnqualifiedId UnqualifiedReductionId; bool InvalidReductionId = false; - bool MapTypeModifierSpecified = false; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); @@ -1775,104 +1926,40 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // Handle map type for map clause. ColonProtectionRAIIObject ColonRAII(*this); - /// The map clause modifier token can be either a identifier or the C++ - /// delete keyword. - auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool { - return Tok.isOneOf(tok::identifier, tok::kw_delete); - }; - // The first identifier may be a list item, a map-type or a - // map-type-modifier. The map modifier can also be delete which has the same + // map-type-modifier. The map-type can also be delete which has the same // spelling of the C++ delete keyword. - Data.MapType = - IsMapClauseModifierToken(Tok) - ? static_cast<OpenMPMapClauseKind>( - getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) - : OMPC_MAP_unknown; Data.DepLinMapLoc = Tok.getLocation(); - bool ColonExpected = false; - if (IsMapClauseModifierToken(Tok)) { - if (PP.LookAhead(0).is(tok::colon)) { - if (Data.MapType == OMPC_MAP_unknown) - Diag(Tok, diag::err_omp_unknown_map_type); - else if (Data.MapType == OMPC_MAP_always) - Diag(Tok, diag::err_omp_map_type_missing); - ConsumeToken(); - } else if (PP.LookAhead(0).is(tok::comma)) { - if (IsMapClauseModifierToken(PP.LookAhead(1)) && - PP.LookAhead(2).is(tok::colon)) { - Data.MapTypeModifier = Data.MapType; - if (Data.MapTypeModifier != OMPC_MAP_always) { - Diag(Tok, diag::err_omp_unknown_map_type_modifier); - Data.MapTypeModifier = OMPC_MAP_unknown; - } else { - MapTypeModifierSpecified = true; - } - - ConsumeToken(); - ConsumeToken(); - - Data.MapType = - IsMapClauseModifierToken(Tok) - ? static_cast<OpenMPMapClauseKind>( - getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) - : OMPC_MAP_unknown; - if (Data.MapType == OMPC_MAP_unknown || - Data.MapType == OMPC_MAP_always) - Diag(Tok, diag::err_omp_unknown_map_type); - ConsumeToken(); - } else { - Data.MapType = OMPC_MAP_tofrom; - Data.IsMapTypeImplicit = true; - } - } else if (IsMapClauseModifierToken(PP.LookAhead(0))) { - if (PP.LookAhead(1).is(tok::colon)) { - Data.MapTypeModifier = Data.MapType; - if (Data.MapTypeModifier != OMPC_MAP_always) { - Diag(Tok, diag::err_omp_unknown_map_type_modifier); - Data.MapTypeModifier = OMPC_MAP_unknown; - } else { - MapTypeModifierSpecified = true; - } - - ConsumeToken(); - - Data.MapType = - IsMapClauseModifierToken(Tok) - ? static_cast<OpenMPMapClauseKind>( - getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) - : OMPC_MAP_unknown; - if (Data.MapType == OMPC_MAP_unknown || - Data.MapType == OMPC_MAP_always) - Diag(Tok, diag::err_omp_unknown_map_type); - ConsumeToken(); - } else { - Data.MapType = OMPC_MAP_tofrom; - Data.IsMapTypeImplicit = true; - } - } else { - Data.MapType = OMPC_MAP_tofrom; - Data.IsMapTypeImplicit = true; - } - } else { + // Check for presence of a colon in the map clause. + TentativeParsingAction TPA(*this); + bool ColonPresent = false; + if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch)) { + if (Tok.is(tok::colon)) + ColonPresent = true; + } + TPA.Revert(); + // Only parse map-type-modifier[s] and map-type if a colon is present in + // the map clause. + if (ColonPresent) { + parseMapTypeModifiers(*this, Data); + parseMapType(*this, Data); + } + if (Data.MapType == OMPC_MAP_unknown) { Data.MapType = OMPC_MAP_tofrom; Data.IsMapTypeImplicit = true; } if (Tok.is(tok::colon)) Data.ColonLoc = ConsumeToken(); - else if (ColonExpected) - Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; } bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction && Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || (Kind == OMPC_reduction && !InvalidReductionId) || - (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && - (!MapTypeModifierSpecified || - Data.MapTypeModifier == OMPC_MAP_always)) || + (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) || (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && @@ -1910,7 +1997,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.ColonLoc = Tok.getLocation(); SourceLocation ELoc = ConsumeToken(); ExprResult Tail = ParseAssignmentExpression(); - Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); + Tail = + Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); if (Tail.isUsable()) Data.TailExpr = Tail.get(); else @@ -1957,7 +2045,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, /// depend-clause: /// 'depend' '(' in | out | inout : list | source ')' /// map-clause: -/// 'map' '(' [ [ always , ] +/// 'map' '(' [ [ always [,] ] [ close [,] ] /// to | from | tofrom | alloc | release | delete ':' ] list ')'; /// to-clause: /// 'to' '(' list ')' @@ -1988,7 +2076,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, return Actions.ActOnOpenMPVarListClause( Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc, Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind, - Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit, - Data.DepLinMapLoc); + Data.MapTypeModifiers, Data.MapTypeModifiersLoc, Data.MapType, + Data.IsMapTypeImplicit, Data.DepLinMapLoc); } diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 07f48e0779dc6..380eb64997a71 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -15,10 +15,10 @@ #include "clang/Basic/PragmaKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Parse/LoopHint.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" -#include "clang/Sema/LoopHint.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -106,8 +106,19 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { tok::OnOffSwitch OOS; if (PP.LexOnOffSwitch(OOS)) return; - if (OOS == tok::OOS_ON) + if (OOS == tok::OOS_ON) { PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); + } + + MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1), + 1); + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_fenv_access); + Toks[0].setLocation(Tok.getLocation()); + Toks[0].setAnnotationEndLoc(Tok.getLocation()); + Toks[0].setAnnotationValue(reinterpret_cast<void*>( + static_cast<uintptr_t>(OOS))); + PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); } }; @@ -250,112 +261,122 @@ struct PragmaAttributeHandler : public PragmaHandler { } // end namespace void Parser::initializePragmaHandlers() { - AlignHandler.reset(new PragmaAlignHandler()); + AlignHandler = llvm::make_unique<PragmaAlignHandler>(); PP.AddPragmaHandler(AlignHandler.get()); - GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); + GCCVisibilityHandler = llvm::make_unique<PragmaGCCVisibilityHandler>(); PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); - OptionsHandler.reset(new PragmaOptionsHandler()); + OptionsHandler = llvm::make_unique<PragmaOptionsHandler>(); PP.AddPragmaHandler(OptionsHandler.get()); - PackHandler.reset(new PragmaPackHandler()); + PackHandler = llvm::make_unique<PragmaPackHandler>(); PP.AddPragmaHandler(PackHandler.get()); - MSStructHandler.reset(new PragmaMSStructHandler()); + MSStructHandler = llvm::make_unique<PragmaMSStructHandler>(); PP.AddPragmaHandler(MSStructHandler.get()); - UnusedHandler.reset(new PragmaUnusedHandler()); + UnusedHandler = llvm::make_unique<PragmaUnusedHandler>(); PP.AddPragmaHandler(UnusedHandler.get()); - WeakHandler.reset(new PragmaWeakHandler()); + WeakHandler = llvm::make_unique<PragmaWeakHandler>(); PP.AddPragmaHandler(WeakHandler.get()); - RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); + RedefineExtnameHandler = llvm::make_unique<PragmaRedefineExtnameHandler>(); PP.AddPragmaHandler(RedefineExtnameHandler.get()); - FPContractHandler.reset(new PragmaFPContractHandler()); + FPContractHandler = llvm::make_unique<PragmaFPContractHandler>(); PP.AddPragmaHandler("STDC", FPContractHandler.get()); - STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler()); + STDCFENVHandler = llvm::make_unique<PragmaSTDC_FENV_ACCESSHandler>(); PP.AddPragmaHandler("STDC", STDCFENVHandler.get()); - STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler()); + STDCCXLIMITHandler = llvm::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>(); PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get()); - STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler()); + STDCUnknownHandler = llvm::make_unique<PragmaSTDC_UnknownHandler>(); PP.AddPragmaHandler("STDC", STDCUnknownHandler.get()); - PCSectionHandler.reset(new PragmaClangSectionHandler(Actions)); + PCSectionHandler = llvm::make_unique<PragmaClangSectionHandler>(Actions); PP.AddPragmaHandler("clang", PCSectionHandler.get()); if (getLangOpts().OpenCL) { - OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); + OpenCLExtensionHandler = llvm::make_unique<PragmaOpenCLExtensionHandler>(); PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); } if (getLangOpts().OpenMP) - OpenMPHandler.reset(new PragmaOpenMPHandler()); + OpenMPHandler = llvm::make_unique<PragmaOpenMPHandler>(); else - OpenMPHandler.reset(new PragmaNoOpenMPHandler()); + OpenMPHandler = llvm::make_unique<PragmaNoOpenMPHandler>(); PP.AddPragmaHandler(OpenMPHandler.get()); if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isOSBinFormatELF()) { - MSCommentHandler.reset(new PragmaCommentHandler(Actions)); + MSCommentHandler = llvm::make_unique<PragmaCommentHandler>(Actions); PP.AddPragmaHandler(MSCommentHandler.get()); } if (getLangOpts().MicrosoftExt) { - MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions)); + MSDetectMismatchHandler = + llvm::make_unique<PragmaDetectMismatchHandler>(Actions); PP.AddPragmaHandler(MSDetectMismatchHandler.get()); - MSPointersToMembers.reset(new PragmaMSPointersToMembers()); + MSPointersToMembers = llvm::make_unique<PragmaMSPointersToMembers>(); PP.AddPragmaHandler(MSPointersToMembers.get()); - MSVtorDisp.reset(new PragmaMSVtorDisp()); + MSVtorDisp = llvm::make_unique<PragmaMSVtorDisp>(); PP.AddPragmaHandler(MSVtorDisp.get()); - MSInitSeg.reset(new PragmaMSPragma("init_seg")); + MSInitSeg = llvm::make_unique<PragmaMSPragma>("init_seg"); PP.AddPragmaHandler(MSInitSeg.get()); - MSDataSeg.reset(new PragmaMSPragma("data_seg")); + MSDataSeg = llvm::make_unique<PragmaMSPragma>("data_seg"); PP.AddPragmaHandler(MSDataSeg.get()); - MSBSSSeg.reset(new PragmaMSPragma("bss_seg")); + MSBSSSeg = llvm::make_unique<PragmaMSPragma>("bss_seg"); PP.AddPragmaHandler(MSBSSSeg.get()); - MSConstSeg.reset(new PragmaMSPragma("const_seg")); + MSConstSeg = llvm::make_unique<PragmaMSPragma>("const_seg"); PP.AddPragmaHandler(MSConstSeg.get()); - MSCodeSeg.reset(new PragmaMSPragma("code_seg")); + MSCodeSeg = llvm::make_unique<PragmaMSPragma>("code_seg"); PP.AddPragmaHandler(MSCodeSeg.get()); - MSSection.reset(new PragmaMSPragma("section")); + MSSection = llvm::make_unique<PragmaMSPragma>("section"); PP.AddPragmaHandler(MSSection.get()); - MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler()); + MSRuntimeChecks = llvm::make_unique<PragmaMSRuntimeChecksHandler>(); PP.AddPragmaHandler(MSRuntimeChecks.get()); - MSIntrinsic.reset(new PragmaMSIntrinsicHandler()); + MSIntrinsic = llvm::make_unique<PragmaMSIntrinsicHandler>(); PP.AddPragmaHandler(MSIntrinsic.get()); - MSOptimize.reset(new PragmaMSOptimizeHandler()); + MSOptimize = llvm::make_unique<PragmaMSOptimizeHandler>(); PP.AddPragmaHandler(MSOptimize.get()); } if (getLangOpts().CUDA) { - CUDAForceHostDeviceHandler.reset( - new PragmaForceCUDAHostDeviceHandler(Actions)); + CUDAForceHostDeviceHandler = + llvm::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions); PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get()); } - OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); + OptimizeHandler = llvm::make_unique<PragmaOptimizeHandler>(Actions); PP.AddPragmaHandler("clang", OptimizeHandler.get()); - LoopHintHandler.reset(new PragmaLoopHintHandler()); + LoopHintHandler = llvm::make_unique<PragmaLoopHintHandler>(); PP.AddPragmaHandler("clang", LoopHintHandler.get()); - UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll")); + UnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("unroll"); PP.AddPragmaHandler(UnrollHintHandler.get()); - NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll")); + NoUnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("nounroll"); PP.AddPragmaHandler(NoUnrollHintHandler.get()); - FPHandler.reset(new PragmaFPHandler()); + UnrollAndJamHintHandler = + llvm::make_unique<PragmaUnrollHintHandler>("unroll_and_jam"); + PP.AddPragmaHandler(UnrollAndJamHintHandler.get()); + + NoUnrollAndJamHintHandler = + llvm::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam"); + PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get()); + + FPHandler = llvm::make_unique<PragmaFPHandler>(); PP.AddPragmaHandler("clang", FPHandler.get()); - AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory)); + AttributePragmaHandler = + llvm::make_unique<PragmaAttributeHandler>(AttrFactory); PP.AddPragmaHandler("clang", AttributePragmaHandler.get()); } @@ -451,6 +472,12 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler(NoUnrollHintHandler.get()); NoUnrollHintHandler.reset(); + PP.RemovePragmaHandler(UnrollAndJamHintHandler.get()); + UnrollAndJamHintHandler.reset(); + + PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get()); + NoUnrollAndJamHintHandler.reset(); + PP.RemovePragmaHandler("clang", FPHandler.get()); FPHandler.reset(); @@ -591,6 +618,30 @@ void Parser::HandlePragmaFPContract() { ConsumeAnnotationToken(); } +void Parser::HandlePragmaFEnvAccess() { + assert(Tok.is(tok::annot_pragma_fenv_access)); + tok::OnOffSwitch OOS = + static_cast<tok::OnOffSwitch>( + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); + + LangOptions::FEnvAccessModeKind FPC; + switch (OOS) { + case tok::OOS_ON: + FPC = LangOptions::FEA_On; + break; + case tok::OOS_OFF: + FPC = LangOptions::FEA_Off; + break; + case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense. + FPC = LangOptions::FEA_Off; + break; + } + + Actions.ActOnPragmaFEnvAccess(FPC); + ConsumeAnnotationToken(); +} + + StmtResult Parser::HandlePragmaCaptured() { assert(Tok.is(tok::annot_pragma_captured)); @@ -955,6 +1006,8 @@ static std::string PragmaLoopHintString(Token PragmaName, Token Option) { if (PragmaName.getIdentifierInfo()->getName() == "loop") { PragmaString = "clang loop "; PragmaString += Option.getIdentifierInfo()->getName(); + } else if (PragmaName.getIdentifierInfo()->getName() == "unroll_and_jam") { + PragmaString = "unroll_and_jam"; } else { assert(PragmaName.getIdentifierInfo()->getName() == "unroll" && "Unexpected pragma name"); @@ -986,7 +1039,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { // without an argument. bool PragmaUnroll = PragmaNameInfo->getName() == "unroll"; bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll"; - if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) { + bool PragmaUnrollAndJam = PragmaNameInfo->getName() == "unroll_and_jam"; + bool PragmaNoUnrollAndJam = PragmaNameInfo->getName() == "nounroll_and_jam"; + if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll || PragmaUnrollAndJam || + PragmaNoUnrollAndJam)) { ConsumeAnnotationToken(); Hint.Range = Info->PragmaName.getLocation(); return true; @@ -999,24 +1055,31 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { // If no option is specified the argument is assumed to be a constant expr. bool OptionUnroll = false; + bool OptionUnrollAndJam = false; bool OptionDistribute = false; + bool OptionPipelineDisabled = false; bool StateOption = false; if (OptionInfo) { // Pragma Unroll does not specify an option. OptionUnroll = OptionInfo->isStr("unroll"); + OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam"); OptionDistribute = OptionInfo->isStr("distribute"); + OptionPipelineDisabled = OptionInfo->isStr("pipeline"); StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) .Case("vectorize", true) .Case("interleave", true) .Default(false) || - OptionUnroll || OptionDistribute; + OptionUnroll || OptionUnrollAndJam || OptionDistribute || + OptionPipelineDisabled; } - bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute; + bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam && + !OptionDistribute && !OptionPipelineDisabled; // Verify loop hint has an argument. if (Toks[0].is(tok::eof)) { ConsumeAnnotationToken(); Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) - << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll + << /*StateArgument=*/StateOption + << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam) << /*AssumeSafetyKeyword=*/AssumeSafetyArg; return false; } @@ -1029,14 +1092,19 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { bool Valid = StateInfo && llvm::StringSwitch<bool>(StateInfo->getName()) - .Cases("enable", "disable", true) - .Case("full", OptionUnroll) + .Case("disable", true) + .Case("enable", !OptionPipelineDisabled) + .Case("full", OptionUnroll || OptionUnrollAndJam) .Case("assume_safety", AssumeSafetyArg) .Default(false); if (!Valid) { - Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) - << /*FullKeyword=*/OptionUnroll - << /*AssumeSafetyKeyword=*/AssumeSafetyArg; + if (OptionPipelineDisabled) { + Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword); + } else { + Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) + << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam) + << /*AssumeSafetyKeyword=*/AssumeSafetyArg; + } return false; } if (Toks.size() > 2) @@ -1076,9 +1144,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { namespace { struct PragmaAttributeInfo { - enum ActionType { Push, Pop }; + enum ActionType { Push, Pop, Attribute }; ParsedAttributes &Attributes; ActionType Action; + const IdentifierInfo *Namespace = nullptr; ArrayRef<Token> Tokens; PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {} @@ -1333,12 +1402,20 @@ void Parser::HandlePragmaAttribute() { auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue()); if (Info->Action == PragmaAttributeInfo::Pop) { ConsumeAnnotationToken(); - Actions.ActOnPragmaAttributePop(PragmaLoc); + Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace); return; } // Parse the actual attribute with its arguments. - assert(Info->Action == PragmaAttributeInfo::Push && + assert((Info->Action == PragmaAttributeInfo::Push || + Info->Action == PragmaAttributeInfo::Attribute) && "Unexpected #pragma attribute command"); + + if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) { + ConsumeAnnotationToken(); + Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace); + return; + } + PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false); ConsumeAnnotationToken(); @@ -1485,8 +1562,12 @@ void Parser::HandlePragmaAttribute() { // Consume the eof terminator token. ConsumeToken(); - Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc, - std::move(SubjectMatchRules)); + // Handle a mixed push/attribute by desurging to a push, then an attribute. + if (Info->Action == PragmaAttributeInfo::Push) + Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace); + + Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc, + std::move(SubjectMatchRules)); } // #pragma GCC visibility comes in two variants: @@ -2737,6 +2818,8 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, /// 'vectorize_width' '(' loop-hint-value ')' /// 'interleave_count' '(' loop-hint-value ')' /// 'unroll_count' '(' loop-hint-value ')' +/// 'pipeline' '(' disable ')' +/// 'pipeline_initiation_interval' '(' loop-hint-value ')' /// /// loop-hint-keyword: /// 'enable' @@ -2796,6 +2879,8 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, .Case("vectorize_width", true) .Case("interleave_count", true) .Case("unroll_count", true) + .Case("pipeline", true) + .Case("pipeline_initiation_interval", true) .Default(false); if (!OptionValid) { PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option) @@ -2844,6 +2929,10 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, /// #pragma unroll unroll-hint-value /// #pragma unroll '(' unroll-hint-value ')' /// #pragma nounroll +/// #pragma unroll_and_jam +/// #pragma unroll_and_jam unroll-hint-value +/// #pragma unroll_and_jam '(' unroll-hint-value ')' +/// #pragma nounroll_and_jam /// /// unroll-hint-value: /// constant-expression @@ -2868,9 +2957,10 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, // nounroll or unroll pragma without an argument. Info->PragmaName = PragmaName; Info->Option.startToken(); - } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") { + } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" || + PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") { PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) - << "nounroll"; + << PragmaName.getIdentifierInfo()->getName(); return; } else { // Unroll pragma with an argument: "#pragma unroll N" or @@ -3041,10 +3131,22 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma( /// /// The syntax is: /// \code -/// #pragma clang attribute push(attribute, subject-set) +/// #pragma clang attribute push (attribute, subject-set) +/// #pragma clang attribute push +/// #pragma clang attribute (attribute, subject-set) /// #pragma clang attribute pop /// \endcode /// +/// There are also 'namespace' variants of push and pop directives. The bare +/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a +/// namespace, since it always applies attributes to the most recently pushed +/// group, regardless of namespace. +/// \code +/// #pragma clang attribute namespace.push (attribute, subject-set) +/// #pragma clang attribute namespace.push +/// #pragma clang attribute namespace.pop +/// \endcode +/// /// The subject-set clause defines the set of declarations which receive the /// attribute. Its exact syntax is described in the LanguageExtensions document /// in Clang's documentation. @@ -3060,25 +3162,56 @@ void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, auto *Info = new (PP.getPreprocessorAllocator()) PragmaAttributeInfo(AttributesForPragmaAttribute); - // Parse the 'push' or 'pop'. - if (Tok.isNot(tok::identifier)) { - PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop); - return; + // Parse the optional namespace followed by a period. + if (Tok.is(tok::identifier)) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (!II->isStr("push") && !II->isStr("pop")) { + Info->Namespace = II; + PP.Lex(Tok); + + if (!Tok.is(tok::period)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period) + << II; + return; + } + PP.Lex(Tok); + } } - const auto *II = Tok.getIdentifierInfo(); - if (II->isStr("push")) - Info->Action = PragmaAttributeInfo::Push; - else if (II->isStr("pop")) - Info->Action = PragmaAttributeInfo::Pop; - else { - PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument) - << PP.getSpelling(Tok); + + if (!Tok.isOneOf(tok::identifier, tok::l_paren)) { + PP.Diag(Tok.getLocation(), + diag::err_pragma_attribute_expected_push_pop_paren); return; } - PP.Lex(Tok); + + // Determine what action this pragma clang attribute represents. + if (Tok.is(tok::l_paren)) { + if (Info->Namespace) { + PP.Diag(Tok.getLocation(), + diag::err_pragma_attribute_namespace_on_attribute); + PP.Diag(Tok.getLocation(), + diag::note_pragma_attribute_namespace_on_attribute); + return; + } + Info->Action = PragmaAttributeInfo::Attribute; + } else { + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (II->isStr("push")) + Info->Action = PragmaAttributeInfo::Push; + else if (II->isStr("pop")) + Info->Action = PragmaAttributeInfo::Pop; + else { + PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument) + << PP.getSpelling(Tok); + return; + } + + PP.Lex(Tok); + } // Parse the actual attribute. - if (Info->Action == PragmaAttributeInfo::Push) { + if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) || + Info->Action == PragmaAttributeInfo::Attribute) { if (Tok.isNot(tok::l_paren)) { PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; return; diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index deb10af4b17b7..2974e6a245b0e 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -15,10 +15,10 @@ #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Parse/LoopHint.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/LoopHint.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" using namespace clang; @@ -348,6 +348,11 @@ Retry: ConsumeAnnotationToken(); return StmtError(); + case tok::annot_pragma_fenv_access: + ProhibitAttributes(Attrs); + HandlePragmaFEnvAccess(); + return StmtEmpty(); + case tok::annot_pragma_opencl_extension: ProhibitAttributes(Attrs); HandlePragmaOpenCLExtension(); @@ -434,7 +439,7 @@ StmtResult Parser::ParseExprStatement() { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Expr); + return Actions.ActOnExprStmt(Expr, isExprValueDiscarded()); } /// ParseSEHTryBlockCommon @@ -902,6 +907,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fp: HandlePragmaFP(); break; + case tok::annot_pragma_fenv_access: + HandlePragmaFEnvAccess(); + break; case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); break; @@ -922,6 +930,44 @@ void Parser::ParseCompoundStatementLeadingPragmas() { } +/// Consume any extra semi-colons resulting in null statements, +/// returning true if any tok::semi were consumed. +bool Parser::ConsumeNullStmt(StmtVector &Stmts) { + if (!Tok.is(tok::semi)) + return false; + + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc; + + while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() && + Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) { + EndLoc = Tok.getLocation(); + + // Don't just ConsumeToken() this tok::semi, do store it in AST. + StmtResult R = ParseStatementOrDeclaration(Stmts, ACK_Any); + if (R.isUsable()) + Stmts.push_back(R.get()); + } + + // Did not consume any extra semi. + if (EndLoc.isInvalid()) + return false; + + Diag(StartLoc, diag::warn_null_statement) + << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); + return true; +} + +bool Parser::isExprValueDiscarded() { + if (Actions.isCurCompoundStmtAStmtExpr()) { + // Look to see if the next two tokens close the statement expression; + // if so, this expression statement is the last statement in a + // statment expression. + return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren); + } + return true; +} + /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope @@ -984,6 +1030,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { continue; } + if (ConsumeNullStmt(Stmts)) + continue; + StmtResult R; if (Tok.isNot(tok::kw___extension__)) { R = ParseStatementOrDeclaration(Stmts, ACK_Any); @@ -1023,7 +1072,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - R = Actions.ActOnExprStmt(Res); + R = Actions.ActOnExprStmt(Res, isExprValueDiscarded()); } } @@ -1534,7 +1583,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { } bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus || - getLangOpts().ObjC1; + getLangOpts().ObjC; // C99 6.8.5p5 - In C99, the for statement is a block. This is not // the case for C90. Start the loop scope. @@ -1562,11 +1611,11 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ExprResult Value; - bool ForEach = false, ForRange = false; + bool ForEach = false; StmtResult FirstPart; Sema::ConditionResult SecondPart; ExprResult Collection; - ForRangeInit ForRangeInit; + ForRangeInfo ForRangeInfo; FullExprArg ThirdPart(Actions); if (Tok.is(tok::code_completion)) { @@ -1580,10 +1629,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); + SourceLocation EmptyInitStmtSemiLoc; + // Parse the first part of the for specifier. if (Tok.is(tok::semi)) { // for (; ProhibitAttributes(attrs); // no first part, eat the ';'. + SourceLocation SemiLoc = Tok.getLocation(); + if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID()) + EmptyInitStmtSemiLoc = SemiLoc; ConsumeToken(); } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) && isForRangeIdentifier()) { @@ -1592,20 +1646,19 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { SourceLocation Loc = ConsumeToken(); MaybeParseCXX11Attributes(attrs); - ForRangeInit.ColonLoc = ConsumeToken(); + ForRangeInfo.ColonLoc = ConsumeToken(); if (Tok.is(tok::l_brace)) - ForRangeInit.RangeExpr = ParseBraceInitializer(); + ForRangeInfo.RangeExpr = ParseBraceInitializer(); else - ForRangeInit.RangeExpr = ParseExpression(); + ForRangeInfo.RangeExpr = ParseExpression(); Diag(Loc, diag::err_for_range_identifier) << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17) ? FixItHint::CreateInsertion(Loc, "auto &&") : FixItHint()); - FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, - attrs, attrs.Range.getEnd()); - ForRange = true; + ForRangeInfo.LoopVar = Actions.ActOnCXXForRangeIdentifier( + getCurScope(), Loc, Name, attrs, attrs.Range.getEnd()); } else if (isForInitDeclaration()) { // for (int X = 4; ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -1622,13 +1675,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy DG = ParseSimpleDeclaration( DeclaratorContext::ForContext, DeclEnd, attrs, false, - MightBeForRangeStmt ? &ForRangeInit : nullptr); + MightBeForRangeStmt ? &ForRangeInfo : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - if (ForRangeInit.ParsedForRangeDecl()) { - Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ? + if (ForRangeInfo.ParsedForRangeDecl()) { + Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_for_range : diag::ext_for_range); - - ForRange = true; + ForRangeInfo.LoopVar = FirstPart; + FirstPart = StmtResult(); } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); } else if ((ForEach = isTokIdentifier_in())) { @@ -1655,8 +1708,16 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (!Value.isInvalid()) { if (ForEach) FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); - else - FirstPart = Actions.ActOnExprStmt(Value); + else { + // We already know this is not an init-statement within a for loop, so + // if we are parsing a C++11 range-based for loop, we should treat this + // expression statement as being a discarded value expression because + // we will err below. This way we do not warn on an unused expression + // that was an error in the first place, like with: for (expr : expr); + bool IsRangeBasedFor = + getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon); + FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor); + } } if (Tok.is(tok::semi)) { @@ -1691,17 +1752,38 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Parse the second part of the for specifier. getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); - if (!ForEach && !ForRange && !SecondPart.isInvalid()) { + if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() && + !SecondPart.isInvalid()) { // Parse the second part of the for specifier. if (Tok.is(tok::semi)) { // for (...;; // no second part. } else if (Tok.is(tok::r_paren)) { // missing both semicolons. } else { - if (getLangOpts().CPlusPlus) + if (getLangOpts().CPlusPlus) { + // C++2a: We've parsed an init-statement; we might have a + // for-range-declaration next. + bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl(); + ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); SecondPart = - ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean); - else { + ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean, + MightBeForRangeStmt ? &ForRangeInfo : nullptr); + + if (ForRangeInfo.ParsedForRangeDecl()) { + Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc() + : ForRangeInfo.ColonLoc, + getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_for_range_init_stmt + : diag::ext_for_range_init_stmt) + << (FirstPart.get() ? FirstPart.get()->getSourceRange() + : SourceRange()); + if (EmptyInitStmtSemiLoc.isValid()) { + Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement) + << /*for-loop*/ 2 + << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc); + } + } + } else { ExprResult SecondExpr = ParseExpression(); if (SecondExpr.isInvalid()) SecondPart = Sema::ConditionError(); @@ -1711,7 +1793,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { Sema::ConditionKind::Boolean); } } + } + // Parse the third part of the for statement. + if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) { if (Tok.isNot(tok::semi)) { if (!SecondPart.isInvalid()) Diag(Tok, diag::err_expected_semi_for); @@ -1724,7 +1809,6 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ConsumeToken(); } - // Parse the third part of the for specifier. if (Tok.isNot(tok::r_paren)) { // for (...;...;) ExprResult Third = ParseExpression(); // FIXME: The C++11 standard doesn't actually say that this is a @@ -1737,7 +1821,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // C++ Coroutines [stmt.iter]: // 'co_await' can only be used for a range-based for statement. - if (CoawaitLoc.isValid() && !ForRange) { + if (CoawaitLoc.isValid() && !ForRangeInfo.ParsedForRangeDecl()) { Diag(CoawaitLoc, diag::err_for_co_await_not_range_for); CoawaitLoc = SourceLocation(); } @@ -1748,12 +1832,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { StmtResult ForRangeStmt; StmtResult ForEachStmt; - if (ForRange) { + if (ForRangeInfo.ParsedForRangeDecl()) { ExprResult CorrectedRange = - Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); + Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); ForRangeStmt = Actions.ActOnCXXForRangeStmt( getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), - ForRangeInit.ColonLoc, CorrectedRange.get(), + ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range @@ -1808,7 +1892,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), Body.get()); - if (ForRange) + if (ForRangeInfo.ParsedForRangeDecl()) return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), @@ -1897,10 +1981,11 @@ StmtResult Parser::ParseReturnStatement() { if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) { R = ParseInitializer(); if (R.isUsable()) - Diag(R.get()->getLocStart(), getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_generalized_initializer_lists : - diag::ext_generalized_initializer_lists) - << R.get()->getSourceRange(); + Diag(R.get()->getBeginLoc(), + getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_generalized_initializer_lists + : diag::ext_generalized_initializer_lists) + << R.get()->getSourceRange(); } else R = ParseExpression(); if (R.isInvalid()) { diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 063f7ccea320a..e0a7cc6e856db 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -425,7 +425,9 @@ bool Parser::isStartOfTemplateTypeParameter() { } } - if (Tok.isNot(tok::kw_typename)) + // 'typedef' is a reasonably-common typo/thinko for 'typename', and is + // ill-formed otherwise. + if (Tok.isNot(tok::kw_typename) && Tok.isNot(tok::kw_typedef)) return false; // C++ [temp.param]p2: @@ -448,6 +450,13 @@ bool Parser::isStartOfTemplateTypeParameter() { case tok::ellipsis: return true; + case tok::kw_typename: + case tok::kw_typedef: + case tok::kw_class: + // These indicate that a comma was missed after a type parameter, not that + // we have found a non-type parameter. + return true; + default: return false; } @@ -469,26 +478,25 @@ bool Parser::isStartOfTemplateTypeParameter() { /// 'template' '<' template-parameter-list '>' 'class' identifier[opt] /// = id-expression NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) { - if (isStartOfTemplateTypeParameter()) - return ParseTypeParameter(Depth, Position); - - if (Tok.is(tok::kw_template)) - return ParseTemplateTemplateParameter(Depth, Position); + if (isStartOfTemplateTypeParameter()) { + // Is there just a typo in the input code? ('typedef' instead of 'typename') + if (Tok.is(tok::kw_typedef)) { + Diag(Tok.getLocation(), diag::err_expected_template_parameter); - // Is there just a typo in the input code? ('typedef' instead of 'typename') - if (Tok.is(tok::kw_typedef)) { - Diag(Tok.getLocation(), diag::err_expected_template_parameter); - - Diag(Tok.getLocation(), diag::note_meant_to_use_typename) - << FixItHint::CreateReplacement(CharSourceRange::getCharRange( - Tok.getLocation(), Tok.getEndLoc()), - "typename"); + Diag(Tok.getLocation(), diag::note_meant_to_use_typename) + << FixItHint::CreateReplacement(CharSourceRange::getCharRange( + Tok.getLocation(), Tok.getEndLoc()), + "typename"); - Tok.setKind(tok::kw_typename); + Tok.setKind(tok::kw_typename); + } return ParseTypeParameter(Depth, Position); } + if (Tok.is(tok::kw_template)) + return ParseTemplateTemplateParameter(Depth, Position); + // If it's none of the above, then it must be a parameter declaration. // NOTE: This will pick up errors in the closure of the template parameter // list (e.g., template < ; Check here to implement >> style closures. @@ -938,7 +946,9 @@ Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, bool Invalid = false; { GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); - if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) + if (!Tok.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater, tok::greaterequal, + tok::greatergreaterequal)) Invalid = ParseTemplateArgumentList(TemplateArgs); if (Invalid) { @@ -1371,26 +1381,37 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { SmallVector<ParseScope*, 4> TemplateParamScopeStack; - // Get the list of DeclContexts to reenter. - SmallVector<DeclContext*, 4> DeclContextsToReenter; + // Get the list of DeclContexts to reenter. For inline methods, we only want + // to push the DeclContext of the outermost class. This matches the way the + // parser normally parses bodies of inline methods when the outermost class is + // complete. + struct ContainingDC { + ContainingDC(DeclContext *DC, bool ShouldPush) : Pair(DC, ShouldPush) {} + llvm::PointerIntPair<DeclContext *, 1, bool> Pair; + DeclContext *getDC() { return Pair.getPointer(); } + bool shouldPushDC() { return Pair.getInt(); } + }; + SmallVector<ContainingDC, 4> DeclContextsToReenter; DeclContext *DD = FunD; + DeclContext *NextContaining = Actions.getContainingDC(DD); while (DD && !DD->isTranslationUnit()) { - DeclContextsToReenter.push_back(DD); + bool ShouldPush = DD == NextContaining; + DeclContextsToReenter.push_back({DD, ShouldPush}); + if (ShouldPush) + NextContaining = Actions.getContainingDC(DD); DD = DD->getLexicalParent(); } // Reenter template scopes from outermost to innermost. - SmallVectorImpl<DeclContext *>::reverse_iterator II = - DeclContextsToReenter.rbegin(); - for (; II != DeclContextsToReenter.rend(); ++II) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope)); - unsigned NumParamLists = - Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II)); + for (ContainingDC CDC : reverse(DeclContextsToReenter)) { + TemplateParamScopeStack.push_back( + new ParseScope(this, Scope::TemplateParamScope)); + unsigned NumParamLists = Actions.ActOnReenterTemplateScope( + getCurScope(), cast<Decl>(CDC.getDC())); CurTemplateDepthTracker.addDepth(NumParamLists); - if (*II != FunD) { + if (CDC.shouldPushDC()) { TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); - Actions.PushDeclContext(Actions.getCurScope(), *II); + Actions.PushDeclContext(Actions.getCurScope(), CDC.getDC()); } } diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index dfd1f8c3b2e68..de39e0675fdb8 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -159,7 +159,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { ConsumeToken(); break; } - // Fall through. + LLVM_FALLTHROUGH; case tok::kw_typeof: case tok::kw___attribute: case tok::kw___underlying_type: { @@ -219,11 +219,11 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { case tok::annot_cxxscope: ConsumeAnnotationToken(); - // Fall through. + LLVM_FALLTHROUGH; default: ConsumeAnyToken(); - if (getLangOpts().ObjC1 && Tok.is(tok::less)) + if (getLangOpts().ObjC && Tok.is(tok::less)) return TryParseProtocolQualifiers(); break; } @@ -345,22 +345,55 @@ struct Parser::ConditionDeclarationOrInitStatementState { bool CanBeExpression = true; bool CanBeCondition = true; bool CanBeInitStatement; + bool CanBeForRangeDecl; + + ConditionDeclarationOrInitStatementState(Parser &P, bool CanBeInitStatement, + bool CanBeForRangeDecl) + : P(P), CanBeInitStatement(CanBeInitStatement), + CanBeForRangeDecl(CanBeForRangeDecl) {} - ConditionDeclarationOrInitStatementState(Parser &P, bool CanBeInitStatement) - : P(P), CanBeInitStatement(CanBeInitStatement) {} + bool resolved() { + return CanBeExpression + CanBeCondition + CanBeInitStatement + + CanBeForRangeDecl < 2; + } void markNotExpression() { CanBeExpression = false; - if (CanBeCondition && CanBeInitStatement) { + if (!resolved()) { // FIXME: Unify the parsing codepaths for condition variables and // simple-declarations so that we don't need to eagerly figure out which // kind we have here. (Just parse init-declarators until we reach a // semicolon or right paren.) RevertingTentativeParsingAction PA(P); - P.SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch); + if (CanBeForRangeDecl) { + // Skip until we hit a ')', ';', or a ':' with no matching '?'. + // The final case is a for range declaration, the rest are not. + while (true) { + unsigned QuestionColonDepth = 0; + P.SkipUntil({tok::r_paren, tok::semi, tok::question, tok::colon}, + StopBeforeMatch); + if (P.Tok.is(tok::question)) + ++QuestionColonDepth; + else if (P.Tok.is(tok::colon)) { + if (QuestionColonDepth) + --QuestionColonDepth; + else { + CanBeCondition = CanBeInitStatement = false; + return; + } + } else { + CanBeForRangeDecl = false; + break; + } + P.ConsumeToken(); + } + } else { + // Just skip until we hit a ')' or ';'. + P.SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch); + } if (P.Tok.isNot(tok::r_paren)) - CanBeCondition = false; + CanBeCondition = CanBeForRangeDecl = false; if (P.Tok.isNot(tok::semi)) CanBeInitStatement = false; } @@ -368,28 +401,36 @@ struct Parser::ConditionDeclarationOrInitStatementState { bool markNotCondition() { CanBeCondition = false; - return !CanBeInitStatement || !CanBeExpression; + return resolved(); + } + + bool markNotForRangeDecl() { + CanBeForRangeDecl = false; + return resolved(); } bool update(TPResult IsDecl) { switch (IsDecl) { case TPResult::True: markNotExpression(); - return true; + assert(resolved() && "can't continue after tentative parsing bails out"); + break; case TPResult::False: - CanBeCondition = CanBeInitStatement = false; - return true; + CanBeCondition = CanBeInitStatement = CanBeForRangeDecl = false; + break; case TPResult::Ambiguous: - return false; + break; case TPResult::Error: - CanBeExpression = CanBeCondition = CanBeInitStatement = false; - return true; + CanBeExpression = CanBeCondition = CanBeInitStatement = + CanBeForRangeDecl = false; + break; } - llvm_unreachable("unknown tentative parse result"); + return resolved(); } ConditionOrInitStatement result() const { - assert(CanBeExpression + CanBeCondition + CanBeInitStatement < 2 && + assert(CanBeExpression + CanBeCondition + CanBeInitStatement + + CanBeForRangeDecl < 2 && "result called but not yet resolved"); if (CanBeExpression) return ConditionOrInitStatement::Expression; @@ -397,6 +438,8 @@ struct Parser::ConditionDeclarationOrInitStatementState { return ConditionOrInitStatement::ConditionDecl; if (CanBeInitStatement) return ConditionOrInitStatement::InitStmtDecl; + if (CanBeForRangeDecl) + return ConditionOrInitStatement::ForRangeDecl; return ConditionOrInitStatement::Error; } }; @@ -419,8 +462,10 @@ struct Parser::ConditionDeclarationOrInitStatementState { /// to the ';' to disambiguate cases like 'int(x))' (an expression) from /// 'int(x);' (a simple-declaration in an init-statement). Parser::ConditionOrInitStatement -Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) { - ConditionDeclarationOrInitStatementState State(*this, CanBeInitStatement); +Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement, + bool CanBeForRangeDecl) { + ConditionDeclarationOrInitStatementState State(*this, CanBeInitStatement, + CanBeForRangeDecl); if (State.update(isCXXDeclarationSpecifier())) return State.result(); @@ -447,11 +492,19 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) { return State.result(); } + // A colon here identifies a for-range declaration. + if (State.CanBeForRangeDecl && Tok.is(tok::colon)) + return ConditionOrInitStatement::ForRangeDecl; + // At this point, it can't be a condition any more, because a condition // must have a brace-or-equal-initializer. if (State.markNotCondition()) return State.result(); + // Likewise, it can't be a for-range declaration any more. + if (State.markNotForRangeDecl()) + return State.result(); + // A parenthesized initializer could be part of an expression or a // simple-declaration. if (Tok.is(tok::l_paren)) { @@ -596,7 +649,7 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate, return CAK_NotAttributeSpecifier; // No tentative parsing if we don't need to look for ']]' or a lambda. - if (!Disambiguate && !getLangOpts().ObjC1) + if (!Disambiguate && !getLangOpts().ObjC) return CAK_AttributeSpecifier; RevertingTentativeParsingAction PA(*this); @@ -605,7 +658,7 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate, ConsumeBracket(); // Outside Obj-C++11, treat anything with a matching ']]' as an attribute. - if (!getLangOpts().ObjC1) { + if (!getLangOpts().ObjC) { ConsumeBracket(); bool IsAttribute = SkipUntil(tok::r_square); @@ -1107,8 +1160,8 @@ public: // Reject any candidate that only resolves to instance members since they // aren't viable as standalone identifiers instead of member references. if (Candidate.isResolved() && !Candidate.isKeyword() && - std::all_of(Candidate.begin(), Candidate.end(), - [](NamedDecl *ND) { return ND->isCXXInstanceMember(); })) + llvm::all_of(Candidate, + [](NamedDecl *ND) { return ND->isCXXInstanceMember(); })) return false; return CorrectionCandidateCallback::ValidateCandidate(Candidate); @@ -1233,7 +1286,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, const Token &Next = NextToken(); // In 'foo bar', 'foo' is always a type name outside of Objective-C. - if (!getLangOpts().ObjC1 && Next.is(tok::identifier)) + if (!getLangOpts().ObjC && Next.is(tok::identifier)) return TPResult::True; if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) { @@ -1299,8 +1352,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, if (Next.isOneOf(tok::kw_new, // ::new tok::kw_delete)) // ::delete return TPResult::False; + LLVM_FALLTHROUGH; } - // Fall through. case tok::kw___super: case tok::kw_decltype: // Annotate typenames and C++ scope specifiers. If we get one, just @@ -1506,7 +1559,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::annot_typename: case_typename: // In Objective-C, we might have a protocol-qualified type. - if (getLangOpts().ObjC1 && NextToken().is(tok::less)) { + if (getLangOpts().ObjC && NextToken().is(tok::less)) { // Tentatively parse the protocol qualifiers. RevertingTentativeParsingAction PA(*this); ConsumeAnyToken(); // The type token diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index c3085654f5299..a93db799f8fe2 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -341,7 +341,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { case tok::semi: if (HasFlagsSet(Flags, StopAtSemi)) return false; - // FALL THROUGH. + LLVM_FALLTHROUGH; default: // Skip this token. ConsumeAnyToken(); @@ -443,7 +443,7 @@ void Parser::Initialize() { // Initialization for Objective-C context sensitive keywords recognition. // Referenced in Parser::ParseObjCTypeQualifierList. - if (getLangOpts().ObjC1) { + if (getLangOpts().ObjC) { ObjCTypeQuals[objc_in] = &PP.getIdentifierTable().get("in"); ObjCTypeQuals[objc_out] = &PP.getIdentifierTable().get("out"); ObjCTypeQuals[objc_inout] = &PP.getIdentifierTable().get("inout"); @@ -674,6 +674,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); return nullptr; + case tok::annot_pragma_fenv_access: + HandlePragmaFEnvAccess(); + return nullptr; case tok::annot_pragma_fp: HandlePragmaFP(); break; @@ -744,7 +747,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return ParseObjCAtDirectives(attrs); case tok::minus: case tok::plus: - if (!getLangOpts().ObjC1) { + if (!getLangOpts().ObjC) { Diag(Tok, diag::err_expected_external_declaration); ConsumeToken(); return nullptr; @@ -975,7 +978,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, // ObjC2 allows prefix attributes on class interfaces and protocols. // FIXME: This still needs better diagnostics. We should only accept // attributes here, no types, etc. - if (getLangOpts().ObjC2 && Tok.is(tok::at)) { + if (getLangOpts().ObjC && Tok.is(tok::at)) { SourceLocation AtLoc = ConsumeToken(); // the "@" if (!Tok.isObjCAtKeyword(tok::objc_interface) && !Tok.isObjCAtKeyword(tok::objc_protocol)) { @@ -1519,7 +1522,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, // Look up and classify the identifier. We don't perform any typo-correction // after a scope specifier, because in general we can't recover from typos - // there (eg, after correcting 'A::tempalte B<X>::C' [sic], we would need to + // there (eg, after correcting 'A::template B<X>::C' [sic], we would need to // jump back into scope specifier parsing). Sema::NameClassification Classification = Actions.ClassifyName( getCurScope(), SS, Name, NameLoc, Next, IsAddressOfOperand, @@ -1551,7 +1554,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, /// An Objective-C object type followed by '<' is a specialization of /// a parameterized class type or a protocol-qualified type. ParsedType Ty = Classification.getType(); - if (getLangOpts().ObjC1 && NextToken().is(tok::less) && + if (getLangOpts().ObjC && NextToken().is(tok::less) && (Ty.get()->isObjCObjectType() || Ty.get()->isObjCObjectPointerType())) { // Consume the name. @@ -1591,7 +1594,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, AnnotateScopeToken(SS, !WasScopeAnnotation); return ANK_TemplateName; } - // Fall through. + LLVM_FALLTHROUGH; case Sema::NC_VarTemplate: case Sema::NC_FunctionTemplate: { // We have a type, variable or function template followed by '<'. @@ -1778,7 +1781,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, /// An Objective-C object type followed by '<' is a specialization of /// a parameterized class type or a protocol-qualified type. - if (getLangOpts().ObjC1 && NextToken().is(tok::less) && + if (getLangOpts().ObjC && NextToken().is(tok::less) && (Ty.get()->isObjCObjectType() || Ty.get()->isObjCObjectPointerType())) { // Consume the name. @@ -1964,6 +1967,10 @@ void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro, ArgumentIndex); } +void Parser::CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) { + Actions.CodeCompleteIncludedFile(Dir, IsAngled); +} + void Parser::CodeCompleteNaturalLanguage() { Actions.CodeCompleteNaturalLanguage(); } |
