https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/130146
>From 98df18461bb06afa06b8968b157a3c5a5cf50324 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com> Date: Thu, 6 Mar 2025 08:51:34 -0600 Subject: [PATCH 1/2] [flang][OpenMP] Parse cancel-directive-name as clause The cancellable construct names on CANCEL or CANCELLATION POINT directives are actually clauses (with the same names as the corresponding constructs). Instead of parsing them into a custom structure, parse them as a clause, which will make CANCEL/CANCELLATION POINT follow the same uniform scheme as other constructs (<directive> [(<arguments>)] [clauses]). --- flang/include/flang/Parser/dump-parse-tree.h | 2 +- flang/include/flang/Parser/parse-tree.h | 11 +- flang/lib/Parser/openmp-parsers.cpp | 31 ++++- flang/lib/Parser/unparse.cpp | 5 +- flang/lib/Semantics/check-omp-structure.cpp | 133 +++++++++++++------ flang/lib/Semantics/check-omp-structure.h | 5 +- flang/test/Semantics/OpenMP/cancel.f90 | 29 ++++ llvm/include/llvm/Frontend/OpenMP/OMP.td | 5 + 8 files changed, 169 insertions(+), 52 deletions(-) create mode 100644 flang/test/Semantics/OpenMP/cancel.f90 diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index fcd902d25fa40..004e22a21ecfa 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -546,6 +546,7 @@ class ParseTreeDumper { #define GEN_FLANG_DUMP_PARSE_TREE_CLAUSES #include "llvm/Frontend/OpenMP/OMP.inc" NODE(parser, OmpClauseList) + NODE(parser, OmpCancellationConstructTypeClause) NODE(parser, OmpContainsClause) NODE(parser, OmpCriticalDirective) NODE(parser, OmpErrorDirective) @@ -689,7 +690,6 @@ class ParseTreeDumper { NODE(parser, OpenMPAtomicConstruct) NODE(parser, OpenMPBlockConstruct) NODE(parser, OpenMPCancelConstruct) - NODE(OpenMPCancelConstruct, If) NODE(parser, OpenMPCancellationPointConstruct) NODE(parser, OpenMPConstruct) NODE(parser, OpenMPCriticalConstruct) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index a197249ebae91..cb0eb884e1193 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4048,6 +4048,12 @@ struct OmpBindClause { WRAPPER_CLASS_BOILERPLATE(OmpBindClause, Binding); }; +// Artificial clause to represent a cancellable construct. +struct OmpCancellationConstructTypeClause { + TUPLE_CLASS_BOILERPLATE(OmpCancellationConstructTypeClause); + std::tuple<OmpDirectiveName, std::optional<ScalarLogicalExpr>> t; +}; + // Ref: [5.2:214] // // contains-clause -> @@ -4870,15 +4876,14 @@ struct OmpCancelType { struct OpenMPCancellationPointConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct); CharBlock source; - std::tuple<Verbatim, OmpCancelType> t; + std::tuple<Verbatim, OmpClauseList> t; }; // 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause] struct OpenMPCancelConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct); - WRAPPER_CLASS(If, ScalarLogicalExpr); CharBlock source; - std::tuple<Verbatim, OmpCancelType, std::optional<If>> t; + std::tuple<Verbatim, OmpClauseList> t; }; // Ref: [5.0:254-255], [5.1:287-288], [5.2:322-323] diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 80831db0e7d50..51b2567a3894d 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -803,8 +803,9 @@ TYPE_PARSER(construct<OmpAbsentClause>(many(maybe(","_tok) >> TYPE_PARSER(construct<OmpContainsClause>(many(maybe(","_tok) >> construct<llvm::omp::Directive>(unwrap(OmpDirectiveNameParser{}))))) -TYPE_PARSER("ABSENT" >> construct<OmpClause>(construct<OmpClause::Absent>( - parenthesized(Parser<OmpAbsentClause>{}))) || +TYPE_PARSER( // + "ABSENT" >> construct<OmpClause>(construct<OmpClause::Absent>( + parenthesized(Parser<OmpAbsentClause>{}))) || "ACQUIRE" >> construct<OmpClause>(construct<OmpClause::Acquire>()) || "ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) || "AFFINITY" >> construct<OmpClause>(construct<OmpClause::Affinity>( @@ -981,7 +982,24 @@ TYPE_PARSER("ABSENT" >> construct<OmpClause>(construct<OmpClause::Absent>( "UPDATE" >> construct<OmpClause>(construct<OmpClause::Update>( parenthesized(Parser<OmpUpdateClause>{}))) || "WHEN" >> construct<OmpClause>(construct<OmpClause::When>( - parenthesized(Parser<OmpWhenClause>{})))) + parenthesized(Parser<OmpWhenClause>{}))) || + // Cancellable constructs + construct<OmpClause>(construct<OmpClause::CancellationConstructType>( + construct<OmpCancellationConstructTypeClause>( // + construct<OmpDirectiveName>(verbatim("DO"_id)), + maybe(parenthesized(scalarLogicalExpr))))) || + construct<OmpClause>(construct<OmpClause::CancellationConstructType>( + construct<OmpCancellationConstructTypeClause>( // + construct<OmpDirectiveName>(verbatim("PARALLEL"_id)), + maybe(parenthesized(scalarLogicalExpr))))) || + construct<OmpClause>(construct<OmpClause::CancellationConstructType>( + construct<OmpCancellationConstructTypeClause>( // + construct<OmpDirectiveName>(verbatim("SECTIONS"_id)), + maybe(parenthesized(scalarLogicalExpr))))) || + construct<OmpClause>(construct<OmpClause::CancellationConstructType>( + construct<OmpCancellationConstructTypeClause>( // + construct<OmpDirectiveName>(verbatim("TASKGROUP"_id)), + maybe(parenthesized(scalarLogicalExpr)))))) // [Clause, [Clause], ...] TYPE_PARSER(sourced(construct<OmpClauseList>( @@ -1104,11 +1122,11 @@ TYPE_PARSER(sourced(construct<OmpCancelType>( // 2.14.2 Cancellation Point construct TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>( - verbatim("CANCELLATION POINT"_tok), Parser<OmpCancelType>{}))) + verbatim("CANCELLATION POINT"_tok), Parser<OmpClauseList>{}))) // 2.14.1 Cancel construct TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok), - Parser<OmpCancelType>{}, maybe("IF" >> parenthesized(scalarLogicalExpr))))) + Parser<OmpClauseList>{}))) TYPE_PARSER(sourced(construct<OmpFailClause>( parenthesized(indirect(Parser<OmpMemoryOrderClause>{}))))) @@ -1192,9 +1210,10 @@ TYPE_PARSER( sourced(construct<OpenMPStandaloneConstruct>( Parser<OpenMPSimpleStandaloneConstruct>{}) || construct<OpenMPStandaloneConstruct>(Parser<OpenMPFlushConstruct>{}) || - construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) || + // Try CANCELLATION POINT before CANCEL. construct<OpenMPStandaloneConstruct>( Parser<OpenMPCancellationPointConstruct>{}) || + construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) || construct<OpenMPStandaloneConstruct>( Parser<OmpMetadirectiveDirective>{}) || construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) / diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 12d86653a2b95..11ce214450d96 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2851,15 +2851,14 @@ class UnparseVisitor { void Unparse(const OpenMPCancellationPointConstruct &x) { BeginOpenMP(); Word("!$OMP CANCELLATION POINT "); - Walk(std::get<OmpCancelType>(x.t)); + Walk(std::get<OmpClauseList>(x.t)); Put("\n"); EndOpenMP(); } void Unparse(const OpenMPCancelConstruct &x) { BeginOpenMP(); Word("!$OMP CANCEL "); - Walk(std::get<OmpCancelType>(x.t)); - Walk(std::get<std::optional<OpenMPCancelConstruct::If>>(x.t)); + Walk(std::get<OmpClauseList>(x.t)); Put("\n"); EndOpenMP(); } diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 64a0be703744d..8d819defb4a0c 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2176,9 +2176,13 @@ void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) { void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) { const auto &dir{std::get<parser::Verbatim>(x.t)}; - const auto &type{std::get<parser::OmpCancelType>(x.t)}; + const auto &clauses{std::get<parser::OmpClauseList>(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_cancel); - CheckCancellationNest(dir.source, type.v); + + if (auto maybeConstruct{GetCancelType( + llvm::omp::Directive::OMPD_cancel, x.source, clauses)}) { + CheckCancellationNest(dir.source, *maybeConstruct); + } } void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) { @@ -2228,13 +2232,38 @@ void OmpStructureChecker::Leave(const parser::OpenMPCriticalConstruct &) { dirContext_.pop_back(); } +void OmpStructureChecker::Enter( + const parser::OmpClause::CancellationConstructType &x) { + // Do not call CheckAllowed/CheckAllowedClause, because in case of an error + // it will print "CANCELLATION_CONSTRUCT_TYPE" as the clause name instead of + // the contained construct name. + auto &dirName{std::get<parser::OmpDirectiveName>(x.v.t)}; + switch (dirName.v) { + case llvm::omp::Directive::OMPD_do: + case llvm::omp::Directive::OMPD_parallel: + case llvm::omp::Directive::OMPD_sections: + case llvm::omp::Directive::OMPD_taskgroup: + break; + default: + context_.Say(dirName.source, + "%s is not a cancellable construct"_err_en_US, + parser::ToUpperCaseLetters( + llvm::omp::getOpenMPDirectiveName(dirName.v).str())); + break; + } +} + void OmpStructureChecker::Enter( const parser::OpenMPCancellationPointConstruct &x) { const auto &dir{std::get<parser::Verbatim>(x.t)}; - const auto &type{std::get<parser::OmpCancelType>(x.t)}; + const auto &clauses{std::get<parser::OmpClauseList>(x.t)}; PushContextAndClauseSets( dir.source, llvm::omp::Directive::OMPD_cancellation_point); - CheckCancellationNest(dir.source, type.v); + + if (auto maybeConstruct{GetCancelType( + llvm::omp::Directive::OMPD_cancellation_point, x.source, clauses)}) { + CheckCancellationNest(dir.source, *maybeConstruct); + } } void OmpStructureChecker::Leave( @@ -2242,8 +2271,42 @@ void OmpStructureChecker::Leave( dirContext_.pop_back(); } +std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType( + llvm::omp::Directive cancelDir, const parser::CharBlock &cancelSource, + const parser::OmpClauseList &clauses) { + // Given clauses from CANCEL or CANCELLATION_POINT, identify the construct + // to which the cancellation applies. + std::optional<llvm::omp::Directive> cancelee; + llvm::StringRef cancelName{llvm::omp::getOpenMPDirectiveName(cancelDir)}; + + for (const parser::OmpClause &clause : clauses.v) { + using CancellationConstructType = + parser::OmpClause::CancellationConstructType; + if (auto *cctype{std::get_if<CancellationConstructType>(&clause.u)}) { + if (cancelee) { + context_.Say(cancelSource, + "Multiple cancel-directive-name clauses are not allowed on the %s construct"_err_en_US, + parser::ToUpperCaseLetters(cancelName.str())); + return std::nullopt; + } + cancelee = std::get<parser::OmpDirectiveName>(cctype->v.t).v; + } + } + + if (!cancelee) { + context_.Say(cancelSource, + "Missing cancel-directive-name clause on the %s construct"_err_en_US, + parser::ToUpperCaseLetters(cancelName.str())); + return std::nullopt; + } + + return cancelee; +} + void OmpStructureChecker::CheckCancellationNest( - const parser::CharBlock &source, const parser::OmpCancelType::Type &type) { + const parser::CharBlock &source, llvm::omp::Directive type) { + llvm::StringRef typeName{llvm::omp::getOpenMPDirectiveName(type)}; + if (CurrentDirectiveIsNested()) { // If construct-type-clause is taskgroup, the cancellation construct must be // closely nested inside a task or a taskloop construct and the cancellation @@ -2254,8 +2317,9 @@ void OmpStructureChecker::CheckCancellationNest( // that matches the type specified in construct-type-clause of the // cancellation construct. bool eligibleCancellation{false}; + switch (type) { - case parser::OmpCancelType::Type::Taskgroup: + case llvm::omp::Directive::OMPD_taskgroup: if (llvm::omp::nestedCancelTaskgroupAllowedSet.test( GetContextParent().directive)) { eligibleCancellation = true; @@ -2281,38 +2345,37 @@ void OmpStructureChecker::CheckCancellationNest( } if (!eligibleCancellation) { context_.Say(source, - "With %s clause, %s construct must be closely nested inside TASK " - "or TASKLOOP construct and %s region must be closely nested inside " - "TASKGROUP region"_err_en_US, - parser::ToUpperCaseLetters( - parser::OmpCancelType::EnumToString(type)), + "With %s clause, %s construct must be closely nested inside TASK or TASKLOOP construct and %s region must be closely nested inside TASKGROUP region"_err_en_US, + parser::ToUpperCaseLetters(typeName.str()), ContextDirectiveAsFortran(), ContextDirectiveAsFortran()); } return; - case parser::OmpCancelType::Type::Sections: + case llvm::omp::Directive::OMPD_sections: if (llvm::omp::nestedCancelSectionsAllowedSet.test( GetContextParent().directive)) { eligibleCancellation = true; } break; - case parser::OmpCancelType::Type::Do: + case llvm::omp::Directive::OMPD_do: if (llvm::omp::nestedCancelDoAllowedSet.test( GetContextParent().directive)) { eligibleCancellation = true; } break; - case parser::OmpCancelType::Type::Parallel: + case llvm::omp::Directive::OMPD_parallel: if (llvm::omp::nestedCancelParallelAllowedSet.test( GetContextParent().directive)) { eligibleCancellation = true; } break; + default: + // This should have been diagnosed by this point. + llvm_unreachable("Unexpected directive"); } if (!eligibleCancellation) { context_.Say(source, - "With %s clause, %s construct cannot be closely nested inside %s " - "construct"_err_en_US, - parser::ToUpperCaseLetters(parser::OmpCancelType::EnumToString(type)), + "With %s clause, %s construct cannot be closely nested inside %s construct"_err_en_US, + parser::ToUpperCaseLetters(typeName.str()), ContextDirectiveAsFortran(), parser::ToUpperCaseLetters( getDirectiveName(GetContextParent().directive).str())); @@ -2320,38 +2383,33 @@ void OmpStructureChecker::CheckCancellationNest( } else { // The cancellation directive cannot be orphaned. switch (type) { - case parser::OmpCancelType::Type::Taskgroup: + case llvm::omp::Directive::OMPD_taskgroup: context_.Say(source, - "%s %s directive is not closely nested inside " - "TASK or TASKLOOP"_err_en_US, + "%s %s directive is not closely nested inside TASK or TASKLOOP"_err_en_US, ContextDirectiveAsFortran(), - parser::ToUpperCaseLetters( - parser::OmpCancelType::EnumToString(type))); + parser::ToUpperCaseLetters(typeName.str())); break; - case parser::OmpCancelType::Type::Sections: + case llvm::omp::Directive::OMPD_sections: context_.Say(source, - "%s %s directive is not closely nested inside " - "SECTION or SECTIONS"_err_en_US, + "%s %s directive is not closely nested inside SECTION or SECTIONS"_err_en_US, ContextDirectiveAsFortran(), - parser::ToUpperCaseLetters( - parser::OmpCancelType::EnumToString(type))); + parser::ToUpperCaseLetters(typeName.str())); break; - case parser::OmpCancelType::Type::Do: + case llvm::omp::Directive::OMPD_do: context_.Say(source, - "%s %s directive is not closely nested inside " - "the construct that matches the DO clause type"_err_en_US, + "%s %s directive is not closely nested inside the construct that matches the DO clause type"_err_en_US, ContextDirectiveAsFortran(), - parser::ToUpperCaseLetters( - parser::OmpCancelType::EnumToString(type))); + parser::ToUpperCaseLetters(typeName.str())); break; - case parser::OmpCancelType::Type::Parallel: + case llvm::omp::Directive::OMPD_parallel: context_.Say(source, - "%s %s directive is not closely nested inside " - "the construct that matches the PARALLEL clause type"_err_en_US, + "%s %s directive is not closely nested inside the construct that matches the PARALLEL clause type"_err_en_US, ContextDirectiveAsFortran(), - parser::ToUpperCaseLetters( - parser::OmpCancelType::EnumToString(type))); + parser::ToUpperCaseLetters(typeName.str())); break; + default: + // This should have been diagnosed by this point. + llvm_unreachable("Unexpected directive"); } } } @@ -3044,7 +3102,6 @@ CHECK_SIMPLE_CLAUSE(MemoryOrder, OMPC_memory_order) CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind) CHECK_SIMPLE_CLAUSE(Align, OMPC_align) CHECK_SIMPLE_CLAUSE(Compare, OMPC_compare) -CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type) CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute) CHECK_SIMPLE_CLAUSE(Weak, OMPC_weak) diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index b70ea58cf5578..48795995fdf50 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -275,8 +275,11 @@ class OmpStructureChecker void CheckTargetUpdate(); void CheckDependenceType(const parser::OmpDependenceType::Value &x); void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x); + std::optional<llvm::omp::Directive> GetCancelType( + llvm::omp::Directive cancelDir, const parser::CharBlock &cancelSource, + const parser::OmpClauseList &clauses); void CheckCancellationNest( - const parser::CharBlock &source, const parser::OmpCancelType::Type &type); + const parser::CharBlock &source, llvm::omp::Directive type); std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x); void CheckReductionObjects( const parser::OmpObjectList &objects, llvm::omp::Clause clauseId); diff --git a/flang/test/Semantics/OpenMP/cancel.f90 b/flang/test/Semantics/OpenMP/cancel.f90 new file mode 100644 index 0000000000000..581c4bdb97646 --- /dev/null +++ b/flang/test/Semantics/OpenMP/cancel.f90 @@ -0,0 +1,29 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp + +subroutine f00 +!$omp parallel +!ERROR: Missing cancel-directive-name clause on the CANCEL construct +!$omp cancel +!$omp end parallel +end + +subroutine f01 +!$omp parallel +!ERROR: Multiple cancel-directive-name clauses are not allowed on the CANCEL construct +!$omp cancel parallel parallel +!$omp end parallel +end + +subroutine f02 +!$omp parallel +!ERROR: Missing cancel-directive-name clause on the CANCELLATION POINT construct +!$omp cancellation point +!$omp end parallel +end + +subroutine f03 +!$omp parallel +!ERROR: Multiple cancel-directive-name clauses are not allowed on the CANCELLATION POINT construct +!$omp cancellation point parallel parallel +!$omp end parallel +end diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 8a2f30a7995dc..cbad02a70609f 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -105,6 +105,7 @@ def OMPC_CancellationConstructType : Clause<"cancellation_construct_type"> { OMP_CANCELLATION_CONSTRUCT_Taskgroup, OMP_CANCELLATION_CONSTRUCT_None ]; + let flangClass = "OmpCancellationConstructTypeClause"; } def OMPC_Contains : Clause<"contains"> { let clangClass = "OMPContainsClause"; @@ -647,12 +648,16 @@ def OMP_BeginDeclareVariant : Directive<"begin declare variant"> { } def OMP_Cancel : Directive<"cancel"> { let allowedOnceClauses = [ + VersionedClause<OMPC_CancellationConstructType>, VersionedClause<OMPC_If>, ]; let association = AS_None; let category = CA_Executable; } def OMP_CancellationPoint : Directive<"cancellation point"> { + let allowedOnceClauses = [ + VersionedClause<OMPC_CancellationConstructType>, + ]; let association = AS_None; let category = CA_Executable; } >From eedbc24196c0872e9466f3936599e5dd9d49630b Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com> Date: Thu, 6 Mar 2025 11:30:24 -0600 Subject: [PATCH 2/2] format --- flang/lib/Parser/openmp-parsers.cpp | 4 ++-- flang/lib/Semantics/check-omp-structure.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 51b2567a3894d..2f094b0ce320d 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1125,8 +1125,8 @@ TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>( verbatim("CANCELLATION POINT"_tok), Parser<OmpClauseList>{}))) // 2.14.1 Cancel construct -TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(verbatim("CANCEL"_tok), - Parser<OmpClauseList>{}))) +TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>( + verbatim("CANCEL"_tok), Parser<OmpClauseList>{}))) TYPE_PARSER(sourced(construct<OmpFailClause>( parenthesized(indirect(Parser<OmpMemoryOrderClause>{}))))) diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 8d819defb4a0c..cc9fc1e531063 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2245,8 +2245,7 @@ void OmpStructureChecker::Enter( case llvm::omp::Directive::OMPD_taskgroup: break; default: - context_.Say(dirName.source, - "%s is not a cancellable construct"_err_en_US, + context_.Say(dirName.source, "%s is not a cancellable construct"_err_en_US, parser::ToUpperCaseLetters( llvm::omp::getOpenMPDirectiveName(dirName.v).str())); break; _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits