diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
9 files changed, 216 insertions, 86 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index ea67a52..ab1f97d 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -27,7 +27,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, - ExprResult& Init) { + SourceLocation PureSpecLoc) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) && "Current token not a '{', ':', '=', or 'try'!"); @@ -47,12 +47,8 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, VS, ICIS_NoInit); if (FnD) { Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs); - bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType(); - if (Init.isUsable()) - Actions.AddInitializerToDecl(FnD, Init.get(), false, - TypeSpecContainsAuto); - else - Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto); + if (PureSpecLoc.isValid()) + Actions.ActOnPureSpecifier(FnD, PureSpecLoc); } } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 1c52552..d843e80 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -691,9 +691,9 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { // Treat these like attributes, even though they're type specifiers. while (true) { switch (Tok.getKind()) { - case tok::kw___nonnull: - case tok::kw___nullable: - case tok::kw___null_unspecified: { + case tok::kw__Nonnull: + case tok::kw__Nullable: + case tok::kw__Null_unspecified: { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); if (!getLangOpts().ObjC1) @@ -2173,7 +2173,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, } // Issue diagnostic and remove constexpr specfier if present. - if (DS.isConstexprSpecified()) { + if (DS.isConstexprSpecified() && DSC != DSC_condition) { Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr); DS.ClearConstexprSpec(); } @@ -3076,9 +3076,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; // Nullability type specifiers. - case tok::kw___nonnull: - case tok::kw___nullable: - case tok::kw___null_unspecified: + case tok::kw__Nonnull: + case tok::kw__Nullable: + case tok::kw__Null_unspecified: ParseNullabilityTypeSpecifiers(DS.getAttributes()); continue; @@ -3192,6 +3192,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID); break; + // concept + case tok::kw_concept: + isInvalid = DS.SetConceptSpec(Loc, PrevSpec, DiagID); + break; + // type-specifier case tok::kw_short: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, @@ -4326,9 +4331,9 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw___pascal: case tok::kw___unaligned: - case tok::kw___nonnull: - case tok::kw___nullable: - case tok::kw___null_unspecified: + case tok::kw__Nonnull: + case tok::kw__Nullable: + case tok::kw__Null_unspecified: case tok::kw___private: case tok::kw___local: @@ -4475,6 +4480,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::annot_decltype: case tok::kw_constexpr: + // C++ Concepts TS - concept + case tok::kw_concept: + // C11 _Atomic case tok::kw__Atomic: return true; @@ -4503,9 +4511,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___pascal: case tok::kw___unaligned: - case tok::kw___nonnull: - case tok::kw___nullable: - case tok::kw___null_unspecified: + case tok::kw__Nonnull: + case tok::kw__Nullable: + case tok::kw__Null_unspecified: case tok::kw___private: case tok::kw___local: @@ -4738,9 +4746,9 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, goto DoneWithTypeQuals; // Nullability type specifiers. - case tok::kw___nonnull: - case tok::kw___nullable: - case tok::kw___null_unspecified: + case tok::kw__Nonnull: + case tok::kw__Nullable: + case tok::kw__Null_unspecified: ParseNullabilityTypeSpecifiers(DS.getAttributes()); continue; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 47778b8..568896d 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -2372,8 +2372,28 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, LateParsedAttrList LateParsedAttrs; SourceLocation EqualLoc; - bool HasInitializer = false; - ExprResult Init; + SourceLocation PureSpecLoc; + + auto TryConsumePureSpecifier = [&] (bool AllowDefinition) { + if (Tok.isNot(tok::equal)) + return false; + + auto &Zero = NextToken(); + SmallString<8> Buffer; + if (Zero.isNot(tok::numeric_constant) || Zero.getLength() != 1 || + PP.getSpelling(Zero, Buffer) != "0") + return false; + + auto &After = GetLookAheadToken(2); + if (!After.isOneOf(tok::semi, tok::comma) && + !(AllowDefinition && + After.isOneOf(tok::l_brace, tok::colon, tok::kw_try))) + return false; + + EqualLoc = ConsumeToken(); + PureSpecLoc = ConsumeToken(); + return true; + }; SmallVector<Decl *, 8> DeclsInGroup; ExprResult BitfieldSize; @@ -2390,16 +2410,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (BitfieldSize.isUnset()) { // MSVC permits pure specifier on inline functions defined at class scope. // Hence check for =0 before checking for function definition. - if (getLangOpts().MicrosoftExt && Tok.is(tok::equal) && - DeclaratorInfo.isFunctionDeclarator() && - NextToken().is(tok::numeric_constant)) { - EqualLoc = ConsumeToken(); - Init = ParseInitializer(); - if (Init.isInvalid()) - SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); - else - HasInitializer = true; - } + if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction()) + TryConsumePureSpecifier(/*AllowDefinition*/ true); FunctionDefinitionKind DefinitionKind = FDK_Declaration; // function-definition: @@ -2453,7 +2465,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, - VS, Init); + VS, PureSpecLoc); if (FunDecl) { for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { @@ -2479,16 +2491,25 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, while (1) { InClassInitStyle HasInClassInit = ICIS_NoInit; - if (Tok.isOneOf(tok::equal, tok::l_brace) && !HasInitializer) { + bool HasStaticInitializer = false; + if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) { if (BitfieldSize.get()) { Diag(Tok, diag::err_bitfield_member_init); SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + } else if (DeclaratorInfo.isDeclarationOfFunction()) { + // It's a pure-specifier. + if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false)) + // Parse it as an expression so that Sema can diagnose it. + HasStaticInitializer = true; + } else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_static && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_typedef && + !DS.isFriendSpecified()) { + // It's a default member initializer. + HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit; } else { - HasInitializer = true; - if (!DeclaratorInfo.isDeclarationOfFunction() && - DeclaratorInfo.getDeclSpec().getStorageClassSpec() - != DeclSpec::SCS_typedef) - HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit; + HasStaticInitializer = true; } } @@ -2528,10 +2549,20 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); } - // Handle the initializer. + // Error recovery might have converted a non-static member into a static + // member. if (HasInClassInit != ICIS_NoInit && - DeclaratorInfo.getDeclSpec().getStorageClassSpec() != - DeclSpec::SCS_static) { + DeclaratorInfo.getDeclSpec().getStorageClassSpec() == + DeclSpec::SCS_static) { + HasInClassInit = ICIS_NoInit; + HasStaticInitializer = true; + } + + if (ThisDecl && PureSpecLoc.isValid()) + Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc); + + // Handle the initializer. + if (HasInClassInit != ICIS_NoInit) { // The initializer was deferred; parse it and cache the tokens. Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_nonstatic_member_init @@ -2551,11 +2582,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ThisDecl->setInvalidDecl(); } else ParseCXXNonStaticMemberInitializer(ThisDecl); - } else if (HasInitializer) { + } else if (HasStaticInitializer) { // Normal initializer. - if (!Init.isUsable()) - Init = ParseCXXMemberInitializer( - ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); + ExprResult Init = ParseCXXMemberInitializer( + ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); if (Init.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); @@ -2608,8 +2638,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DeclaratorInfo.clear(); VS.clear(); BitfieldSize = ExprResult(/*Invalid=*/false); - Init = ExprResult(/*Invalid=*/false); - HasInitializer = false; + EqualLoc = PureSpecLoc = SourceLocation(); DeclaratorInfo.setCommaLoc(CommaLoc); // GNU attributes are allowed before the second and subsequent declarator. @@ -2632,13 +2661,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); } -/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or -/// pure-specifier. Also detect and reject any attempted defaulted/deleted -/// function definition. The location of the '=', if any, will be placed in -/// EqualLoc. +/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer. +/// Also detect and reject any attempted defaulted/deleted function definition. +/// The location of the '=', if any, will be placed in EqualLoc. /// -/// pure-specifier: -/// '= 0' +/// This does not check for a pure-specifier; that's handled elsewhere. /// /// brace-or-equal-initializer: /// '=' initializer-expression @@ -2742,6 +2769,11 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); T.skipToEnd(); + + // Parse and discard any trailing attributes. + ParsedAttributes Attrs(AttrFactory); + if (Tok.is(tok::kw___attribute)) + MaybeParseGNUAttributes(Attrs); } /// ParseCXXMemberSpecification - Parse the class definition. @@ -3317,13 +3349,16 @@ Parser::tryParseExceptionSpecification(bool Delayed, T.consumeOpen(); NoexceptType = EST_ComputedNoexcept; NoexceptExpr = ParseConstantExpression(); + T.consumeClose(); // The argument must be contextually convertible to bool. We use // ActOnBooleanCondition for this purpose. - if (!NoexceptExpr.isInvalid()) + if (!NoexceptExpr.isInvalid()) { NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc, NoexceptExpr.get()); - T.consumeClose(); - NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); + NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); + } else { + NoexceptType = EST_None; + } } else { // There is no argument. NoexceptType = EST_BasicNoexcept; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index da759c7..b866798 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -205,6 +205,24 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { return Actions.ActOnConstantExpression(Res); } +/// \brief Parse a constraint-expression. +/// +/// \verbatim +/// constraint-expression: [Concepts TS 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 + ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false)); + ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); + + return Res; +} + bool Parser::isNotExpressionStart() { tok::TokenKind K = Tok.getKind(); if (K == tok::l_brace || K == tok::r_brace || @@ -1042,6 +1060,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression // unary-expression: 'sizeof' '(' type-name ')' case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression + // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')' + case tok::kw___builtin_omp_required_simd_align: return ParseUnaryExprOrTypeTraitExpression(); case tok::ampamp: { // unary-expression: '&&' identifier SourceLocation AmpAmpLoc = ConsumeToken(); @@ -1636,8 +1656,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, ParsedType &CastTy, SourceRange &CastRange) { - assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof, - tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step) && + assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof, + tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step, + tok::kw___builtin_omp_required_simd_align) && "Not a typeof/sizeof/alignof/vec_step expression!"); ExprResult Operand; @@ -1722,7 +1743,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, /// \endverbatim ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, - tok::kw__Alignof, tok::kw_vec_step) && + tok::kw__Alignof, tok::kw_vec_step, + tok::kw___builtin_omp_required_simd_align) && "Not a sizeof/alignof/vec_step expression!"); Token OpTok = Tok; ConsumeToken(); @@ -1792,6 +1814,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { ExprKind = UETT_AlignOf; else if (OpTok.is(tok::kw_vec_step)) ExprKind = UETT_VecStep; + else if (OpTok.is(tok::kw___builtin_omp_required_simd_align)) + ExprKind = UETT_OpenMPRequiredSimdAlign; if (isCastExpr) return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 7fb4b5e..02176c4 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -1686,7 +1686,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, // type-specifier-seq DeclSpec DS(AttrFactory); DS.takeAttributesFrom(attrs); - ParseSpecifierQualifierList(DS); + ParseSpecifierQualifierList(DS, AS_none, DSC_condition); // declarator Declarator DeclaratorInfo(DS, Declarator::ConditionContext); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp index e4f7911..f975f87 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -557,14 +557,14 @@ static void diagnoseRedundantPropertyNullability(Parser &P, SourceLocation nullabilityLoc){ if (DS.getNullability() == nullability) { P.Diag(nullabilityLoc, diag::warn_nullability_duplicate) - << static_cast<unsigned>(nullability) << true + << DiagNullabilityKind(nullability, true) << SourceRange(DS.getNullabilityLoc()); return; } P.Diag(nullabilityLoc, diag::err_nullability_conflicting) - << static_cast<unsigned>(nullability) << true - << static_cast<unsigned>(DS.getNullability()) << true + << DiagNullabilityKind(nullability, true) + << DiagNullabilityKind(DS.getNullability(), true) << SourceRange(DS.getNullabilityLoc()); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp index a3c3c5d..0113a31 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp @@ -30,24 +30,39 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd // TODO: add other combined directives in topological order. const OpenMPDirectiveKind F[][3] = { - { OMPD_for, OMPD_simd, OMPD_for_simd }, - { OMPD_parallel, OMPD_for, OMPD_parallel_for }, - { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd }, - { OMPD_parallel, OMPD_sections, OMPD_parallel_sections } - }; + {OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/, + OMPD_cancellation_point}, + {OMPD_for, OMPD_simd, OMPD_for_simd}, + {OMPD_parallel, OMPD_for, OMPD_parallel_for}, + {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, + {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}}; auto Tok = P.getCurToken(); auto DKind = Tok.isAnnotation() ? OMPD_unknown : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + bool TokenMatched = false; for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { - if (DKind == F[i][0]) { + if (!Tok.isAnnotation() && DKind == OMPD_unknown) { + TokenMatched = + (i == 0) && + !P.getPreprocessor().getSpelling(Tok).compare("cancellation"); + } else { + TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown; + } + if (TokenMatched) { Tok = P.getPreprocessor().LookAhead(0); auto SDKind = Tok.isAnnotation() ? OMPD_unknown : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); - if (SDKind == F[i][1]) { + if (!Tok.isAnnotation() && DKind == OMPD_unknown) { + TokenMatched = + (i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point"); + } else { + TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown; + } + if (TokenMatched) { P.ConsumeToken(); DKind = F[i][2]; } @@ -110,6 +125,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_atomic: case OMPD_target: case OMPD_teams: + case OMPD_cancellation_point: + case OMPD_cancel: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -145,6 +162,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; SourceLocation Loc = ConsumeToken(), EndLoc; auto DKind = ParseOpenMPDirectiveKind(*this); + OpenMPDirectiveKind CancelRegion = OMPD_unknown; // Name of critical directive. DeclarationNameInfo DirName; StmtResult Directive = StmtError(); @@ -178,6 +196,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: + case OMPD_cancellation_point: + case OMPD_cancel: if (!StandAloneAllowed) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind); @@ -217,6 +237,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { } T.consumeClose(); } + } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { + CancelRegion = ParseOpenMPDirectiveKind(*this); + if (Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeToken(); } if (isOpenMPLoopDirective(DKind)) @@ -226,13 +250,13 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { ParseScope OMPDirectiveScope(this, ScopeFlags); Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); - Actions.StartOpenMPClauses(); while (Tok.isNot(tok::annot_pragma_openmp_end)) { OpenMPClauseKind CKind = Tok.isAnnotation() ? OMPC_unknown : FlushHasClause ? OMPC_flush : getOpenMPClauseKind(PP.getSpelling(Tok)); + Actions.StartOpenMPClause(CKind); FlushHasClause = false; OMPClause *Clause = ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); @@ -245,8 +269,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { // Skip ',' if any. if (Tok.is(tok::comma)) ConsumeToken(); + Actions.EndOpenMPClause(); } - Actions.EndOpenMPClauses(); // End location of the directive. EndLoc = Tok.getLocation(); // Consume final annot_pragma_openmp_end. @@ -267,7 +291,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { } if (CreateDirective) Directive = Actions.ActOnOpenMPExecutableDirective( - DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc); + DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, + EndLoc); // Exit scope. Actions.EndOpenMPDSABlock(Directive.get()); @@ -453,6 +478,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_copyin: case OMPC_copyprivate: case OMPC_flush: + case OMPC_depend: Clause = ParseOpenMPVarListClause(CKind); break; case OMPC_unknown: @@ -674,6 +700,8 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, /// 'copyprivate' '(' list ')' /// flush-clause: /// 'flush' '(' list ')' +/// depend-clause: +/// 'depend' '(' in | out | inout : list ')' /// OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); @@ -683,6 +711,9 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { CXXScopeSpec ReductionIdScopeSpec; UnqualifiedId ReductionId; bool InvalidReductionId = false; + OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; + SourceLocation DepLoc; + // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, @@ -706,10 +737,30 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { } else { Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; } + } else if (Kind == OMPC_depend) { + // Handle dependency type for depend clause. + ColonProtectionRAIIObject ColonRAII(*this); + DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + DepLoc = Tok.getLocation(); + + if (DepKind == OMPC_DEPEND_unknown) { + SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + } else { + ConsumeToken(); + } + if (Tok.is(tok::colon)) { + ColonLoc = ConsumeToken(); + } else { + Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type"; + } } SmallVector<Expr *, 5> Vars; - bool IsComma = !InvalidReductionId; + bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) || + ((Kind == OMPC_reduction) && !InvalidReductionId) || + ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown); const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { @@ -753,13 +804,16 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { // Parse ')'. T.consumeClose(); - if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId) + if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) || + (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) || + InvalidReductionId) return nullptr; return Actions.ActOnOpenMPVarListClause( Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), ReductionIdScopeSpec, ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) - : DeclarationNameInfo()); + : DeclarationNameInfo(), + DepKind, DepLoc); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index a811678..2a9becb 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -116,7 +116,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, SmallVector<Decl*, 4> TemplateParams; if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(), TemplateParams, LAngleLoc, RAngleLoc)) { - // Skip until the semi-colon or a }. + // Skip until the semi-colon or a '}'. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); TryConsumeToken(tok::semi); return nullptr; @@ -132,6 +132,17 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, if (!TemplateParams.empty()) { isSpecialization = false; ++CurTemplateDepthTracker; + + if (TryConsumeToken(tok::kw_requires)) { + ExprResult ER = + Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression()); + if (!ER.isUsable()) { + // Skip until the semi-colon or a '}'. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + TryConsumeToken(tok::semi); + return nullptr; + } + } } else { LastParamListWasEmpty = true; } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index d63cf24..368cb93 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -632,8 +632,8 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() { // ptr-operator ConsumeToken(); while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict, - tok::kw___nonnull, tok::kw___nullable, - tok::kw___null_unspecified)) + tok::kw__Nonnull, tok::kw__Nullable, + tok::kw__Null_unspecified)) ConsumeToken(); } else { return TPResult::True; @@ -1213,9 +1213,11 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // 'friend' // 'typedef' // 'constexpr' + // 'concept' case tok::kw_friend: case tok::kw_typedef: case tok::kw_constexpr: + case tok::kw_concept: // storage-class-specifier case tok::kw_register: case tok::kw_static: @@ -1276,9 +1278,9 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw___ptr32: case tok::kw___forceinline: case tok::kw___unaligned: - case tok::kw___nonnull: - case tok::kw___nullable: - case tok::kw___null_unspecified: + case tok::kw__Nonnull: + case tok::kw__Nullable: + case tok::kw__Null_unspecified: return TPResult::True; // Borland |