diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 130 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 16 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 39 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 77 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 27 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseOpenMP.cpp | 478 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 136 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 26 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 8 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 47 |
13 files changed, 770 insertions, 227 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index a1abf8269c451..aa314da8e5b40 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -986,7 +986,7 @@ public: // Put back the original tokens. Self.SkipUntil(EndKind, StopAtSemi | StopBeforeMatch); if (Toks.size()) { - auto Buffer = llvm::make_unique<Token[]>(Toks.size()); + auto Buffer = std::make_unique<Token[]>(Toks.size()); std::copy(Toks.begin() + 1, Toks.end(), Buffer.get()); Buffer[Toks.size() - 1] = Self.Tok; Self.PP.EnterTokenStream(std::move(Buffer), Toks.size(), true, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 73b4f50fda460..b248d7582d847 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -86,8 +86,8 @@ static bool isAttributeLateParsed(const IdentifierInfo &II) { } /// Check if the a start and end source location expand to the same macro. -bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc, - SourceLocation EndLoc) { +static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc, + SourceLocation EndLoc) { if (!StartLoc.isMacroID() || !EndLoc.isMacroID()) return false; @@ -335,6 +335,7 @@ unsigned Parser::ParseAttributeArgsCommon( ConsumeParen(); bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName); + bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName); // Interpret "kw_this" as an identifier if the attributed requests it. if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) @@ -346,7 +347,7 @@ unsigned Parser::ParseAttributeArgsCommon( bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) || attributeHasVariadicIdentifierArg(*AttrName); ParsedAttr::Kind AttrKind = - ParsedAttr::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax); // If we don't know how to parse this attribute, but this is the only // token in this argument, assume it's meant to be an identifier. @@ -360,6 +361,7 @@ unsigned Parser::ParseAttributeArgsCommon( ArgExprs.push_back(ParseIdentifierLoc()); } + ParsedType TheParsedType; if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) { // Eat the comma. if (!ArgExprs.empty()) @@ -372,8 +374,17 @@ unsigned Parser::ParseAttributeArgsCommon( Tok.setKind(tok::identifier); ExprResult ArgExpr; - if (Tok.is(tok::identifier) && - attributeHasVariadicIdentifierArg(*AttrName)) { + if (AttributeIsTypeArgAttr) { + TypeResult T = ParseTypeName(); + if (T.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return 0; + } + if (T.isUsable()) + TheParsedType = T.get(); + break; // FIXME: Multiple type arguments are not implemented. + } else if (Tok.is(tok::identifier) && + attributeHasVariadicIdentifierArg(*AttrName)) { ArgExprs.push_back(ParseIdentifierLoc()); } else { bool Uneval = attributeParsedArgsUnevaluated(*AttrName); @@ -397,14 +408,20 @@ unsigned Parser::ParseAttributeArgsCommon( SourceLocation RParen = Tok.getLocation(); if (!ExpectAndConsume(tok::r_paren)) { SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; - Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, - ArgExprs.data(), ArgExprs.size(), Syntax); + + if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) { + Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen), + ScopeName, ScopeLoc, TheParsedType, Syntax); + } else { + Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, + ArgExprs.data(), ArgExprs.size(), Syntax); + } } if (EndLoc) *EndLoc = RParen; - return static_cast<unsigned>(ArgExprs.size()); + return static_cast<unsigned>(ArgExprs.size() + !TheParsedType.get().isNull()); } /// Parse the arguments to a parameterized GNU attribute or @@ -421,7 +438,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); ParsedAttr::Kind AttrKind = - ParsedAttr::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax); if (AttrKind == ParsedAttr::AT_Availability) { ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, @@ -471,7 +488,7 @@ unsigned Parser::ParseClangAttributeArgs( assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); ParsedAttr::Kind AttrKind = - ParsedAttr::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax); switch (AttrKind) { default: @@ -1672,9 +1689,9 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) continue; if (AL.getKind() == ParsedAttr::UnknownAttribute) - Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName(); + Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL; else { - Diag(AL.getLoc(), DiagID) << AL.getName(); + Diag(AL.getLoc(), DiagID) << AL; AL.setInvalid(); } } @@ -1724,9 +1741,10 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, /// [C++11/C11] static_assert-declaration /// others... [FIXME] /// -Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, - SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs) { +Parser::DeclGroupPtrTy +Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributesWithRange &attrs, + SourceLocation *DeclSpecStart) { ParenBraceBracketBalancer BalancerRAIIObj(*this); // Must temporarily exit the objective-c container scope for // parsing c none objective-c decls. @@ -1746,8 +1764,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation InlineLoc = ConsumeToken(); return ParseNamespace(Context, DeclEnd, InlineLoc); } - return ParseSimpleDeclaration(Context, DeclEnd, attrs, - true); + return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr, + DeclSpecStart); case tok::kw_namespace: ProhibitAttributes(attrs); return ParseNamespace(Context, DeclEnd); @@ -1760,7 +1778,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Context, DeclEnd, attrs, true); + return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr, + DeclSpecStart); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -1785,11 +1804,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, /// If FRI is non-null, we might be parsing a for-range-declaration instead /// of a simple-declaration. If we find that we are, we also parse the /// for-range-initializer, and place it here. -Parser::DeclGroupPtrTy -Parser::ParseSimpleDeclaration(DeclaratorContext Context, - SourceLocation &DeclEnd, - ParsedAttributesWithRange &Attrs, - bool RequireSemi, ForRangeInit *FRI) { +/// +/// DeclSpecStart is used when decl-specifiers are parsed before parsing +/// the Declaration. The SourceLocation for this Decl is set to +/// DeclSpecStart if DeclSpecStart is non-null. +Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI, + SourceLocation *DeclSpecStart) { // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); @@ -1819,6 +1841,9 @@ Parser::ParseSimpleDeclaration(DeclaratorContext Context, return Actions.ConvertDeclToDeclGroup(TheDecl); } + if (DeclSpecStart) + DS.SetRangeStart(*DeclSpecStart); + DS.takeAttributesFrom(Attrs); return ParseDeclGroup(DS, Context, &DeclEnd, FRI); } @@ -2075,6 +2100,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, bool IsForRangeLoop = false; if (TryConsumeToken(tok::colon, FRI->ColonLoc)) { IsForRangeLoop = true; + if (getLangOpts().OpenMP) + Actions.startOpenMPCXXRangeFor(); if (Tok.is(tok::l_brace)) FRI->RangeExpr = ParseBraceInitializer(); else @@ -2489,7 +2516,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, // Issue diagnostic and remove constexpr specifier if present. if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) { Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr) - << (DS.getConstexprSpecifier() == CSK_consteval); + << DS.getConstexprSpecifier(); DS.ClearConstexprSpec(); } } @@ -2902,28 +2929,29 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, IdentifierInfo *Name = AfterScope.getIdentifierInfo(); Sema::NameClassification Classification = Actions.ClassifyName( getCurScope(), SS, Name, AfterScope.getLocation(), Next, - /*IsAddressOfOperand=*/false, /*CCC=*/nullptr); + /*CCC=*/nullptr); switch (Classification.getKind()) { case Sema::NC_Error: SkipMalformedDecl(); return true; case Sema::NC_Keyword: - case Sema::NC_NestedNameSpecifier: - llvm_unreachable("typo correction and nested name specifiers not " - "possible here"); + llvm_unreachable("typo correction is not possible here"); case Sema::NC_Type: case Sema::NC_TypeTemplate: + case Sema::NC_UndeclaredNonType: + case Sema::NC_UndeclaredTemplate: // Not a previously-declared non-type entity. MightBeDeclarator = false; break; case Sema::NC_Unknown: - case Sema::NC_Expression: + case Sema::NC_NonType: + case Sema::NC_DependentNonType: + case Sema::NC_ContextIndependentExpr: case Sema::NC_VarTemplate: case Sema::NC_FunctionTemplate: - case Sema::NC_UndeclaredTemplate: // Might be a redeclaration of a prior entity. break; } @@ -3549,6 +3577,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isStorageClass = true; break; case tok::kw__Thread_local: + if (!getLangOpts().C11) + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, Loc, PrevSpec, DiagID); isStorageClass = true; @@ -3599,14 +3629,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } case tok::kw__Noreturn: if (!getLangOpts().C11) - Diag(Loc, diag::ext_c11_noreturn); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID); break; // alignment-specifier case tok::kw__Alignas: if (!getLangOpts().C11) - Diag(Tok, diag::ext_c11_alignment) << Tok.getName(); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); ParseAlignmentSpecifier(DS.getAttributes()); continue; @@ -3626,15 +3656,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID); break; - // constexpr + // constexpr, consteval, constinit specifiers case tok::kw_constexpr: isInvalid = DS.SetConstexprSpec(CSK_constexpr, Loc, PrevSpec, DiagID); break; - - // consteval case tok::kw_consteval: isInvalid = DS.SetConstexprSpec(CSK_consteval, Loc, PrevSpec, DiagID); break; + case tok::kw_constinit: + isInvalid = DS.SetConstexprSpec(CSK_constinit, Loc, PrevSpec, DiagID); + break; // type-specifier case tok::kw_short: @@ -3662,10 +3693,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DiagID); break; case tok::kw__Complex: + if (!getLangOpts().C99) + Diag(Tok, diag::ext_c99_feature) << Tok.getName(); isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec, DiagID); break; case tok::kw__Imaginary: + if (!getLangOpts().C99) + Diag(Tok, diag::ext_c99_feature) << Tok.getName(); isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec, DiagID); break; @@ -3746,6 +3781,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; case tok::kw_bool: case tok::kw__Bool: + if (Tok.is(tok::kw__Bool) && !getLangOpts().C99) + Diag(Tok, diag::ext_c99_feature) << Tok.getName(); + if (Tok.is(tok::kw_bool) && DS.getTypeSpecType() != DeclSpec::TST_unspecified && DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -3889,6 +3927,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If the _Atomic keyword is immediately followed by a left parenthesis, // it is interpreted as a type specifier (with a type name), not as a // type qualifier. + if (!getLangOpts().C11) + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); + if (NextToken().is(tok::l_paren)) { ParseAtomicSpecifier(DS); continue; @@ -4081,7 +4122,7 @@ void Parser::ParseStructDeclaration( /// [OBC] '@' 'defs' '(' class-name ')' /// void Parser::ParseStructUnionBody(SourceLocation RecordLoc, - unsigned TagType, Decl *TagDecl) { + DeclSpec::TST TagType, Decl *TagDecl) { PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, "parsing struct/union body"); assert(!getLangOpts().CPlusPlus && "C++ declarations not supported"); @@ -4131,6 +4172,14 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, continue; } + if (tok::isPragmaAnnotation(Tok.getKind())) { + Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) + << DeclSpec::getSpecifierName( + TagType, Actions.getASTContext().getPrintingPolicy()); + ConsumeAnnotationToken(); + continue; + } + if (!Tok.is(tok::at)) { auto CFieldCallback = [&](ParsingFieldDeclarator &FD) { // Install the declarator into the current TagDecl. @@ -4632,8 +4681,10 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { ExprResult AssignedVal; EnumAvailabilityDiags.emplace_back(*this); + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); if (TryConsumeToken(tok::equal, EqualLoc)) { - AssignedVal = ParseConstantExpression(); + AssignedVal = ParseConstantExpressionInExprEvalContext(); if (AssignedVal.isInvalid()) SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch); } @@ -5038,8 +5089,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::annot_decltype: case tok::kw_constexpr: - // C++20 consteval. + // C++20 consteval and constinit. case tok::kw_consteval: + case tok::kw_constinit: // C11 _Atomic case tok::kw__Atomic: @@ -5286,6 +5338,8 @@ void Parser::ParseTypeQualifierListOpt( case tok::kw__Atomic: if (!AtomicAllowed) goto DoneWithTypeQuals; + if (!getLangOpts().C11) + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID, getLangOpts()); break; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 9c61c4da447aa..b98ce3e662921 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -862,7 +862,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ "Not a static_assert declaration"); if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11) - Diag(Tok, diag::ext_c11_static_assert); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); if (Tok.is(tok::kw_static_assert)) Diag(Tok, diag::warn_cxx98_compat_static_assert); @@ -1313,6 +1313,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::kw_mutable: // struct foo {...} mutable x; case tok::kw_thread_local: // struct foo {...} thread_local x; case tok::kw_constexpr: // struct foo {...} constexpr x; + case tok::kw_consteval: // struct foo {...} consteval x; + case tok::kw_constinit: // struct foo {...} constinit x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, // almost no one actually writes code like this. If we see one of these, @@ -3134,6 +3136,13 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( TagDecl); default: + if (tok::isPragmaAnnotation(Tok.getKind())) { + Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) + << DeclSpec::getSpecifierName(TagType, + Actions.getASTContext().getPrintingPolicy()); + ConsumeAnnotationToken(); + return nullptr; + } return ParseCXXClassMemberDeclaration(AS, AccessAttrs); } } @@ -3907,7 +3916,8 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, IdentifierInfo *ScopeName) { - switch (ParsedAttr::getKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) { + switch ( + ParsedAttr::getParsedKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) { case ParsedAttr::AT_CarriesDependency: case ParsedAttr::AT_Deprecated: case ParsedAttr::AT_FallThrough: @@ -4337,7 +4347,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration( while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { - ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, + ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS); continue; } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 7a0c07bd3b04e..b74a95a3cd4b6 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -228,18 +228,16 @@ ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { /// Parse a constraint-expression. /// /// \verbatim -/// constraint-expression: [Concepts TS temp.constr.decl p1] +/// constraint-expression: C++2a[temp.constr.decl]p1 /// logical-or-expression /// \endverbatim ExprResult Parser::ParseConstraintExpression() { - // FIXME: this may erroneously consume a function-body as the braced - // initializer list of a compound literal - // - // FIXME: this may erroneously consume a parenthesized rvalue reference - // declarator as a parenthesized address-of-label expression + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); - + if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) + return ExprError(); return Res; } @@ -573,7 +571,7 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { } std::unique_ptr<CorrectionCandidateCallback> clone() override { - return llvm::make_unique<CastExpressionIdValidator>(*this); + return std::make_unique<CastExpressionIdValidator>(*this); } private: @@ -840,13 +838,23 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); case tok::annot_primary_expr: - assert(Res.get() == nullptr && "Stray primary-expression annotation?"); Res = getExprAnnotation(Tok); ConsumeAnnotationToken(); if (!Res.isInvalid() && Tok.is(tok::less)) checkPotentialAngleBracket(Res); break; + case tok::annot_non_type: + case tok::annot_non_type_dependent: + case tok::annot_non_type_undeclared: { + CXXScopeSpec SS; + Token Replacement; + Res = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement); + assert(!Res.isUnset() && + "should not perform typo correction on annotation token"); + break; + } + case tok::kw___super: case tok::kw_decltype: // Annotate the token and tail recurse. @@ -1191,7 +1199,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(); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); LLVM_FALLTHROUGH; case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')' case tok::kw___alignof: // unary-expression: '__alignof' unary-expression @@ -1772,12 +1780,12 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { OpKind == tok::arrow ? tok::period : tok::arrow; ExprResult CorrectedLHS(/*Invalid=*/true); if (getLangOpts().CPlusPlus && OrigLHS) { - const bool DiagsAreSuppressed = Diags.getSuppressAllDiagnostics(); - Diags.setSuppressAllDiagnostics(true); + // FIXME: Creating a TentativeAnalysisScope from outside Sema is a + // hack. + Sema::TentativeAnalysisScope Trap(Actions); CorrectedLHS = Actions.ActOnStartCXXMemberReference( getCurScope(), OrigLHS, OpLoc, CorrectedOpKind, ObjectType, MayBePseudoDestructor); - Diags.setSuppressAllDiagnostics(DiagsAreSuppressed); } Expr *Base = LHS.get(); @@ -2733,11 +2741,10 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) { /// \endverbatim ExprResult Parser::ParseGenericSelectionExpression() { assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected"); - SourceLocation KeyLoc = ConsumeToken(); - if (!getLangOpts().C11) - Diag(KeyLoc, diag::ext_c11_generic_selection); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); + SourceLocation KeyLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.expectAndConsume()) return ExprError(); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 85c7e6c6bcdf9..a064e4b175877 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -555,27 +555,66 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } -ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand, +ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, + bool isAddressOfOperand, Token &Replacement) { - SourceLocation TemplateKWLoc; - UnqualifiedId Name; - if (ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/false, - /*AllowConstructorName=*/false, - /*AllowDeductionGuide=*/false, - /*ObjectType=*/nullptr, &TemplateKWLoc, Name)) - return ExprError(); + ExprResult E; + + // We may have already annotated this id-expression. + switch (Tok.getKind()) { + case tok::annot_non_type: { + NamedDecl *ND = getNonTypeAnnotation(Tok); + SourceLocation Loc = ConsumeAnnotationToken(); + E = Actions.ActOnNameClassifiedAsNonType(getCurScope(), SS, ND, Loc, Tok); + break; + } + + case tok::annot_non_type_dependent: { + IdentifierInfo *II = getIdentifierAnnotation(Tok); + SourceLocation Loc = ConsumeAnnotationToken(); + + // This is only the direct operand of an & operator if it is not + // followed by a postfix-expression suffix. + if (isAddressOfOperand && isPostfixExpressionSuffixStart()) + isAddressOfOperand = false; + + E = Actions.ActOnNameClassifiedAsDependentNonType(SS, II, Loc, + isAddressOfOperand); + break; + } - // This is only the direct operand of an & operator if it is not - // followed by a postfix-expression suffix. - if (isAddressOfOperand && isPostfixExpressionSuffixStart()) - isAddressOfOperand = false; + case tok::annot_non_type_undeclared: { + assert(SS.isEmpty() && + "undeclared non-type annotation should be unqualified"); + IdentifierInfo *II = getIdentifierAnnotation(Tok); + SourceLocation Loc = ConsumeAnnotationToken(); + E = Actions.ActOnNameClassifiedAsUndeclaredNonType(II, Loc); + break; + } + + default: + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*AllowDeductionGuide=*/false, + /*ObjectType=*/nullptr, &TemplateKWLoc, Name)) + return ExprError(); + + // This is only the direct operand of an & operator if it is not + // followed by a postfix-expression suffix. + if (isAddressOfOperand && isPostfixExpressionSuffixStart()) + isAddressOfOperand = false; + + E = Actions.ActOnIdExpression( + getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren), + isAddressOfOperand, /*CCC=*/nullptr, /*IsInlineAsmIdentifier=*/false, + &Replacement); + break; + } - ExprResult E = Actions.ActOnIdExpression( - getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren), - isAddressOfOperand, /*CCC=*/nullptr, /*IsInlineAsmIdentifier=*/false, - &Replacement); if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less)) checkPotentialAngleBracket(E); return E; @@ -1214,7 +1253,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( A.getKind() == ParsedAttr::AT_CUDAHost || A.getKind() == ParsedAttr::AT_CUDAGlobal) Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position) - << A.getName()->getName(); + << A.getAttrName()->getName(); }; // FIXME: Consider allowing this as an extension for GCC compatibiblity. diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 7a455484b902f..5ab055130dc2a 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -39,12 +39,14 @@ bool Parser::MayBeDesignationStart() { // cases here, and fall back to tentative parsing if those fail. switch (PP.LookAhead(0).getKind()) { case tok::equal: + case tok::ellipsis: case tok::r_square: // Definitely starts a lambda expression. return false; case tok::amp: case tok::kw_this: + case tok::star: case tok::identifier: // We have to do additional analysis, because these could be the // start of a constant expression or a lambda capture list. @@ -114,6 +116,8 @@ static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, /// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production /// checking to see if the token stream starts with a designator. /// +/// C99: +/// /// designation: /// designator-list '=' /// [GNU] array-designator @@ -131,6 +135,21 @@ static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, /// '[' constant-expression ']' /// [GNU] '[' constant-expression '...' constant-expression ']' /// +/// C++20: +/// +/// designated-initializer-list: +/// designated-initializer-clause +/// designated-initializer-list ',' designated-initializer-clause +/// +/// designated-initializer-clause: +/// designator brace-or-equal-initializer +/// +/// designator: +/// '.' identifier +/// +/// We allow the C99 syntax extensions in C++20, but do not allow the C++20 +/// extension (a braced-init-list after the designator with no '=') in C99. +/// /// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an /// initializer (because it is an expression). We need to consider this case /// when parsing array designators. @@ -363,6 +382,14 @@ ExprResult Parser::ParseInitializerWithPotentialDesignator() { ParseInitializer()); } + // Handle a C++20 braced designated initialization, which results in + // direct-list-initialization of the aggregate element. We allow this as an + // extension from C++11 onwards (when direct-list-initialization was added). + if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus11) { + return Actions.ActOnDesignatedInitializer(Desig, SourceLocation(), false, + ParseBraceInitializer()); + } + // We read some number of designators and found something that isn't an = or // an initializer. If we have exactly one array designator, this // is the GNU 'designation: array-designator' extension. Otherwise, it is a diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 8937a0986c956..42d6221a7333a 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -710,7 +710,6 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, case tok::objc_required: case tok::objc_optional: // This is only valid on protocols. - // FIXME: Should this check for ObjC2 being enabled? if (contextKey != tok::objc_protocol) Diag(AtLoc, diag::err_objc_directive_only_in_protocol); else @@ -718,9 +717,6 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, break; case tok::objc_property: - if (!getLangOpts().ObjC) - Diag(AtLoc, diag::err_objc_properties_require_objc2); - ObjCDeclSpec OCDS; SourceLocation LParenLoc; // Parse property attribute list, if any. diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 52a68f6d6935c..91fe10e667db4 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -17,6 +17,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/UniqueVector.h" using namespace clang; @@ -42,6 +43,8 @@ enum OpenMPDirectiveKindEx { OMPD_teams_distribute_parallel, OMPD_target_teams_distribute_parallel, OMPD_mapper, + OMPD_variant, + OMPD_parallel_master, }; class DeclDirectiveListParserHelper final { @@ -80,6 +83,7 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) { .Case("reduction", OMPD_reduction) .Case("update", OMPD_update) .Case("mapper", OMPD_mapper) + .Case("variant", OMPD_variant) .Default(OMPD_unknown); } @@ -93,6 +97,7 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, {OMPD_declare, OMPD_simd, OMPD_declare_simd}, {OMPD_declare, OMPD_target, OMPD_declare_target}, + {OMPD_declare, OMPD_variant, OMPD_declare_variant}, {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, {OMPD_distribute_parallel_for, OMPD_simd, @@ -131,7 +136,11 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { {OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for}, {OMPD_target_teams_distribute_parallel_for, OMPD_simd, - OMPD_target_teams_distribute_parallel_for_simd}}; + OMPD_target_teams_distribute_parallel_for_simd}, + {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, + {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, + {OMPD_parallel, OMPD_master, OMPD_parallel_master}, + {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}}; enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; Token Tok = P.getCurToken(); unsigned DKind = @@ -752,6 +761,7 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, /*IsReinject*/ true); // Consume the previously pushed token. ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); FNContextRAII FnContext(*this, Ptr); OMPDeclareSimdDeclAttr::BranchStateTy BS = @@ -782,25 +792,386 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, LinModifiers, Steps, SourceRange(Loc, EndLoc)); } +/// Parse optional 'score' '(' <expr> ')' ':'. +static ExprResult parseContextScore(Parser &P) { + ExprResult ScoreExpr; + SmallString<16> Buffer; + StringRef SelectorName = + P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); + OMPDeclareVariantAttr::ScoreType ScoreKind = + OMPDeclareVariantAttr::ScoreUnknown; + (void)OMPDeclareVariantAttr::ConvertStrToScoreType(SelectorName, ScoreKind); + if (ScoreKind == OMPDeclareVariantAttr::ScoreUnknown) + return ScoreExpr; + assert(ScoreKind == OMPDeclareVariantAttr::ScoreSpecified && + "Expected \"score\" clause."); + (void)P.ConsumeToken(); + SourceLocation RLoc; + ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); + // Parse ':' + if (P.getCurToken().is(tok::colon)) + (void)P.ConsumeAnyToken(); + else + P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon) + << "context selector score clause"; + return ScoreExpr; +} + +/// Parse context selector for 'implementation' selector set: +/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> } +/// ')' +static void parseImplementationSelector( + Parser &P, SourceLocation Loc, llvm::StringMap<SourceLocation> &UsedCtx, + llvm::function_ref<void(SourceRange, + const Sema::OpenMPDeclareVariantCtsSelectorData &)> + Callback) { + const Token &Tok = P.getCurToken(); + // Parse inner context selector set name, if any. + if (!Tok.is(tok::identifier)) { + P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) + << "implementation"; + // Skip until either '}', ')', or end of directive. + while (!P.SkipUntil(tok::r_brace, tok::r_paren, + tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) + ; + return; + } + SmallString<16> Buffer; + StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); + auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); + if (!Res.second) { + // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. + // Each trait-selector-name can only be specified once. + P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) + << CtxSelectorName << "implementation"; + P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) + << CtxSelectorName; + } + OMPDeclareVariantAttr::CtxSelectorType CSKind = + OMPDeclareVariantAttr::CtxUnknown; + (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName, + CSKind); + (void)P.ConsumeToken(); + switch (CSKind) { + case OMPDeclareVariantAttr::CtxVendor: { + // Parse '('. + BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); + (void)T.expectAndConsume(diag::err_expected_lparen_after, + CtxSelectorName.data()); + const ExprResult Score = parseContextScore(P); + llvm::UniqueVector<llvm::SmallString<16>> Vendors; + do { + // Parse <vendor>. + StringRef VendorName; + if (Tok.is(tok::identifier)) { + Buffer.clear(); + VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); + (void)P.ConsumeToken(); + if (!VendorName.empty()) + Vendors.insert(VendorName); + } else { + P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) + << "vendor identifier" + << "vendor" + << "implementation"; + } + if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { + P.Diag(Tok, diag::err_expected_punc) + << (VendorName.empty() ? "vendor name" : VendorName); + } + } while (Tok.is(tok::identifier)); + // Parse ')'. + (void)T.consumeClose(); + if (!Vendors.empty()) { + SmallVector<StringRef, 4> ImplVendors(Vendors.size()); + llvm::copy(Vendors, ImplVendors.begin()); + Sema::OpenMPDeclareVariantCtsSelectorData Data( + OMPDeclareVariantAttr::CtxSetImplementation, CSKind, + llvm::makeMutableArrayRef(ImplVendors.begin(), ImplVendors.size()), + Score); + Callback(SourceRange(Loc, Tok.getLocation()), Data); + } + break; + } + case OMPDeclareVariantAttr::CtxUnknown: + P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) + << "implementation"; + // Skip until either '}', ')', or end of directive. + while (!P.SkipUntil(tok::r_brace, tok::r_paren, + tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) + ; + return; + } +} + +/// Parses clauses for 'declare variant' directive. +/// clause: +/// <selector_set_name> '=' '{' <context_selectors> '}' +/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ] +bool Parser::parseOpenMPContextSelectors( + SourceLocation Loc, + llvm::function_ref<void(SourceRange, + const Sema::OpenMPDeclareVariantCtsSelectorData &)> + Callback) { + llvm::StringMap<SourceLocation> UsedCtxSets; + do { + // Parse inner context selector set name. + if (!Tok.is(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector) + << getOpenMPClauseName(OMPC_match); + return true; + } + SmallString<16> Buffer; + StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer); + auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation()); + if (!Res.second) { + // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. + // Each trait-set-selector-name can only be specified once. + Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use) + << CtxSelectorSetName; + Diag(Res.first->getValue(), + diag::note_omp_declare_variant_ctx_set_used_here) + << CtxSelectorSetName; + } + // Parse '='. + (void)ConsumeToken(); + if (Tok.isNot(tok::equal)) { + Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected) + << CtxSelectorSetName; + return true; + } + (void)ConsumeToken(); + // TBD: add parsing of known context selectors. + // Unknown selector - just ignore it completely. + { + // Parse '{'. + BalancedDelimiterTracker TBr(*this, tok::l_brace, + tok::annot_pragma_openmp_end); + if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "=")) + return true; + OMPDeclareVariantAttr::CtxSelectorSetType CSSKind = + OMPDeclareVariantAttr::CtxSetUnknown; + (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType( + CtxSelectorSetName, CSSKind); + llvm::StringMap<SourceLocation> UsedCtx; + do { + switch (CSSKind) { + case OMPDeclareVariantAttr::CtxSetImplementation: + parseImplementationSelector(*this, Loc, UsedCtx, Callback); + break; + case OMPDeclareVariantAttr::CtxSetUnknown: + // Skip until either '}', ')', or end of directive. + while (!SkipUntil(tok::r_brace, tok::r_paren, + tok::annot_pragma_openmp_end, StopBeforeMatch)) + ; + break; + } + const Token PrevTok = Tok; + if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) + Diag(Tok, diag::err_omp_expected_comma_brace) + << (PrevTok.isAnnotation() ? "context selector trait" + : PP.getSpelling(PrevTok)); + } while (Tok.is(tok::identifier)); + // Parse '}'. + (void)TBr.consumeClose(); + } + // Consume ',' + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) + (void)ExpectAndConsume(tok::comma); + } while (Tok.isAnyIdentifier()); + return false; +} + +/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. +void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, + CachedTokens &Toks, + SourceLocation Loc) { + PP.EnterToken(Tok, /*IsReinject*/ true); + PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, + /*IsReinject*/ true); + // Consume the previously pushed token. + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); + + FNContextRAII FnContext(*this, Ptr); + // Parse function declaration id. + SourceLocation RLoc; + // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs + // instead of MemberExprs. + ExprResult AssociatedFunction = + ParseOpenMPParensExpr(getOpenMPDirectiveName(OMPD_declare_variant), RLoc, + /*IsAddressOfOperand=*/true); + if (!AssociatedFunction.isUsable()) { + if (!Tok.is(tok::annot_pragma_openmp_end)) + while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) + ; + // Skip the last annot_pragma_openmp_end. + (void)ConsumeAnnotationToken(); + return; + } + Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = + Actions.checkOpenMPDeclareVariantFunction( + Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation())); + + // Parse 'match'. + OpenMPClauseKind CKind = Tok.isAnnotation() + ? OMPC_unknown + : getOpenMPClauseKind(PP.getSpelling(Tok)); + if (CKind != OMPC_match) { + Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) + << getOpenMPClauseName(OMPC_match); + while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) + ; + // Skip the last annot_pragma_openmp_end. + (void)ConsumeAnnotationToken(); + return; + } + (void)ConsumeToken(); + // Parse '('. + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(OMPC_match))) { + while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) + ; + // Skip the last annot_pragma_openmp_end. + (void)ConsumeAnnotationToken(); + return; + } + + // Parse inner context selectors. + if (!parseOpenMPContextSelectors( + Loc, [this, &DeclVarData]( + SourceRange SR, + const Sema::OpenMPDeclareVariantCtsSelectorData &Data) { + if (DeclVarData.hasValue()) + Actions.ActOnOpenMPDeclareVariantDirective( + DeclVarData.getValue().first, DeclVarData.getValue().second, + SR, Data); + })) { + // Parse ')'. + (void)T.consumeClose(); + // Need to check for extra tokens. + if (Tok.isNot(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::warn_omp_extra_tokens_at_eol) + << getOpenMPDirectiveName(OMPD_declare_variant); + } + } + + // Skip last tokens. + while (Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + // Skip the last annot_pragma_openmp_end. + (void)ConsumeAnnotationToken(); +} + +/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. +/// +/// default-clause: +/// 'default' '(' 'none' | 'shared' ') +/// +/// proc_bind-clause: +/// 'proc_bind' '(' 'master' | 'close' | 'spread' ') +/// +/// device_type-clause: +/// 'device_type' '(' 'host' | 'nohost' | 'any' )' +namespace { + struct SimpleClauseData { + unsigned Type; + SourceLocation Loc; + SourceLocation LOpen; + SourceLocation TypeLoc; + SourceLocation RLoc; + SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, + SourceLocation TypeLoc, SourceLocation RLoc) + : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} + }; +} // anonymous namespace + +static Optional<SimpleClauseData> +parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { + const Token &Tok = P.getCurToken(); + SourceLocation Loc = Tok.getLocation(); + SourceLocation LOpen = P.ConsumeToken(); + // Parse '('. + BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(Kind))) + return llvm::None; + + unsigned Type = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok)); + SourceLocation TypeLoc = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + P.ConsumeAnyToken(); + + // Parse ')'. + SourceLocation RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); + + return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); +} + Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { // OpenMP 4.5 syntax with list of entities. Sema::NamedDeclSetType SameDirectiveDecls; + SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation, + NamedDecl *>, + 4> + DeclareTargetDecls; + OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; + SourceLocation DeviceTypeLoc; 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; + bool IsDeviceTypeClause = + getLangOpts().OpenMP >= 50 && + getOpenMPClauseKind(ClauseName) == OMPC_device_type; + // Parse 'to|link|device_type' clauses. + if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) && + !IsDeviceTypeClause) { + Diag(Tok, diag::err_omp_declare_target_unexpected_clause) + << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0); break; } + // Parse 'device_type' clause and go to next clause if any. + if (IsDeviceTypeClause) { + Optional<SimpleClauseData> DevTypeData = + parseOpenMPSimpleClause(*this, OMPC_device_type); + if (DevTypeData.hasValue()) { + if (DeviceTypeLoc.isValid()) { + // We already saw another device_type clause, diagnose it. + Diag(DevTypeData.getValue().Loc, + diag::warn_omp_more_one_device_type_clause); + } + switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { + case OMPC_DEVICE_TYPE_any: + DT = OMPDeclareTargetDeclAttr::DT_Any; + break; + case OMPC_DEVICE_TYPE_host: + DT = OMPDeclareTargetDeclAttr::DT_Host; + break; + case OMPC_DEVICE_TYPE_nohost: + DT = OMPDeclareTargetDeclAttr::DT_NoHost; + break; + case OMPC_DEVICE_TYPE_unknown: + llvm_unreachable("Unexpected device_type"); + } + DeviceTypeLoc = DevTypeData.getValue().Loc; + } + continue; + } ConsumeToken(); } - auto &&Callback = [this, MT, &SameDirectiveDecls]( - CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { - Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, - SameDirectiveDecls); + auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls]( + CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { + NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName( + getCurScope(), SS, NameInfo, SameDirectiveDecls); + if (ND) + DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND); }; if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, /*AllowScopeSpecifier=*/true)) @@ -812,6 +1183,15 @@ Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { } SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); ConsumeAnyToken(); + for (auto &MTLocDecl : DeclareTargetDecls) { + OMPDeclareTargetDeclAttr::MapTypeTy MT; + SourceLocation Loc; + NamedDecl *ND; + std::tie(MT, Loc, ND) = MTLocDecl; + // device_type clause is applied only to functions. + Actions.ActOnOpenMPDeclareTargetName( + ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT); + } SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), SameDirectiveDecls.end()); if (Decls.empty()) @@ -1005,13 +1385,15 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } break; } + case OMPD_declare_variant: case OMPD_declare_simd: { // The syntax is: - // { #pragma omp declare simd } + // { #pragma omp declare {simd|variant} } // <function-declaration-or-definition> // - ConsumeToken(); CachedTokens Toks; + Toks.push_back(Tok); + ConsumeToken(); while(Tok.isNot(tok::annot_pragma_openmp_end)) { Toks.push_back(Tok); ConsumeAnyToken(); @@ -1035,10 +1417,16 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } } if (!Ptr) { - Diag(Loc, diag::err_omp_decl_in_declare_simd); + Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) + << (DKind == OMPD_declare_simd ? 0 : 1); return DeclGroupPtrTy(); } - return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); + if (DKind == OMPD_declare_simd) + return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); + assert(DKind == OMPD_declare_variant && + "Expected declare variant directive only"); + ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); + return Ptr; } case OMPD_declare_target: { SourceLocation DTLoc = ConsumeAnyToken(); @@ -1120,6 +1508,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_target_parallel_for: case OMPD_taskloop: case OMPD_taskloop_simd: + case OMPD_master_taskloop: + case OMPD_master_taskloop_simd: + case OMPD_parallel_master_taskloop: case OMPD_distribute: case OMPD_end_declare_target: case OMPD_target_update: @@ -1174,20 +1565,17 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | /// 'for simd' | 'parallel for simd' | 'target' | 'target data' | -/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | -/// 'distribute' | 'target enter data' | 'target exit data' | -/// 'target parallel' | 'target parallel for' | -/// 'target update' | 'distribute parallel for' | -/// 'distribute paralle for simd' | 'distribute simd' | -/// 'target parallel for simd' | 'target simd' | -/// 'teams distribute' | 'teams distribute simd' | -/// 'teams distribute parallel for simd' | -/// 'teams distribute parallel for' | 'target teams' | -/// 'target teams distribute' | -/// 'target teams distribute parallel for' | -/// 'target teams distribute parallel for simd' | -/// 'target teams distribute simd' {clause} -/// annot_pragma_openmp_end +/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 'master +/// taskloop' | 'master taskloop simd' | 'parallel master taskloop' | +/// 'distribute' | 'target enter data' | 'target exit data' | 'target +/// parallel' | 'target parallel for' | 'target update' | 'distribute +/// parallel for' | 'distribute paralle for simd' | 'distribute simd' | +/// 'target parallel for simd' | 'target simd' | 'teams distribute' | +/// 'teams distribute simd' | 'teams distribute parallel for simd' | +/// 'teams distribute parallel for' | 'target teams' | 'target teams +/// distribute' | 'target teams distribute parallel for' | 'target teams +/// distribute parallel for simd' | 'target teams distribute simd' +/// {clause} annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { @@ -1362,6 +1750,9 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_target_parallel_for: case OMPD_taskloop: case OMPD_taskloop_simd: + case OMPD_master_taskloop: + case OMPD_master_taskloop_simd: + case OMPD_parallel_master_taskloop: case OMPD_distribute: case OMPD_distribute_parallel_for: case OMPD_distribute_parallel_for_simd: @@ -1474,6 +1865,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_requires: + case OMPD_declare_variant: Diag(Tok, diag::err_omp_unexpected_directive) << 1 << getOpenMPDirectiveName(DKind); SkipUntil(tok::annot_pragma_openmp_end); @@ -1712,6 +2104,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_allocate: Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); break; + case OMPC_device_type: case OMPC_unknown: Diag(Tok, diag::warn_omp_extra_tokens_at_eol) << getOpenMPDirectiveName(DKind); @@ -1719,6 +2112,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, break; case OMPC_threadprivate: case OMPC_uniform: + case OMPC_match: if (!WrongDirective) Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); @@ -1732,14 +2126,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, /// constructs. /// \param RLoc Returned location of right paren. ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, - SourceLocation &RLoc) { + SourceLocation &RLoc, + bool IsAddressOfOperand) { BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) return ExprError(); SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression( - /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); + /*isUnaryExpression=*/false, IsAddressOfOperand, NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); @@ -1811,29 +2206,12 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, /// OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, bool ParseOnly) { - SourceLocation Loc = Tok.getLocation(); - SourceLocation LOpen = ConsumeToken(); - // Parse '('. - BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); - if (T.expectAndConsume(diag::err_expected_lparen_after, - getOpenMPClauseName(Kind))) - return nullptr; - - unsigned Type = getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); - SourceLocation TypeLoc = Tok.getLocation(); - if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && - Tok.isNot(tok::annot_pragma_openmp_end)) - ConsumeAnyToken(); - - // Parse ')'. - SourceLocation RLoc = Tok.getLocation(); - if (!T.consumeClose()) - RLoc = T.getCloseLocation(); - - if (ParseOnly) + llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); + if (!Val || ParseOnly) return nullptr; - return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc); + return Actions.ActOnOpenMPSimpleClause( + Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, + Val.getValue().Loc, Val.getValue().RLoc); } /// Parsing of OpenMP clauses like 'ordered'. diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index f81ecc738c283..cdbf697cf7f1f 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -265,122 +265,122 @@ struct PragmaAttributeHandler : public PragmaHandler { } // end namespace void Parser::initializePragmaHandlers() { - AlignHandler = llvm::make_unique<PragmaAlignHandler>(); + AlignHandler = std::make_unique<PragmaAlignHandler>(); PP.AddPragmaHandler(AlignHandler.get()); - GCCVisibilityHandler = llvm::make_unique<PragmaGCCVisibilityHandler>(); + GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>(); PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); - OptionsHandler = llvm::make_unique<PragmaOptionsHandler>(); + OptionsHandler = std::make_unique<PragmaOptionsHandler>(); PP.AddPragmaHandler(OptionsHandler.get()); - PackHandler = llvm::make_unique<PragmaPackHandler>(); + PackHandler = std::make_unique<PragmaPackHandler>(); PP.AddPragmaHandler(PackHandler.get()); - MSStructHandler = llvm::make_unique<PragmaMSStructHandler>(); + MSStructHandler = std::make_unique<PragmaMSStructHandler>(); PP.AddPragmaHandler(MSStructHandler.get()); - UnusedHandler = llvm::make_unique<PragmaUnusedHandler>(); + UnusedHandler = std::make_unique<PragmaUnusedHandler>(); PP.AddPragmaHandler(UnusedHandler.get()); - WeakHandler = llvm::make_unique<PragmaWeakHandler>(); + WeakHandler = std::make_unique<PragmaWeakHandler>(); PP.AddPragmaHandler(WeakHandler.get()); - RedefineExtnameHandler = llvm::make_unique<PragmaRedefineExtnameHandler>(); + RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>(); PP.AddPragmaHandler(RedefineExtnameHandler.get()); - FPContractHandler = llvm::make_unique<PragmaFPContractHandler>(); + FPContractHandler = std::make_unique<PragmaFPContractHandler>(); PP.AddPragmaHandler("STDC", FPContractHandler.get()); - STDCFENVHandler = llvm::make_unique<PragmaSTDC_FENV_ACCESSHandler>(); + STDCFENVHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>(); PP.AddPragmaHandler("STDC", STDCFENVHandler.get()); - STDCCXLIMITHandler = llvm::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>(); + STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>(); PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get()); - STDCUnknownHandler = llvm::make_unique<PragmaSTDC_UnknownHandler>(); + STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>(); PP.AddPragmaHandler("STDC", STDCUnknownHandler.get()); - PCSectionHandler = llvm::make_unique<PragmaClangSectionHandler>(Actions); + PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions); PP.AddPragmaHandler("clang", PCSectionHandler.get()); if (getLangOpts().OpenCL) { - OpenCLExtensionHandler = llvm::make_unique<PragmaOpenCLExtensionHandler>(); + OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>(); PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); } if (getLangOpts().OpenMP) - OpenMPHandler = llvm::make_unique<PragmaOpenMPHandler>(); + OpenMPHandler = std::make_unique<PragmaOpenMPHandler>(); else - OpenMPHandler = llvm::make_unique<PragmaNoOpenMPHandler>(); + OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>(); PP.AddPragmaHandler(OpenMPHandler.get()); if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isOSBinFormatELF()) { - MSCommentHandler = llvm::make_unique<PragmaCommentHandler>(Actions); + MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions); PP.AddPragmaHandler(MSCommentHandler.get()); } if (getLangOpts().MicrosoftExt) { MSDetectMismatchHandler = - llvm::make_unique<PragmaDetectMismatchHandler>(Actions); + std::make_unique<PragmaDetectMismatchHandler>(Actions); PP.AddPragmaHandler(MSDetectMismatchHandler.get()); - MSPointersToMembers = llvm::make_unique<PragmaMSPointersToMembers>(); + MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>(); PP.AddPragmaHandler(MSPointersToMembers.get()); - MSVtorDisp = llvm::make_unique<PragmaMSVtorDisp>(); + MSVtorDisp = std::make_unique<PragmaMSVtorDisp>(); PP.AddPragmaHandler(MSVtorDisp.get()); - MSInitSeg = llvm::make_unique<PragmaMSPragma>("init_seg"); + MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg"); PP.AddPragmaHandler(MSInitSeg.get()); - MSDataSeg = llvm::make_unique<PragmaMSPragma>("data_seg"); + MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg"); PP.AddPragmaHandler(MSDataSeg.get()); - MSBSSSeg = llvm::make_unique<PragmaMSPragma>("bss_seg"); + MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg"); PP.AddPragmaHandler(MSBSSSeg.get()); - MSConstSeg = llvm::make_unique<PragmaMSPragma>("const_seg"); + MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg"); PP.AddPragmaHandler(MSConstSeg.get()); - MSCodeSeg = llvm::make_unique<PragmaMSPragma>("code_seg"); + MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg"); PP.AddPragmaHandler(MSCodeSeg.get()); - MSSection = llvm::make_unique<PragmaMSPragma>("section"); + MSSection = std::make_unique<PragmaMSPragma>("section"); PP.AddPragmaHandler(MSSection.get()); - MSRuntimeChecks = llvm::make_unique<PragmaMSRuntimeChecksHandler>(); + MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>(); PP.AddPragmaHandler(MSRuntimeChecks.get()); - MSIntrinsic = llvm::make_unique<PragmaMSIntrinsicHandler>(); + MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>(); PP.AddPragmaHandler(MSIntrinsic.get()); - MSOptimize = llvm::make_unique<PragmaMSOptimizeHandler>(); + MSOptimize = std::make_unique<PragmaMSOptimizeHandler>(); PP.AddPragmaHandler(MSOptimize.get()); } if (getLangOpts().CUDA) { CUDAForceHostDeviceHandler = - llvm::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions); + std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions); PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get()); } - OptimizeHandler = llvm::make_unique<PragmaOptimizeHandler>(Actions); + OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions); PP.AddPragmaHandler("clang", OptimizeHandler.get()); - LoopHintHandler = llvm::make_unique<PragmaLoopHintHandler>(); + LoopHintHandler = std::make_unique<PragmaLoopHintHandler>(); PP.AddPragmaHandler("clang", LoopHintHandler.get()); - UnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("unroll"); + UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll"); PP.AddPragmaHandler(UnrollHintHandler.get()); - NoUnrollHintHandler = llvm::make_unique<PragmaUnrollHintHandler>("nounroll"); + NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll"); PP.AddPragmaHandler(NoUnrollHintHandler.get()); UnrollAndJamHintHandler = - llvm::make_unique<PragmaUnrollHintHandler>("unroll_and_jam"); + std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam"); PP.AddPragmaHandler(UnrollAndJamHintHandler.get()); NoUnrollAndJamHintHandler = - llvm::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam"); + std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam"); PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get()); - FPHandler = llvm::make_unique<PragmaFPHandler>(); + FPHandler = std::make_unique<PragmaFPHandler>(); PP.AddPragmaHandler("clang", FPHandler.get()); AttributePragmaHandler = - llvm::make_unique<PragmaAttributeHandler>(AttrFactory); + std::make_unique<PragmaAttributeHandler>(AttrFactory); PP.AddPragmaHandler("clang", AttributePragmaHandler.get()); } @@ -1006,18 +1006,13 @@ struct PragmaLoopHintInfo { } // end anonymous namespace static std::string PragmaLoopHintString(Token PragmaName, Token Option) { - std::string PragmaString; - 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"); - PragmaString = "unroll"; - } - return PragmaString; + StringRef Str = PragmaName.getIdentifierInfo()->getName(); + std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str(); + return llvm::StringSwitch<StringRef>(Str) + .Case("loop", ClangLoopStr) + .Case("unroll_and_jam", Str) + .Case("unroll", Str) + .Default(""); } bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { @@ -1041,12 +1036,12 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { // Return a valid hint if pragma unroll or nounroll were specified // without an argument. - bool PragmaUnroll = PragmaNameInfo->getName() == "unroll"; - bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll"; - bool PragmaUnrollAndJam = PragmaNameInfo->getName() == "unroll_and_jam"; - bool PragmaNoUnrollAndJam = PragmaNameInfo->getName() == "nounroll_and_jam"; - if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll || PragmaUnrollAndJam || - PragmaNoUnrollAndJam)) { + auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName()) + .Cases("unroll", "nounroll", "unroll_and_jam", + "nounroll_and_jam", true) + .Default(false); + + if (Toks.empty() && IsLoopHint) { ConsumeAnnotationToken(); Hint.Range = Info->PragmaName.getLocation(); return true; @@ -1071,6 +1066,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { StateOption = llvm::StringSwitch<bool>(OptionInfo->getName()) .Case("vectorize", true) .Case("interleave", true) + .Case("vectorize_predicate", true) .Default(false) || OptionUnroll || OptionUnrollAndJam || OptionDistribute || OptionPipelineDisabled; @@ -1472,9 +1468,9 @@ void Parser::HandlePragmaAttribute() { if (Tok.getIdentifierInfo()) { // If we suspect that this is an attribute suggest the use of // '__attribute__'. - if (ParsedAttr::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, - ParsedAttr::AS_GNU) != - ParsedAttr::UnknownAttribute) { + if (ParsedAttr::getParsedKind( + Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, + ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) { SourceLocation InsertStartLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::l_paren)) { @@ -1508,7 +1504,7 @@ void Parser::HandlePragmaAttribute() { ParsedAttr &Attribute = *Attrs.begin(); if (!Attribute.isSupportedByPragmaAttribute()) { Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) - << Attribute.getName(); + << Attribute; SkipToEnd(); return; } @@ -1625,7 +1621,7 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, return; } - auto Toks = llvm::make_unique<Token[]>(1); + auto Toks = std::make_unique<Token[]>(1); Toks[0].startToken(); Toks[0].setKind(tok::annot_pragma_vis); Toks[0].setLocation(VisLoc); @@ -1794,7 +1790,7 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, /*IsReinject=*/false); } -// #pragma clang section bss="abc" data="" rodata="def" text="" +// #pragma clang section bss="abc" data="" rodata="def" text="" relro="" void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstToken) { @@ -1816,6 +1812,8 @@ void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP, SecKind = Sema::PragmaClangSectionKind::PCSK_Data; else if (SecType->isStr("rodata")) SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata; + else if (SecType->isStr("relro")) + SecKind = Sema::PragmaClangSectionKind::PCSK_Relro; else if (SecType->isStr("text")) SecKind = Sema::PragmaClangSectionKind::PCSK_Text; else { @@ -2241,7 +2239,7 @@ void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, Tok.setLocation(EodLoc); Pragma.push_back(Tok); - auto Toks = llvm::make_unique<Token[]>(Pragma.size()); + auto Toks = std::make_unique<Token[]>(Pragma.size()); std::copy(Pragma.begin(), Pragma.end(), Toks.get()); PP.EnterTokenStream(std::move(Toks), Pragma.size(), /*DisableMacroExpansion=*/false, /*IsReinject=*/false); @@ -2458,7 +2456,7 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP, TokenVector.push_back(EoF); // We must allocate this array with new because EnterTokenStream is going to // delete it later. - auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size()); + auto TokenArray = std::make_unique<Token[]>(TokenVector.size()); std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get()); auto Value = new (PP.getPreprocessorAllocator()) std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray), @@ -2743,7 +2741,7 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP, return; } - auto TokenArray = llvm::make_unique<Token[]>(TokenList.size()); + auto TokenArray = std::make_unique<Token[]>(TokenList.size()); std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), @@ -2824,6 +2822,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, /// 'vectorize' '(' loop-hint-keyword ')' /// 'interleave' '(' loop-hint-keyword ')' /// 'unroll' '(' unroll-hint-keyword ')' +/// 'vectorize_predicate' '(' loop-hint-keyword ')' /// 'vectorize_width' '(' loop-hint-value ')' /// 'interleave_count' '(' loop-hint-value ')' /// 'unroll_count' '(' loop-hint-value ')' @@ -2885,6 +2884,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, .Case("interleave", true) .Case("unroll", true) .Case("distribute", true) + .Case("vectorize_predicate", true) .Case("vectorize_width", true) .Case("interleave_count", true) .Case("unroll_count", true) @@ -2926,7 +2926,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, return; } - auto TokenArray = llvm::make_unique<Token[]>(TokenList.size()); + auto TokenArray = std::make_unique<Token[]>(TokenList.size()); std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), @@ -2998,7 +2998,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, } // Generate the hint token. - auto TokenArray = llvm::make_unique<Token[]>(1); + auto TokenArray = std::make_unique<Token[]>(1); TokenArray[0].startToken(); TokenArray[0].setKind(tok::annot_pragma_loop_hint); TokenArray[0].setLocation(PragmaName.getLocation()); @@ -3270,7 +3270,7 @@ void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, << "clang attribute"; // Generate the annotated pragma token. - auto TokenArray = llvm::make_unique<Token[]>(1); + auto TokenArray = std::make_unique<Token[]>(1); TokenArray[0].startToken(); TokenArray[0].setKind(tok::annot_pragma_attribute); TokenArray[0].setLocation(FirstToken.getLocation()); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index bf04253ab7fdc..727ab75adae8b 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -140,7 +140,7 @@ public: } std::unique_ptr<CorrectionCandidateCallback> clone() override { - return llvm::make_unique<StatementFilterCCC>(*this); + return std::make_unique<StatementFilterCCC>(*this); } private: @@ -153,6 +153,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { const char *SemiError = nullptr; StmtResult Res; + SourceLocation GNUAttributeLoc; // Cases in this switch statement should fall through if the parser expects // the token to end in a semicolon (in which case SemiError should be set), @@ -186,7 +187,7 @@ Retry: // Try to limit which sets of keywords should be included in typo // correction based on what the next token is. StatementFilterCCC CCC(Next); - if (TryAnnotateName(/*IsAddressOfOperand*/ false, &CCC) == ANK_Error) { + if (TryAnnotateName(&CCC) == ANK_Error) { // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); @@ -208,10 +209,19 @@ Retry: if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != ParsedStmtContext()) && - isDeclarationStatement()) { + (GNUAttributeLoc.isValid() || isDeclarationStatement())) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy Decl = ParseDeclaration(DeclaratorContext::BlockContext, - DeclEnd, Attrs); + DeclGroupPtrTy Decl; + if (GNUAttributeLoc.isValid()) { + DeclStart = GNUAttributeLoc; + Decl = ParseDeclaration(DeclaratorContext::BlockContext, DeclEnd, Attrs, + &GNUAttributeLoc); + } else { + Decl = + ParseDeclaration(DeclaratorContext::BlockContext, DeclEnd, Attrs); + } + if (Attrs.Range.getBegin().isValid()) + DeclStart = Attrs.Range.getBegin(); return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd); } @@ -223,6 +233,12 @@ Retry: return ParseExprStatement(StmtCtx); } + case tok::kw___attribute: { + GNUAttributeLoc = Tok.getLocation(); + ParseGNUAttributes(Attrs); + goto Retry; + } + case tok::kw_case: // C99 6.8.1: labeled-statement return ParseCaseStatement(StmtCtx); case tok::kw_default: // C99 6.8.1: labeled-statement diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 9bb5b6eac37e2..928bc5aa25b35 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -630,11 +630,11 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { } // Grab the template parameter name (if given) - SourceLocation NameLoc; + SourceLocation NameLoc = Tok.getLocation(); IdentifierInfo *ParamName = nullptr; if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); - NameLoc = ConsumeToken(); + ConsumeToken(); } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater, tok::greatergreater)) { // Unnamed template parameter. Don't have to do anything here, just @@ -727,11 +727,11 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { : diag::ext_variadic_templates); // Get the identifier, if given. - SourceLocation NameLoc; + SourceLocation NameLoc = Tok.getLocation(); IdentifierInfo *ParamName = nullptr; if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); - NameLoc = ConsumeToken(); + ConsumeToken(); } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater, tok::greatergreater)) { // Unnamed template parameter. Don't have to do anything here, just diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index a413f9a94148a..e2e16ca63d1eb 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -1193,7 +1193,7 @@ public: } std::unique_ptr<CorrectionCandidateCallback> clone() override { - return llvm::make_unique<TentativeParseCCC>(*this); + return std::make_unique<TentativeParseCCC>(*this); } }; } @@ -1330,7 +1330,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // this is ambiguous. Typo-correct to type and expression keywords and // to types and identifiers, in order to try to recover from errors. TentativeParseCCC CCC(Next); - switch (TryAnnotateName(false /* no nested name specifier */, &CCC)) { + switch (TryAnnotateName(&CCC)) { case ANK_Error: return TPResult::Error; case ANK_TentativeDecl: @@ -1408,6 +1408,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw_typedef: case tok::kw_constexpr: case tok::kw_consteval: + case tok::kw_constinit: // storage-class-specifier case tok::kw_register: case tok::kw_static: @@ -1568,7 +1569,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, } else { // Try to resolve the name. If it doesn't exist, assume it was // intended to name a type and keep disambiguating. - switch (TryAnnotateName(false /* SS is not dependent */)) { + switch (TryAnnotateName()) { case ANK_Error: return TPResult::Error; case ANK_TentativeDecl: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 9124f1558664d..2645f27e656f7 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -174,7 +174,7 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { return ExpectAndConsume(tok::semi, DiagID); } -void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { +void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, DeclSpec::TST TST) { if (!Tok.is(tok::semi)) return; bool HadMultipleSemis = false; @@ -202,7 +202,7 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis) Diag(StartLoc, diag::ext_extra_semi) - << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST, + << Kind << DeclSpec::getSpecifierName(TST, Actions.getASTContext().getPrintingPolicy()) << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); else @@ -1174,8 +1174,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (Tok.isNot(tok::equal)) { for (const ParsedAttr &AL : D.getAttributes()) if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) - Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) - << AL.getName(); + Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) << AL; } // In delayed template parsing mode, for function template we consume the @@ -1562,13 +1561,10 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { /// with a typo-corrected keyword. This is only appropriate when the current /// name must refer to an entity which has already been declared. /// -/// \param IsAddressOfOperand Must be \c true if the name is preceded by an '&' -/// and might possibly have a dependent nested name specifier. /// \param CCC Indicates how to perform typo-correction for this name. If NULL, /// no typo correction will be performed. Parser::AnnotatedNameKind -Parser::TryAnnotateName(bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC) { +Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) { assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope)); const bool EnteringContext = false; @@ -1604,9 +1600,8 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, // after a scope specifier, because in general we can't recover from typos // 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, SS.isEmpty() ? CCC : nullptr); + Sema::NameClassification Classification = Actions.ClassifyName( + getCurScope(), SS, Name, NameLoc, Next, SS.isEmpty() ? CCC : nullptr); // If name lookup found nothing and we guessed that this was a template name, // double-check before committing to that interpretation. C++20 requires that @@ -1619,7 +1614,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, FakeNext.setKind(tok::unknown); Classification = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, FakeNext, - IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr); + SS.isEmpty() ? CCC : nullptr); } switch (Classification.getKind()) { @@ -1672,7 +1667,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, return ANK_Success; } - case Sema::NC_Expression: + case Sema::NC_ContextIndependentExpr: Tok.setKind(tok::annot_primary_expr); setExprAnnotation(Tok, Classification.getExpression()); Tok.setAnnotationEndLoc(NameLoc); @@ -1681,6 +1676,29 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, PP.AnnotateCachedTokens(Tok); return ANK_Success; + case Sema::NC_NonType: + Tok.setKind(tok::annot_non_type); + setNonTypeAnnotation(Tok, Classification.getNonTypeDecl()); + Tok.setLocation(NameLoc); + Tok.setAnnotationEndLoc(NameLoc); + PP.AnnotateCachedTokens(Tok); + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + return ANK_Success; + + case Sema::NC_UndeclaredNonType: + case Sema::NC_DependentNonType: + Tok.setKind(Classification.getKind() == Sema::NC_UndeclaredNonType + ? tok::annot_non_type_undeclared + : tok::annot_non_type_dependent); + setIdentifierAnnotation(Tok, Name); + Tok.setLocation(NameLoc); + Tok.setAnnotationEndLoc(NameLoc); + PP.AnnotateCachedTokens(Tok); + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + return ANK_Success; + case Sema::NC_TypeTemplate: if (Next.isNot(tok::less)) { // This may be a type template being used as a template template argument. @@ -1702,9 +1720,6 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, return ANK_Error; return ANK_Success; } - - case Sema::NC_NestedNameSpecifier: - llvm_unreachable("already parsed nested name specifier"); } // Unable to classify the name, but maybe we can annotate a scope specifier. |