diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -1978,7 +1978,11 @@ */ CXCursor_OMPParallelMaskedTaskLoopSimdDirective = 304, - CXCursor_LastStmt = CXCursor_OMPParallelMaskedTaskLoopSimdDirective, + /** OpenMP error directive. + */ + CXCursor_OMPErrorDirective = 305, + + CXCursor_LastStmt = CXCursor_OMPErrorDirective, /** * Cursor that represents the translation unit itself. 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 @@ -3153,6 +3153,10 @@ DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPErrorDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -6220,6 +6220,51 @@ return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass; } }; + +/// This represents '#pragma omp error' directive. +/// +/// \code +/// #pragma omp error +/// \endcode +class OMPErrorDirective final : public OMPExecutableDirective { + friend class ASTStmtReader; + friend class OMPExecutableDirective; + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// + OMPErrorDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error, + StartLoc, EndLoc) {} + /// Build an empty directive. + /// + explicit OMPErrorDirective() + : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error, + SourceLocation(), SourceLocation()) {} + +public: + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// + static OMPErrorDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses); + + /// Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPErrorDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPErrorDirectiveClass; + } +}; } // end namespace clang #endif diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -292,3 +292,4 @@ def OMPTargetTeamsGenericLoopDirective : StmtNode; def OMPParallelGenericLoopDirective : StmtNode; def OMPTargetParallelGenericLoopDirective : StmtNode; +def OMPErrorDirective : StmtNode; 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 @@ -11286,6 +11286,10 @@ /// Called on well-formed '\#pragma omp taskyield'. StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp error'. + StmtResult ActOnOpenMPErrorDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); /// Called on well-formed '\#pragma omp barrier'. StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1932,6 +1932,7 @@ STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, STMT_OMP_TASK_DIRECTIVE, STMT_OMP_TASKYIELD_DIRECTIVE, + STMT_OMP_ERROR_DIRECTIVE, STMT_OMP_BARRIER_DIRECTIVE, STMT_OMP_TASKWAIT_DIRECTIVE, STMT_OMP_FLUSH_DIRECTIVE, diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -744,6 +744,21 @@ return new (C) OMPTaskyieldDirective(); } +OMPErrorDirective *OMPErrorDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses) { + return createDirective( + C, Clauses, /*AssociatedStmt=*/nullptr, /*NumChildren=*/0, StartLoc, + EndLoc); +} + +OMPErrorDirective *OMPErrorDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + return createEmptyDirective(C, NumClauses); +} + OMPBarrierDirective *OMPBarrierDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc) { diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -843,6 +843,11 @@ PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPErrorDirective(OMPErrorDirective *Node) { + Indent() << "#pragma omp error"; + PrintOMPExecutableDirective(Node); +} + void StmtPrinter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *Node) { Indent() << "#pragma omp taskgroup"; PrintOMPExecutableDirective(Node); 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 @@ -1014,6 +1014,9 @@ VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPErrorDirective(const OMPErrorDirective *S) { + VisitOMPExecutableDirective(S); +} void StmtProfiler::VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *S) { VisitOMPExecutableDirective(S); if (const Expr *E = S->getReductionRef()) 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 @@ -763,6 +763,7 @@ case OMPD_allocate: case OMPD_taskyield: case OMPD_barrier: + case OMPD_error: case OMPD_taskwait: case OMPD_cancellation_point: case OMPD_cancel: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -254,6 +254,9 @@ case Stmt::OMPTaskyieldDirectiveClass: EmitOMPTaskyieldDirective(cast(*S)); break; + case Stmt::OMPErrorDirectiveClass: + EmitOMPErrorDirective(cast(*S)); + break; case Stmt::OMPBarrierDirectiveClass: EmitOMPBarrierDirective(cast(*S)); break; 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 @@ -1347,6 +1347,7 @@ case OMPD_parallel_for_simd: case OMPD_task: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_taskgroup: @@ -5244,6 +5245,10 @@ CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc()); } +void CodeGenFunction::EmitOMPErrorDirective(const OMPErrorDirective &S) { + llvm_unreachable("CodeGen for 'omp error' is not supported yet."); +} + void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3520,6 +3520,7 @@ void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S); void EmitOMPTaskDirective(const OMPTaskDirective &S); void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S); + void EmitOMPErrorDirective(const OMPErrorDirective &S); void EmitOMPBarrierDirective(const OMPBarrierDirective &S); void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S); void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S); 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 @@ -2310,6 +2310,7 @@ case OMPD_unroll: case OMPD_task: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_taskgroup: @@ -2410,8 +2411,8 @@ /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | /// 'section' | 'single' | 'master' | 'critical' [ '(' ')' ] | /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | -/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | -/// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target +/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error' +/// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | /// 'master taskloop' | 'master taskloop simd' | 'parallel master /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target @@ -2697,6 +2698,7 @@ case OMPD_depobj: case OMPD_scan: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1494,6 +1494,7 @@ case Stmt::OMPTaskLoopSimdDirectiveClass: case Stmt::OMPTaskwaitDirectiveClass: case Stmt::OMPTaskyieldDirectiveClass: + case Stmt::OMPErrorDirectiveClass: case Stmt::OMPTeamsDirectiveClass: case Stmt::OMPTeamsDistributeDirectiveClass: case Stmt::OMPTeamsDistributeParallelForDirectiveClass: 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 @@ -4532,6 +4532,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -6305,6 +6306,11 @@ "No associated statement allowed for 'omp taskyield' directive"); Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc); break; + case OMPD_error: + assert(AStmt == nullptr && + "No associated statement allowed for 'omp taskyield' directive"); + Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc); + break; case OMPD_barrier: assert(ClausesWithImplicit.empty() && "No clauses are allowed for 'omp barrier' directive"); @@ -11020,6 +11026,12 @@ return OMPBarrierDirective::Create(Context, StartLoc, EndLoc); } +StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc) { + return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses); +} + StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { @@ -15313,6 +15325,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15401,6 +15414,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15497,6 +15511,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15588,6 +15603,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15676,6 +15692,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15767,6 +15784,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15861,6 +15879,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15952,6 +15971,7 @@ case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: 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 @@ -8897,6 +8897,17 @@ return Res; } +template +StmtResult +TreeTransform::TransformOMPErrorDirective(OMPErrorDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_error, DirName, nullptr, + D->getBeginLoc()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + template StmtResult TreeTransform::TransformOMPTaskgroupDirective( OMPTaskgroupDirective *D) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2412,6 +2412,13 @@ VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPErrorDirective(OMPErrorDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + Record.skipInts(1); + VisitOMPExecutableDirective(D); +} + void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); @@ -3359,6 +3366,11 @@ Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_ERROR_DIRECTIVE: + S = OMPErrorDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case STMT_OMP_TASKGROUP_DIRECTIVE: S = OMPTaskgroupDirective::CreateEmpty( Context, Record[ASTStmtReader::NumStmtFields], Empty); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2396,6 +2396,13 @@ Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE; } +void ASTStmtWriter::VisitOMPErrorDirective(OMPErrorDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_ERROR_DIRECTIVE; +} + void ASTStmtWriter::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) { VisitStmt(D); VisitOMPExecutableDirective(D); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1744,6 +1744,7 @@ case Stmt::OMPTaskyieldDirectiveClass: case Stmt::OMPBarrierDirectiveClass: case Stmt::OMPTaskwaitDirectiveClass: + case Stmt::OMPErrorDirectiveClass: case Stmt::OMPTaskgroupDirectiveClass: case Stmt::OMPFlushDirectiveClass: case Stmt::OMPDepobjDirectiveClass: diff --git a/clang/test/OpenMP/error_ast_print.cpp b/clang/test/OpenMP/error_ast_print.cpp new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/error_ast_print.cpp @@ -0,0 +1,62 @@ +// 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-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 +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void foo() {} +// CHECK: template int tmain(T argc, char **argv) +// CHECK: static int a; +// CHECK-NEXT: #pragma omp error +// CHECK-NEXT: a = argv[0][0]; +// CHECK-NEXT: ++a; +// CHECK-NEXT: #pragma omp error +// CHECK-NEXT: { +// CHECK-NEXT: int b = 10; +// CHECK-NEXT: T c = 100; +// CHECK-NEXT: a = b + c; +// CHECK-NEXT: } +// CHECK-NEXT: #pragma omp error +// CHECK-NEXT: foo(); +// CHECK-NEXT: return N; + +template +int tmain(T argc, char **argv) { + T b = argc, c, d, e, f, g; + static int a; +#pragma omp error + a = argv[0][0]; + ++a; +#pragma omp error + { + int b = 10; + T c = 100; + a = b + c; + } +#pragma omp error + foo(); +return N; +} + +// 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 +// CHECK-NEXT: a = 2; +// CHECK-NEXT: #pragma omp error +// CHECK-NEXT: foo(); +int main (int argc, char **argv) { + int b = argc, c, d, e, f, g; + static int a; +#pragma omp error + a=2; +#pragma omp error + foo(); +} +#endif diff --git a/clang/test/OpenMP/error_message.cpp b/clang/test/OpenMP/error_message.cpp new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/error_message.cpp @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized + +// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized + +template +T tmain(T argc) { + if (argc) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + if (argc) { +#pragma omp error + } + while (argc) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + while (argc) { +#pragma omp error + } + do +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp error + } while (argc); + switch (argc) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp error + } + switch (argc) { +#pragma omp error + case 1: +#pragma omp error + break; + default: { +#pragma omp error + } break; + } + for (;;) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + for (;;) { +#pragma omp error + } +label: +#pragma omp error +label1 : { +#pragma omp error +} +if (1) + label2: +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + + return T(); +} + +int main(int argc, char **argv) { +#pragma omp error + ; +#pragma omp error untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp error'}} +#pragma omp error unknown // expected-warning {{extra tokens at the end of '#pragma omp error' are ignored}} + if (argc) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + if (argc) { +#pragma omp error + } + while (argc) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + while (argc) { +#pragma omp error + } + do +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + while (argc) + ; + do { +#pragma omp error + } while (argc); + switch (argc) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + switch (argc) + case 1: +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + switch (argc) + case 1: { +#pragma omp error + } + switch (argc) { +#pragma omp error + case 1: +#pragma omp error + break; + default: { +#pragma omp error + } break; + } + for (;;) +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + for (;;) { +#pragma omp error + } +label: +#pragma omp error +label1 : { +#pragma omp error +} +if (1) + label2: +#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}} + + return tmain(argc); +} 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 @@ -2164,6 +2164,7 @@ void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D); void VisitOMPBarrierDirective(const OMPBarrierDirective *D); void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D); + void VisitOMPErrorDirective(const OMPErrorDirective *D); void VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *D); void VisitOMPCancellationPointDirective(const OMPCancellationPointDirective *D); @@ -3114,6 +3115,10 @@ VisitOMPExecutableDirective(D); } +void EnqueueVisitor::VisitOMPErrorDirective(const OMPErrorDirective *D) { + VisitOMPExecutableDirective(D); +} + void EnqueueVisitor::VisitOMPTaskgroupDirective( const OMPTaskgroupDirective *D) { VisitOMPExecutableDirective(D); @@ -5819,6 +5824,8 @@ return cxstring::createRef("OMPBarrierDirective"); case CXCursor_OMPTaskwaitDirective: return cxstring::createRef("OMPTaskwaitDirective"); + case CXCursor_OMPErrorDirective: + return cxstring::createRef("OMPErrorDirective"); case CXCursor_OMPTaskgroupDirective: return cxstring::createRef("OMPTaskgroupDirective"); case CXCursor_OMPFlushDirective: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -712,6 +712,9 @@ case Stmt::OMPTaskwaitDirectiveClass: K = CXCursor_OMPTaskwaitDirective; break; + case Stmt::OMPErrorDirectiveClass: + K = CXCursor_OMPErrorDirective; + break; case Stmt::OMPTaskgroupDirectiveClass: K = CXCursor_OMPTaskgroupDirective; break; 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 @@ -526,6 +526,7 @@ } def OMP_TaskYield : Directive<"taskyield"> {} def OMP_Barrier : Directive<"barrier"> {} +def OMP_Error : Directive<"error"> {} def OMP_TaskWait : Directive<"taskwait"> { let allowedClauses = [ VersionedClause