diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -1642,6 +1642,86 @@ } }; +/// This represents 'severity' clause in the '#pragma omp error' directive +/// +/// \code +/// #pragma omp error severity(fatal) +/// \endcode +/// In this example directive '#pragma omp error' has simple +/// 'severity' clause with kind 'fatal'. +class OMPSeverityClause final : public OMPClause { + friend class OMPClauseReader; + + /// Location of '(' + SourceLocation LParenLoc; + + /// A kind of the 'severity' clause. + OpenMPSeverityClauseKind Kind = OMPC_SEVERITY_unknown; + + /// Start location of the kind in source code. + SourceLocation KindKwLoc; + + /// Set kind of the clause. + /// + /// \param K Kind of clause. + void setSeverityKind(OpenMPSeverityClauseKind K) { Kind = K; } + + /// Set clause kind location. + /// + /// \param KLoc Kind location. + void setSeverityKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + + /// Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + +public: + /// Build 'severity' clause with argument \a A ('fatal' or 'warning'). + /// + /// \param A Argument of the clause ('fatal' or 'warning'). + /// \param ALoc Starting location of the argument. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + OMPSeverityClause(OpenMPSeverityClauseKind A, SourceLocation ALoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(llvm::omp::OMPC_severity, StartLoc, EndLoc), + LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} + + /// Build an empty clause. + OMPSeverityClause() + : OMPClause(llvm::omp::OMPC_severity, SourceLocation(), + SourceLocation()) {} + + /// Returns the locaiton of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// Returns kind of the clause. + OpenMPSeverityClauseKind getSeverityKind() const { return Kind; } + + /// Returns location of clause kind. + SourceLocation getSeverityKindKwLoc() const { return KindKwLoc; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == llvm::omp::OMPC_severity; + } +}; + /// This represents 'schedule' clause in the '#pragma omp ...' directive. /// /// \code diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -3315,6 +3315,11 @@ return true; } +template +bool RecursiveASTVisitor::VisitOMPSeverityClause(OMPSeverityClause *) { + return true; +} + template bool RecursiveASTVisitor::VisitOMPScheduleClause(OMPScheduleClause *C) { diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -138,6 +138,13 @@ OMPC_AT_unknown }; +/// OpenMP attributes for 'severity' clause. +enum OpenMPSeverityClauseKind { +#define OPENMP_SEVERITY_KIND(Name) OMPC_SEVERITY_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_SEVERITY_unknown +}; + /// OpenMP device type for 'device_type' clause. enum OpenMPDeviceType { #define OPENMP_DEVICE_TYPE_KIND(Name) \ diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -44,6 +44,9 @@ #ifndef OPENMP_AT_KIND #define OPENMP_AT_KIND(Name) #endif +#ifndef OPENMP_SEVERITY_KIND +#define OPENMP_SEVERITY_KIND(Name) +#endif #ifndef OPENMP_DEFAULTMAP_MODIFIER #define OPENMP_DEFAULTMAP_MODIFIER(Name) #endif @@ -126,6 +129,10 @@ OPENMP_AT_KIND(compilation) OPENMP_AT_KIND(execution) +// Modifiers for 'severity' clause. +OPENMP_SEVERITY_KIND(fatal) +OPENMP_SEVERITY_KIND(warning) + // Map types for 'map' clause. OPENMP_MAP_KIND(alloc) OPENMP_MAP_KIND(to) @@ -187,6 +194,7 @@ #undef OPENMP_SCHEDULE_KIND #undef OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND #undef OPENMP_AT_KIND +#undef OPENMP_SEVERITY_KIND #undef OPENMP_MAP_KIND #undef OPENMP_MAP_MODIFIER_KIND #undef OPENMP_MOTION_MODIFIER_KIND diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11836,6 +11836,13 @@ SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'severity' clause. + OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Data used for processing a list of variables in OpenMP clauses. struct OpenMPVarListDataTy final { Expr *DepModOrTailExpr = nullptr; diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -153,6 +153,7 @@ case OMPC_dynamic_allocators: case OMPC_atomic_default_mem_order: case OMPC_at: + case OMPC_severity: case OMPC_device_type: case OMPC_match: case OMPC_nontemporal: @@ -253,6 +254,7 @@ case OMPC_dynamic_allocators: case OMPC_atomic_default_mem_order: case OMPC_at: + case OMPC_severity: case OMPC_device_type: case OMPC_match: case OMPC_nontemporal: @@ -1788,6 +1790,12 @@ << ")"; } +void OMPClausePrinter::VisitOMPSeverityClause(OMPSeverityClause *Node) { + OS << "severity(" + << getOpenMPSimpleClauseTypeName(OMPC_severity, Node->getSeverityKind()) + << ")"; +} + void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) { OS << "schedule("; if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -532,6 +532,8 @@ void OMPClauseProfiler::VisitOMPAtClause(const OMPAtClause *C) {} +void OMPClauseProfiler::VisitOMPSeverityClause(const OMPSeverityClause *C) {} + void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) { VistOMPClauseWithPreInit(C); if (auto *S = C->getChunkSize()) diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -109,6 +109,11 @@ #define OPENMP_AT_KIND(Name) .Case(#Name, OMPC_AT_##Name) #include "clang/Basic/OpenMPKinds.def" .Default(OMPC_AT_unknown); + case OMPC_severity: + return llvm::StringSwitch(Str) +#define OPENMP_SEVERITY_KIND(Name) .Case(#Name, OMPC_SEVERITY_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_SEVERITY_unknown); case OMPC_lastprivate: return llvm::StringSwitch(Str) #define OPENMP_LASTPRIVATE_KIND(Name) .Case(#Name, OMPC_LASTPRIVATE_##Name) @@ -351,7 +356,16 @@ #include "clang/Basic/OpenMPKinds.def" } llvm_unreachable("Invalid OpenMP 'at' clause type"); - llvm_unreachable("Invalid OpenMP 'at' clause type"); + case OMPC_severity: + switch (Type) { + case OMPC_SEVERITY_unknown: + return "unknown"; +#define OPENMP_SEVERITY_KIND(Name) \ + case OMPC_SEVERITY_##Name: \ + return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'severity' clause type"); case OMPC_lastprivate: switch (Type) { case OMPC_LASTPRIVATE_unknown: diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -6513,6 +6513,7 @@ case OMPC_dynamic_allocators: case OMPC_atomic_default_mem_order: case OMPC_at: + case OMPC_severity: case OMPC_device_type: case OMPC_match: case OMPC_nontemporal: diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -3237,6 +3237,7 @@ case OMPC_proc_bind: case OMPC_atomic_default_mem_order: case OMPC_at: + case OMPC_severity: case OMPC_order: case OMPC_bind: // OpenMP [2.14.3.1, Restrictions] @@ -3247,8 +3248,9 @@ // OpenMP [5.0, Requires directive, Restrictions] // At most one atomic_default_mem_order clause can appear // on the directive - // OpenMP [5.1, Requires directive, Restrictions] + // OpenMP [5.1, error directive, Restrictions] // At most one at clause can appear on the directive + // At most one severity clause can appear on the directive // OpenMP 5.1, 2.11.7 loop Construct, Restrictions. // At most one bind clause can appear on a loop directive. if (!FirstClause && CKind != OMPC_order) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6720,6 +6720,7 @@ case OMPC_match: case OMPC_when: case OMPC_at: + case OMPC_severity: default: llvm_unreachable("Unexpected clause"); } @@ -11039,10 +11040,19 @@ Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier); return StmtError(); } + auto SeverityClauses = + OMPExecutableDirective::getClausesOfKind(Clauses); + const OMPSeverityClause *SeverityC = + SeverityClauses.empty() ? nullptr : (*SeverityClauses.begin()); + if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) { - Diag(AtC ? AtC->getBeginLoc() : StartLoc, diag::err_diagnose_if_succeeded) - << "ERROR"; - return StmtError(); + if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning) + Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded) + << "WARNING"; + else + Diag(StartLoc, diag::err_diagnose_if_succeeded) << "ERROR"; + if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning) + return StmtError(); } return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses); } @@ -15187,6 +15197,7 @@ case OMPC_nontemporal: case OMPC_order: case OMPC_at: + case OMPC_severity: case OMPC_destroy: case OMPC_inclusive: case OMPC_exclusive: @@ -16113,6 +16124,7 @@ case OMPC_nontemporal: case OMPC_order: case OMPC_at: + case OMPC_severity: case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: @@ -16519,6 +16531,11 @@ Res = ActOnOpenMPAtClause(static_cast(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; + case OMPC_severity: + Res = ActOnOpenMPSeverityClause( + static_cast(Argument), ArgumentLoc, StartLoc, + LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -16713,6 +16730,22 @@ OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (Kind == OMPC_SEVERITY_unknown) { + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_severity, /*First=*/0, + /*Last=*/OMPC_SEVERITY_unknown) + << getOpenMPClauseName(OMPC_severity); + return nullptr; + } + return new (Context) + OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPOrderClause(OpenMPOrderClauseKind Kind, SourceLocation KindKwLoc, SourceLocation StartLoc, @@ -16913,6 +16946,7 @@ case OMPC_nontemporal: case OMPC_order: case OMPC_at: + case OMPC_severity: case OMPC_destroy: case OMPC_novariants: case OMPC_nocontext: @@ -17170,6 +17204,7 @@ case OMPC_nontemporal: case OMPC_order: case OMPC_at: + case OMPC_severity: case OMPC_novariants: case OMPC_nocontext: case OMPC_detach: @@ -17725,6 +17760,7 @@ case OMPC_match: case OMPC_order: case OMPC_at: + case OMPC_severity: case OMPC_destroy: case OMPC_novariants: case OMPC_nocontext: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2362,6 +2362,20 @@ return getSema().ActOnOpenMPAtClause(Kind, KwLoc, StartLoc, LParenLoc, EndLoc); } + + /// Build a new OpenMP 'severity' clause. + /// + /// By default, performs semantic analysis to build the new OpenMP clause. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPSeverityClause(OpenMPSeverityClauseKind Kind, + SourceLocation KwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPSeverityClause(Kind, KwLoc, StartLoc, LParenLoc, + EndLoc); + } + /// Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -9873,6 +9887,14 @@ C->getEndLoc()); } +template +OMPClause * +TreeTransform::TransformOMPSeverityClause(OMPSeverityClause *C) { + return getDerived().RebuildOMPSeverityClause( + C->getSeverityKind(), C->getSeverityKindKwLoc(), C->getBeginLoc(), + C->getLParenLoc(), C->getEndLoc()); +} + template OMPClause * TreeTransform::TransformOMPPrivateClause(OMPPrivateClause *C) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9952,6 +9952,9 @@ case llvm::omp::OMPC_at: C = new (Context) OMPAtClause(); break; + case llvm::omp::OMPC_severity: + C = new (Context) OMPSeverityClause(); + break; case llvm::omp::OMPC_private: C = OMPPrivateClause::CreateEmpty(Context, Record.readInt()); break; @@ -10360,6 +10363,12 @@ C->setAtKindKwLoc(Record.readSourceLocation()); } +void OMPClauseReader::VisitOMPSeverityClause(OMPSeverityClause *C) { + C->setSeverityKind(static_cast(Record.readInt())); + C->setLParenLoc(Record.readSourceLocation()); + C->setSeverityKindKwLoc(Record.readSourceLocation()); +} + void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) { C->setLParenLoc(Record.readSourceLocation()); unsigned NumVars = C->varlist_size(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6987,6 +6987,12 @@ Record.AddSourceLocation(C->getAtKindKwLoc()); } +void OMPClauseWriter::VisitOMPSeverityClause(OMPSeverityClause *C) { + Record.push_back(C->getSeverityKind()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getSeverityKindKwLoc()); +} + void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) { Record.push_back(C->varlist_size()); Record.AddSourceLocation(C->getLParenLoc()); diff --git a/clang/test/OpenMP/error_ast_print.cpp b/clang/test/OpenMP/error_ast_print.cpp --- a/clang/test/OpenMP/error_ast_print.cpp +++ b/clang/test/OpenMP/error_ast_print.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -fopenmp-version=51 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -fopenmp-version=51 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s -// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -fopenmp-version=51 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -fopenmp-version=51 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s // expected-no-diagnostics #ifndef HEADER @@ -13,16 +13,16 @@ void foo() {} // CHECK: template int tmain(T argc, char **argv) // CHECK: static int a; -// CHECK-NEXT: #pragma omp error at(execution) +// CHECK-NEXT: #pragma omp error at(execution) severity(fatal) // CHECK-NEXT: a = argv[0][0]; // CHECK-NEXT: ++a; -// CHECK-NEXT: #pragma omp error at(execution) +// CHECK-NEXT: #pragma omp error at(execution) severity(warning) // CHECK-NEXT: { // CHECK-NEXT: int b = 10; // CHECK-NEXT: T c = 100; // CHECK-NEXT: a = b + c; // CHECK-NEXT: } -// CHECK-NEXT: #pragma omp error at(execution) +// CHECK-NEXT: #pragma omp error at(execution) severity(fatal) // CHECK-NEXT: foo(); // CHECK-NEXT: return N; @@ -30,16 +30,16 @@ int tmain(T argc, char **argv) { T b = argc, c, d, e, f, g; static int a; -#pragma omp error at(execution) +#pragma omp error at(execution) severity(fatal) a = argv[0][0]; ++a; -#pragma omp error at(execution) +#pragma omp error at(execution) severity(warning) { int b = 10; T c = 100; a = b + c; } -#pragma omp error at(execution) +#pragma omp error at(execution) severity(fatal) foo(); return N; } @@ -47,16 +47,16 @@ // CHECK: int main(int argc, char **argv) // CHECK-NEXT: int b = argc, c, d, e, f, g; // CHECK-NEXT: static int a; -// CHECK-NEXT: #pragma omp error at(execution) +// CHECK-NEXT: #pragma omp error at(execution) severity(fatal) // CHECK-NEXT: a = 2; -// CHECK-NEXT: #pragma omp error at(execution) +// CHECK-NEXT: #pragma omp error at(execution) severity(warning) // CHECK-NEXT: foo(); int main (int argc, char **argv) { int b = argc, c, d, e, f, g; static int a; -#pragma omp error at(execution) +#pragma omp error at(execution) severity(fatal) a=2; -#pragma omp error at(execution) +#pragma omp error at(execution) severity(warning) foo(); } #endif diff --git a/clang/test/OpenMP/error_message.cpp b/clang/test/OpenMP/error_message.cpp --- a/clang/test/OpenMP/error_message.cpp +++ b/clang/test/OpenMP/error_message.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -ferror-limit 100 %s -Wuninitialized -// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -ferror-limit 100 %s -Wuninitialized template T tmain(T argc) { @@ -67,6 +67,33 @@ #pragma omp error at(execution) // no error #pragma omp error at(compilation) // expected-error {{ERROR}} + +// expected-error@+1 {{ERROR}} +#pragma omp error at(compilation) at(execution) //expected-error {{directive '#pragma omp error' cannot contain more than one 'at' clause}} + +// expected-error@+1 {{ERROR}} +#pragma omp error severity() // expected-error {{expected 'fatal' or 'warning' in OpenMP clause 'severity'}} +// expected-error@+1 {{ERROR}} +#pragma omp error severity(xyz) // expected-error {{expected 'fatal' or 'warning' in OpenMP clause 'severity'}} +// expected-error@+1 {{ERROR}} +#pragma omp error severity(fatal) severity(warning) // expected-error {{directive '#pragma omp error' cannot contain more than one 'severity' clause}} + +// expected-error@+1 {{ERROR}} +#pragma omp error severity(fatal) severity(fatal) // expected-error {{directive '#pragma omp error' cannot contain more than one 'severity' clause}} + +// expected-warning@+2 {{WARNING}} +// expected-warning@+1 {{WARNING}} +#pragma omp error severity(warning) severity(warning) // expected-error {{directive '#pragma omp error' cannot contain more than one 'severity' clause}} + +// expected-warning@+1 {{WARNING}} +#pragma omp error severity(warning) // expected-warning {{WARNING}} +#pragma omp error severity(fatal) // expected-error {{ERROR}} + +// expected-warning@+1 {{WARNING}} +#pragma omp error at(compilation) severity(warning) // expected-warning {{WARNING}} +#pragma omp error at(execution) severity(warning) // no error, diagnosic at runtime +#pragma omp error at(compilation) severity(fatal) // expected-error {{ERROR}} +#pragma omp error at(execution) severity(fatal) // no error, error at runtime return T(); } @@ -146,5 +173,5 @@ label2: #pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} - return tmain(argc); + return tmain(argc);// expected-note {{in instantiation of function template specialization 'tmain' requested here}} } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2445,6 +2445,8 @@ void OMPClauseEnqueue::VisitOMPAtClause(const OMPAtClause *) {} +void OMPClauseEnqueue::VisitOMPSeverityClause(const OMPSeverityClause *) {} + void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) { Visitor->AddStmt(C->getDevice()); } diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1869,6 +1869,7 @@ CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants) CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext) CHECK_SIMPLE_CLAUSE(At, OMPC_at) +CHECK_SIMPLE_CLAUSE(Severity, OMPC_severity) CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter) CHECK_SIMPLE_CLAUSE(When, OMPC_when) CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -304,6 +304,9 @@ def OMPC_At : Clause<"at"> { let clangClass = "OMPAtClause"; } +def OMPC_Severity : Clause<"severity"> { + let clangClass = "OMPSeverityClause"; +} def OMPC_Allocate : Clause<"allocate"> { let clangClass = "OMPAllocateClause"; let flangClass = "OmpAllocateClause"; @@ -532,7 +535,8 @@ def OMP_Barrier : Directive<"barrier"> {} def OMP_Error : Directive<"error"> { let allowedClauses = [ - VersionedClause + VersionedClause, + VersionedClause ]; } def OMP_TaskWait : Directive<"taskwait"> {