jdoerfert updated this revision to Diff 284961.
jdoerfert added a comment.
Update for @alokmishra.besu via arcanist as the webinterface doesn't allow
patches over 2MB
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D76211/new/
https://reviews.llvm.org/D76211
Files:
clang/include/clang-c/Index.h
clang/include/clang/AST/OpenMPClause.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/StmtOpenMP.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/StmtNodes.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/OpenMPClause.cpp
clang/lib/AST/StmtOpenMP.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/Basic/OpenMPKinds.cpp
clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
clang/lib/CodeGen/CGStmt.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaExceptionSpec.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/test/OpenMP/metadirective_ast_print.cpp
clang/test/OpenMP/metadirective_codegen.cpp
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/CXCursor.cpp
llvm/include/llvm/Frontend/OpenMP/OMP.td
llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
Index: llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -111,6 +111,7 @@
__OMP_CLAUSE(uses_allocators, OMPUsesAllocatorsClause)
__OMP_CLAUSE(affinity, OMPAffinityClause)
__OMP_CLAUSE(use_device_addr, OMPUseDeviceAddrClause)
+__OMP_CLAUSE(when, OMPWhenClause)
__OMP_CLAUSE_NO_CLASS(uniform)
__OMP_CLAUSE_NO_CLASS(device_type)
Index: llvm/include/llvm/Frontend/OpenMP/OMP.td
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -42,6 +42,7 @@
def OMPC_SafeLen : Clause<"safelen"> { let clangClass = "OMPSafelenClause"; }
def OMPC_SimdLen : Clause<"simdlen"> { let clangClass = "OMPSimdlenClause"; }
def OMPC_Collapse : Clause<"collapse"> { let clangClass = "OMPCollapseClause"; }
+def OMPC_When : Clause<"when"> { let clangClass = "OMPWhenClause"; }
def OMPC_Default : Clause<"default"> { let clangClass = "OMPDefaultClause"; }
def OMPC_Private : Clause<"private"> { let clangClass = "OMPPrivateClause"; }
def OMPC_FirstPrivate : Clause<"firstprivate"> {
@@ -199,6 +200,14 @@
// Definition of OpenMP directives
//===----------------------------------------------------------------------===//
+def OMP_Metadirective : Directive<"metadirective"> {
+ let allowedClauses = [
+ VersionedClause<OMPC_When>
+ ];
+ let allowedOnceClauses = [
+ VersionedClause<OMPC_Default>
+ ];
+}
def OMP_ThreadPrivate : Directive<"threadprivate"> {}
def OMP_Parallel : Directive<"parallel"> {
let allowedClauses = [
Index: clang/tools/libclang/CXCursor.cpp
===================================================================
--- clang/tools/libclang/CXCursor.cpp
+++ clang/tools/libclang/CXCursor.cpp
@@ -639,6 +639,9 @@
case Stmt::MSDependentExistsStmtClass:
K = CXCursor_UnexposedStmt;
break;
+ case Stmt::OMPMetaDirectiveClass:
+ K = CXCursor_OMPMetaDirective;
+ break;
case Stmt::OMPParallelDirectiveClass:
K = CXCursor_OMPParallelDirective;
break;
Index: clang/tools/libclang/CIndex.cpp
===================================================================
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -2213,6 +2213,10 @@
Visitor->AddStmt(C->getNumForLoops());
}
+void OMPClauseEnqueue::VisitOMPWhenClause(const OMPWhenClause *C) {
+ Visitor->AddStmt(C->getExpr());
+}
+
void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) {}
void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) {}
@@ -5518,6 +5522,8 @@
return cxstring::createRef("CXXAccessSpecifier");
case CXCursor_ModuleImportDecl:
return cxstring::createRef("ModuleImport");
+ case CXCursor_OMPMetaDirective:
+ return cxstring::createRef("OMPMetaDirective");
case CXCursor_OMPParallelDirective:
return cxstring::createRef("OMPParallelDirective");
case CXCursor_OMPSimdDirective:
Index: clang/test/OpenMP/metadirective_codegen.cpp
===================================================================
--- /dev/null
+++ clang/test/OpenMP/metadirective_codegen.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -verify -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+int main(int argc, char **argv) {
+ int N = 15;
+#pragma omp metadirective when(user = {condition(N <= 1)} \
+ : parallel) when(user = {condition(N > 10)} \
+ : parallel for) default()
+ for (int i = 0; i < N; i++)
+ ;
+ // CHECK: %cmp{{[0-9]*}} = icmp sle i32 %{{[0-9]+}}, 1
+ // CHECK: br i1 %cmp{{[0-9]*}}, label %if.then{{[0-9]*}}, label %if.else{{[0-9]*}}
+ // CHECK: if.then{{[0-9]*}}:
+ // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i32* %N)
+ // CHECK: br label %if.end{{[0-9]*}}
+ // CHECK: if.else{{[0-9]*}}:
+ // CHECK: %{{[0-9]+}} = load i32, i32* %N, align 4
+ // CHECK: %cmp{{[0-9]+}} = icmp sgt i32 %{{[0-9]+}}, 10
+ // CHECK: br i1 %cmp{{[0-9]+}}, label %if.then{{[0-9]*}}, label %if.else{{[0-9]*}}
+ // CHECK: if.then{{[0-9]*}}:
+ // CHECK: call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* [[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i32* %N)
+ // CHECK: br label %if.end
+ // CHECK: if.else{{[0-9]*}}:
+ // CHECK: store i32 0, i32* %i{{[0-9]*}}, align 4
+ // CHECK: br label %for.cond{{[0-9]*}}
+ // CHECK: for.cond:
+ // CHECK: %{{[0-9]+}} = load i32, i32* %i{{[0-9]*}}, align 4
+ // CHECK: %{{[0-9]+}} = load i32, i32* %N, align 4
+ // CHECK: %cmp{{[0-9]+}} = icmp slt i32 %{{[0-9]+}}, %{{[0-9]+}}
+ // CHECK: br i1 %cmp{{[0-9]+}}, label %for.body, label %for.end
+ // CHECK: for.body:
+ // CHECK: br label %for.inc
+ // CHECK: for.inc:
+ // CHECK: %{{[0-9]+}} = load i32, i32* %i{{[0-9]*}}, align 4
+ // CHECK: %inc = add nsw i32 %{{[0-9]+}}, 1
+ // CHECK: store i32 %inc, i32* %i{{[0-9]*}}, align 4
+ // CHECK: br label %for.cond
+ // CHECK: for.end:
+
+ return 0;
+}
Index: clang/test/OpenMP/metadirective_ast_print.cpp
===================================================================
--- /dev/null
+++ clang/test/OpenMP/metadirective_ast_print.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// expected-no-diagnostics
+
+int main() {
+ int N = 15;
+#pragma omp metadirective when(user = {condition(N > 10)} \
+ : parallel for) default()
+ // CHECK: #pragma omp metadirective when(N > 10: parallel for) default()
+ for (int i = 0; i < N; i++)
+ ;
+
+#pragma omp metadirective when(user = {condition(N < 10)} \
+ :) default(parallel for)
+ // CHECK: #pragma omp metadirective when(N < 10: ) default(parallel for)
+ for (int i = 0; i < N; i++)
+ ;
+
+ return 0;
+}
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1292,6 +1292,7 @@
case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPMetaDirectiveClass:
case Stmt::CapturedStmtClass: {
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2167,6 +2167,13 @@
Record.AddSourceLocation(E->getEndLoc());
}
+void ASTStmtWriter::VisitOMPMetaDirective(OMPMetaDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_META_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
VisitStmt(D);
Record.writeUInt32(D->getCollapsedNumber());
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -6191,6 +6191,11 @@
Record.AddSourceLocation(C->getLParenLoc());
}
+void OMPClauseWriter::VisitOMPWhenClause(OMPWhenClause *C) {
+ Record.AddStmt(C->getExpr());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
Record.push_back(unsigned(C->getDefaultKind()));
Record.AddSourceLocation(C->getLParenLoc());
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2273,6 +2273,13 @@
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPMetaDirective(OMPMetaDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ Record.skipInts(1);
+ VisitOMPExecutableDirective(D);
+}
+
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
@@ -3113,6 +3120,11 @@
nullptr);
break;
+ case STMT_OMP_META_DIRECTIVE:
+ S = OMPMetaDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case STMT_OMP_PARALLEL_DIRECTIVE:
S =
OMPParallelDirective::CreateEmpty(Context,
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -11735,6 +11735,9 @@
OMPClause *OMPClauseReader::readClause() {
OMPClause *C = nullptr;
switch (llvm::omp::Clause(Record.readInt())) {
+ case llvm::omp::OMPC_when:
+ C = new (Context) OMPWhenClause();
+ break;
case llvm::omp::OMPC_if:
C = new (Context) OMPIfClause();
break;
@@ -12051,6 +12054,11 @@
C->setLParenLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPWhenClause(OMPWhenClause *C) {
+ C->setExpr(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
C->setDefaultKind(static_cast<llvm::omp::DefaultKind>(Record.readInt()));
C->setLParenLoc(Record.readSourceLocation());
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -1633,6 +1633,19 @@
EndLoc);
}
+ /// Build a new OpenMP 'when' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPWhenClause(Expr *expr, OpenMPDirectiveKind DKind,
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPWhenClause(expr, DKind, Clauses, AStmt,
+ StartLoc, LParenLoc, EndLoc);
+ }
+
/// Build a new OpenMP 'default' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -8370,6 +8383,17 @@
AssociatedStmt.get(), D->getBeginLoc(), D->getEndLoc());
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPMetaDirective(OMPMetaDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_metadirective, DirName,
+ nullptr, D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
@@ -9044,6 +9068,16 @@
E.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
}
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPWhenClause(OMPWhenClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getExpr());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPWhenClause(
+ C->getExpr(), C->getDKind(), C->getClauses(), C->getInnerStmt(),
+ C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+}
+
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -3700,6 +3700,7 @@
void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
switch (DKind) {
+ case OMPD_metadirective:
case OMPD_parallel:
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
@@ -5083,6 +5084,11 @@
llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
switch (Kind) {
+ case OMPD_metadirective:
+ Res =
+ ActOnOpenMPMetaDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+ AllowedNameModifiers.push_back(OMPD_metadirective);
+ break;
case OMPD_parallel:
Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
@@ -5502,6 +5508,7 @@
case OMPC_atomic_default_mem_order:
case OMPC_device_type:
case OMPC_match:
+ case OMPC_when:
default:
llvm_unreachable("Unexpected clause");
}
@@ -6263,6 +6270,69 @@
FD->addAttr(NewAttr);
}
+StmtResult Sema::ActOnOpenMPMetaDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ auto *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ StmtResult IfStmt = StmtError();
+ Stmt *ElseStmt = NULL;
+
+ for (auto i = Clauses.rbegin(); i < Clauses.rend(); i++) {
+ OMPWhenClause *WhenClause = dyn_cast<OMPWhenClause>(*i);
+ Expr *WhenCondExpr = WhenClause->getExpr();
+ Stmt *ThenStmt = NULL;
+ Stmt *WhenAStmt = WhenClause->getInnerStmt();
+
+ OpenMPDirectiveKind DKind = WhenClause->getDKind();
+ DeclarationNameInfo DirName;
+ ArrayRef<OMPClause *> clauses = WhenClause->getClauses();
+
+ StartOpenMPDSABlock(DKind, DirName, getCurScope(), StartLoc);
+ if (DKind != OMPD_unknown) {
+ ThenStmt =
+ ActOnOpenMPExecutableDirective(DKind, DirName, OMPD_unknown, clauses,
+ WhenAStmt, StartLoc, EndLoc)
+ .get();
+ }
+ EndOpenMPDSABlock(ThenStmt);
+
+ if (WhenCondExpr == NULL) {
+ if (ElseStmt != NULL) {
+ Diag(WhenClause->getBeginLoc(), diag::err_omp_misplaced_default_clause);
+ return StmtError();
+ }
+ if (DKind == OMPD_unknown)
+ ElseStmt = WhenClause->getInnerStmt();
+ else
+ ElseStmt = ThenStmt;
+ continue;
+ }
+
+ if (ThenStmt == NULL)
+ ThenStmt = AStmt;
+
+ IfStmt =
+ ActOnIfStmt(SourceLocation(), false, NULL,
+ ActOnCondition(getCurScope(), SourceLocation(),
+ WhenCondExpr, Sema::ConditionKind::Boolean),
+ ThenStmt, SourceLocation(), ElseStmt);
+ ElseStmt = IfStmt.get();
+ }
+
+ return OMPMetaDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ IfStmt.get());
+}
+
StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
@@ -11760,6 +11830,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
default:
llvm_unreachable("Clause is not allowed.");
}
@@ -11913,6 +11984,7 @@
case OMPD_atomic:
case OMPD_teams_distribute:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with if-clause");
case OMPD_unknown:
default:
@@ -11992,6 +12064,7 @@
case OMPD_teams_distribute:
case OMPD_teams_distribute_simd:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
case OMPD_unknown:
default:
@@ -12069,6 +12142,7 @@
case OMPD_atomic:
case OMPD_distribute_simd:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
case OMPD_unknown:
default:
@@ -12146,6 +12220,7 @@
case OMPD_atomic:
case OMPD_distribute_simd:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
case OMPD_unknown:
default:
@@ -12223,6 +12298,7 @@
case OMPD_distribute_simd:
case OMPD_target_teams:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with schedule clause");
case OMPD_unknown:
default:
@@ -12300,6 +12376,7 @@
case OMPD_atomic:
case OMPD_target_teams:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with schedule clause");
case OMPD_unknown:
default:
@@ -12377,6 +12454,7 @@
case OMPD_atomic:
case OMPD_distribute_simd:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
case OMPD_unknown:
default:
@@ -12456,12 +12534,22 @@
case OMPD_atomic:
case OMPD_distribute_simd:
case OMPD_requires:
+ case OMPD_metadirective:
llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
case OMPD_unknown:
default:
llvm_unreachable("Unknown OpenMP directive");
}
break;
+ case OMPC_when:
+ if (DKind == OMPD_metadirective) {
+ CaptureRegion = OMPD_metadirective;
+ } else if (DKind == OMPD_unknown) {
+ llvm_unreachable("Unknown OpenMP directive");
+ } else {
+ llvm_unreachable("Unexpected OpenMP directive with when clause");
+ }
+ break;
case OMPC_firstprivate:
case OMPC_lastprivate:
case OMPC_reduction:
@@ -12968,6 +13056,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
default:
llvm_unreachable("Clause is not allowed.");
}
@@ -12995,6 +13084,15 @@
return std::string(Out.str());
}
+OMPClause *Sema::ActOnOpenMPWhenClause(Expr *Expr, OpenMPDirectiveKind DKind,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return new (Context)
+ OMPWhenClause(Expr, DKind, Clauses, AStmt, StartLoc, LParenLoc, EndLoc);
+}
+
OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
SourceLocation KindKwLoc,
SourceLocation StartLoc,
@@ -13207,6 +13305,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
default:
llvm_unreachable("Clause is not allowed.");
}
@@ -13445,6 +13544,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
default:
llvm_unreachable("Clause is not allowed.");
}
@@ -13723,6 +13823,7 @@
case OMPC_destroy:
case OMPC_detach:
case OMPC_uses_allocators:
+ case OMPC_when:
default:
llvm_unreachable("Clause is not allowed.");
}
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1486,6 +1486,7 @@
case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPMetaDirectiveClass:
case Stmt::ReturnStmtClass:
case Stmt::SEHExceptStmtClass:
case Stmt::SEHFinallyStmtClass:
Index: clang/lib/Parse/ParseOpenMP.cpp
===================================================================
--- clang/lib/Parse/ParseOpenMP.cpp
+++ clang/lib/Parse/ParseOpenMP.cpp
@@ -2017,6 +2017,7 @@
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute_simd:
+ case OMPD_metadirective:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
break;
@@ -2089,6 +2090,73 @@
bool HasAssociatedStatement = true;
switch (DKind) {
+ case OMPD_metadirective: {
+ ConsumeToken();
+
+ /* Get Stmt and revert back */
+ TentativeParsingAction TPA1(*this);
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ ConsumeAnyToken();
+ }
+ ConsumeAnnotationToken();
+ ParseScope InnerStmtScope(this, Scope::DeclScope,
+ getLangOpts().C99 || getLangOpts().CPlusPlus,
+ Tok.is(tok::l_brace));
+ StmtResult AStmt = ParseStatement();
+ InnerStmtScope.Exit();
+ TPA1.Revert();
+ /*End Get Stmt*/
+
+ ParseScope OMPDirectiveScope(this, ScopeFlags);
+ Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
+
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ Actions.StartOpenMPClause(CKind);
+ OMPClause *Clause = ParseOpenMPMetaClause(DKind, CKind);
+ FirstClauses[(unsigned)CKind].setInt(true);
+ if (Clause) {
+ FirstClauses[(unsigned)CKind].setPointer(Clause);
+ Clauses.push_back(Clause);
+ }
+
+ // Skip ',' if any.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ Actions.EndOpenMPClause();
+ // Consume trailing ')' if any
+ if (Tok.is(tok::r_paren))
+ ConsumeAnyToken();
+ }
+ // End location of the directive.
+ EndLoc = Tok.getLocation();
+ // Consume final annot_pragma_openmp_end.
+ ConsumeAnnotationToken();
+
+ for (auto i = Clauses.begin(); i < Clauses.end(); i++) {
+ OMPWhenClause *WhenClause = dyn_cast<OMPWhenClause>(*i);
+ if (WhenClause->getDKind() == OMPD_unknown)
+ WhenClause->setInnerStmt(AStmt.get());
+ }
+
+ // The body is a block scope like in Lambdas and Blocks.
+ Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
+ ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
+ StmtResult AssociatedStmt =
+ (Sema::CompoundScopeRAII(Actions), ParseStatement());
+ AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+
+ Directive = Actions.ActOnOpenMPExecutableDirective(
+ DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
+ EndLoc);
+
+ // Exit scope.
+ Actions.EndOpenMPDSABlock(Directive.get());
+ OMPDirectiveScope.Exit();
+ break;
+ }
case OMPD_threadprivate: {
// FIXME: Should this be permitted in C++?
if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
@@ -2488,6 +2556,146 @@
T.getCloseLocation(), Data);
}
+OMPClause *Parser::ParseOpenMPMetaClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind) {
+ OMPClause *Clause = nullptr;
+ bool ErrorFound = false;
+ bool WrongDirective = false;
+ SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
+ llvm::omp::Clause_enumSize + 1>
+ FirstClauses(llvm::omp::Clause_enumSize + 1);
+ // Check if it is called from metadirective.
+ if (DKind != OMPD_metadirective) {
+ Diag(Tok, diag::err_omp_unexpected_clause)
+ << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ ErrorFound = true;
+ }
+
+ // Check if clause is allowed for the given directive.
+ if (CKind != OMPC_unknown &&
+ !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
+ Diag(Tok, diag::err_omp_unexpected_clause)
+ << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ ErrorFound = true;
+ WrongDirective = true;
+ }
+
+ if (CKind == OMPC_default || CKind == OMPC_when) {
+ SourceLocation Loc = ConsumeToken();
+ SourceLocation DelimLoc;
+ // Parse '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(CKind).data()))
+ // if (T.expectAndConsume(diag::err_expected_lparen_after,
+ // ClauseName.data()))
+ return nullptr;
+
+ Expr *expr = NULL;
+ if (CKind == OMPC_when) {
+ // parse and get condition expression to pass to the When clause
+ OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
+ parseOMPContextSelectors(Loc, TI);
+ expr = TI.Sets.front().Selectors.front().ScoreOrCondition;
+
+ // Parse ':'
+ if (Tok.is(tok::colon))
+ ConsumeAnyToken();
+ else {
+ Diag(Tok, diag::warn_pragma_expected_colon) << "when clause";
+ return nullptr;
+ }
+ }
+
+ // Parse Directive
+ OpenMPDirectiveKind DirKind = OMPD_unknown;
+ SmallVector<OMPClause *, 5> Clauses;
+ StmtResult AssociatedStmt;
+
+ if (Tok.isNot(tok::r_paren)) {
+ ParsingOpenMPDirectiveRAII DirScope(*this);
+ ParenBraceBracketBalancer BalancerRAIIObj(*this);
+ DeclarationNameInfo DirName;
+ unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope |
+ Scope::OpenMPDirectiveScope;
+
+ DirKind = parseOpenMPDirectiveKind(*this);
+ ConsumeToken();
+ ParseScope OMPDirectiveScope(this, ScopeFlags);
+ Actions.StartOpenMPDSABlock(DirKind, DirName, Actions.getCurScope(), Loc);
+
+ int paren = 0;
+ while (Tok.isNot(tok::r_paren) || paren != 0) {
+ if (Tok.is(tok::l_paren))
+ paren++;
+ if (Tok.is(tok::r_paren))
+ paren--;
+
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ Actions.StartOpenMPClause(CKind);
+
+ OMPClause *Clause = ParseOpenMPClause(
+ DirKind, CKind, !FirstClauses[(unsigned)CKind].getInt());
+ FirstClauses[(unsigned)CKind].setInt(true);
+ if (Clause) {
+ FirstClauses[(unsigned)CKind].setPointer(Clause);
+ Clauses.push_back(Clause);
+ }
+
+ // Skip ',' if any.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ Actions.EndOpenMPClause();
+ }
+
+ Actions.ActOnOpenMPRegionStart(DirKind, getCurScope());
+ ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
+ /* Get Stmt and revert back */
+ TentativeParsingAction TPA(*this);
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ ConsumeAnyToken();
+ }
+ ConsumeAnnotationToken();
+ ParseScope InnerStmtScope(this, Scope::DeclScope,
+ getLangOpts().C99 || getLangOpts().CPlusPlus,
+ Tok.is(tok::l_brace));
+ StmtResult AStmt = ParseStatement();
+ InnerStmtScope.Exit();
+ TPA.Revert();
+ /* End Get Stmt */
+ AssociatedStmt = (Sema::CompoundScopeRAII(Actions), AStmt);
+ AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+
+ StmtResult Directive = Actions.ActOnOpenMPExecutableDirective(
+ DirKind, DirName, OMPD_unknown, Clauses, AssociatedStmt.get(), Loc,
+ Tok.getLocation());
+
+ Actions.EndOpenMPDSABlock(Directive.get());
+ OMPDirectiveScope.Exit();
+ }
+
+ // Parse ')'
+ T.consumeClose();
+
+ if (WrongDirective)
+ return nullptr;
+
+ Clause = Actions.ActOnOpenMPWhenClause(expr, DirKind, Clauses,
+ AssociatedStmt.get(), Loc, DelimLoc,
+ Tok.getLocation());
+ } else {
+ ErrorFound = false;
+ Diag(Tok, diag::err_omp_unexpected_clause)
+ << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ }
+
+ return ErrorFound ? nullptr : Clause;
+}
+
/// Parsing of OpenMP clauses.
///
/// clause:
@@ -2691,6 +2899,7 @@
case OMPC_threadprivate:
case OMPC_uniform:
case OMPC_match:
+ case OMPC_when:
if (!WrongDirective)
Diag(Tok, diag::err_omp_unexpected_clause)
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -3348,6 +3348,7 @@
const RegionCodeGenTy &BodyGen,
OMPTargetDataInfo &InputInfo);
+ void EmitOMPMetaDirective(const OMPMetaDirective &S);
void EmitOMPParallelDirective(const OMPParallelDirective &S);
void EmitOMPSimdDirective(const OMPSimdDirective &S);
void EmitOMPForDirective(const OMPForDirective &S);
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -5310,6 +5310,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
default:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
@@ -6498,6 +6499,11 @@
CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
}
+void CodeGenFunction::EmitOMPMetaDirective(const OMPMetaDirective &S) {
+ Stmt *I = S.getIfStmt();
+ EmitIfStmt(cast<IfStmt>(*I));
+}
+
void CodeGenFunction::EmitOMPParallelMasterTaskLoopDirective(
const OMPParallelMasterTaskLoopDirective &S) {
auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -192,6 +192,9 @@
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
+ case Stmt::OMPMetaDirectiveClass:
+ EmitOMPMetaDirective(cast<OMPMetaDirective>(*S));
+ break;
case Stmt::OMPParallelDirectiveClass:
EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
break;
Index: clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -800,6 +800,7 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
default:
llvm_unreachable("Unexpected directive.");
@@ -881,6 +882,7 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
default:
break;
@@ -1055,6 +1057,7 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
default:
llvm_unreachable("Unexpected directive.");
@@ -1142,6 +1145,7 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
default:
break;
Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7018,6 +7018,7 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
break;
default:
@@ -9044,6 +9045,7 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
default:
llvm_unreachable("Unexpected directive.");
@@ -9850,6 +9852,7 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
default:
llvm_unreachable("Unknown target directive for OpenMP device codegen.");
@@ -10512,6 +10515,7 @@
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
case OMPD_requires:
+ case OMPD_metadirective:
case OMPD_unknown:
default:
llvm_unreachable("Unexpected standalone target data directive.");
Index: clang/lib/Basic/OpenMPKinds.cpp
===================================================================
--- clang/lib/Basic/OpenMPKinds.cpp
+++ clang/lib/Basic/OpenMPKinds.cpp
@@ -180,6 +180,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
break;
default:
break;
@@ -420,6 +421,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
break;
default:
break;
@@ -578,6 +580,9 @@
OpenMPDirectiveKind DKind) {
assert(unsigned(DKind) < llvm::omp::Directive_enumSize);
switch (DKind) {
+ case OMPD_metadirective:
+ CaptureRegions.push_back(OMPD_metadirective);
+ break;
case OMPD_parallel:
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
Index: clang/lib/AST/StmtProfile.cpp
===================================================================
--- clang/lib/AST/StmtProfile.cpp
+++ clang/lib/AST/StmtProfile.cpp
@@ -476,6 +476,11 @@
Profiler->VisitStmt(Evt);
}
+void OMPClauseProfiler::VisitOMPWhenClause(const OMPWhenClause *C) {
+ if (C->getExpr())
+ Profiler->VisitStmt(C->getExpr());
+}
+
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
@@ -847,6 +852,10 @@
P.Visit(*I);
}
+void StmtProfiler::VisitOMPMetaDirective(const OMPMetaDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitOMPLoopDirective(const OMPLoopDirective *S) {
VisitOMPExecutableDirective(S);
}
Index: clang/lib/AST/StmtPrinter.cpp
===================================================================
--- clang/lib/AST/StmtPrinter.cpp
+++ clang/lib/AST/StmtPrinter.cpp
@@ -644,12 +644,25 @@
if (Clause && !Clause->isImplicit()) {
OS << ' ';
Printer.Visit(Clause);
+ if (dyn_cast<OMPMetaDirective>(S)) {
+ OMPWhenClause *c = dyn_cast<OMPWhenClause>(Clause);
+ if (c != NULL) {
+ if (c->getDKind() != llvm::omp::OMPD_unknown)
+ OS << getOpenMPDirectiveName(c->getDKind());
+ OS << ")";
+ }
+ }
}
OS << NL;
if (!ForceNoStmt && S->hasAssociatedStmt())
PrintStmt(S->getRawStmt());
}
+void StmtPrinter::VisitOMPMetaDirective(OMPMetaDirective *Node) {
+ Indent() << "#pragma omp metadirective";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) {
Indent() << "#pragma omp parallel";
PrintOMPExecutableDirective(Node);
Index: clang/lib/AST/StmtOpenMP.cpp
===================================================================
--- clang/lib/AST/StmtOpenMP.cpp
+++ clang/lib/AST/StmtOpenMP.cpp
@@ -191,6 +191,25 @@
llvm::copy(A, getFinalsConditions().begin());
}
+OMPMetaDirective *OMPMetaDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, Stmt *IfStmt) {
+ auto *Dir = createDirective<OMPMetaDirective>(
+ C, Clauses, AssociatedStmt, /*NumChildren=*/1, StartLoc, EndLoc);
+ Dir->setIfStmt(IfStmt);
+ return Dir;
+}
+
+OMPMetaDirective *OMPMetaDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ return createEmptyDirective<OMPMetaDirective>(C, NumClauses,
+ /*HasAssociatedStmt=*/true,
+ /*NumChildren=*/1);
+}
+
OMPParallelDirective *OMPParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
Index: clang/lib/AST/OpenMPClause.cpp
===================================================================
--- clang/lib/AST/OpenMPClause.cpp
+++ clang/lib/AST/OpenMPClause.cpp
@@ -156,6 +156,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
break;
default:
break;
@@ -250,6 +251,7 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
+ case OMPC_when:
break;
default:
break;
@@ -1499,6 +1501,16 @@
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
+void OMPClausePrinter::VisitOMPWhenClause(OMPWhenClause *Node) {
+ if (Node->getExpr() != NULL) {
+ OS << "when(";
+ Node->getExpr()->printPretty(OS, nullptr, Policy, 0);
+ OS << ": ";
+ } else {
+ OS << "default(";
+ }
+}
+
void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << "if(";
if (Node->getNameModifier() != OMPD_unknown)
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -1824,21 +1824,21 @@
/// A CXXBoolLiteralExpr record.
EXPR_CXX_BOOL_LITERAL,
- EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
- EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
- EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).
- EXPR_CXX_THIS, // CXXThisExpr
- EXPR_CXX_THROW, // CXXThrowExpr
- EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
- EXPR_CXX_DEFAULT_INIT, // CXXDefaultInitExpr
- EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
+ EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
+ EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
+ EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).
+ EXPR_CXX_THIS, // CXXThisExpr
+ EXPR_CXX_THROW, // CXXThrowExpr
+ EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
+ EXPR_CXX_DEFAULT_INIT, // CXXDefaultInitExpr
+ EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
EXPR_CXX_NEW, // CXXNewExpr
EXPR_CXX_DELETE, // CXXDeleteExpr
EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
- EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
+ EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr
EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
@@ -1846,41 +1846,42 @@
EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr
EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
- EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr
- EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
+ EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr
+ EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
- EXPR_OPAQUE_VALUE, // OpaqueValueExpr
- EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
- EXPR_TYPE_TRAIT, // TypeTraitExpr
- EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
+ EXPR_OPAQUE_VALUE, // OpaqueValueExpr
+ EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
+ EXPR_TYPE_TRAIT, // TypeTraitExpr
+ EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
- EXPR_PACK_EXPANSION, // PackExpansionExpr
- EXPR_SIZEOF_PACK, // SizeOfPackExpr
- EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
- EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
- EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
- EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
- EXPR_CXX_FOLD, // CXXFoldExpr
- EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr
- EXPR_REQUIRES, // RequiresExpr
+ EXPR_PACK_EXPANSION, // PackExpansionExpr
+ EXPR_SIZEOF_PACK, // SizeOfPackExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK, // SubstNonTypeTemplateParmPackExpr
+ EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
+ EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
+ EXPR_CXX_FOLD, // CXXFoldExpr
+ EXPR_CONCEPT_SPECIALIZATION, // ConceptSpecializationExpr
+ EXPR_REQUIRES, // RequiresExpr
// CUDA
- EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
+ EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
// OpenCL
- EXPR_ASTYPE, // AsTypeExpr
+ EXPR_ASTYPE, // AsTypeExpr
// Microsoft
- EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
+ EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, // MSPropertySubscriptExpr
- EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
- EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
- STMT_SEH_LEAVE, // SEHLeaveStmt
- STMT_SEH_EXCEPT, // SEHExceptStmt
- STMT_SEH_FINALLY, // SEHFinallyStmt
- STMT_SEH_TRY, // SEHTryStmt
+ EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
+ EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
+ STMT_SEH_LEAVE, // SEHLeaveStmt
+ STMT_SEH_EXCEPT, // SEHExceptStmt
+ STMT_SEH_FINALLY, // SEHFinallyStmt
+ STMT_SEH_TRY, // SEHTryStmt
// OpenMP directives
+ STMT_OMP_META_DIRECTIVE,
STMT_OMP_PARALLEL_DIRECTIVE,
STMT_OMP_SIMD_DIRECTIVE,
STMT_OMP_FOR_DIRECTIVE,
@@ -1940,10 +1941,10 @@
EXPR_OMP_ITERATOR,
// ARC
- EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
+ EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
- STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt
- EXPR_LAMBDA, // LambdaExpr
+ STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt
+ EXPR_LAMBDA, // LambdaExpr
STMT_COROUTINE_BODY,
STMT_CORETURN,
EXPR_COAWAIT,
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -10134,6 +10134,11 @@
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init);
// OpenMP directives and clauses.
+ /// Called on well-formed '\#pragma omp metadirective' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPMetaDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
/// Called on correct id-expression from the '#pragma omp
/// threadprivate'.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec,
@@ -10629,6 +10634,12 @@
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// Called on well-formed 'when' clause.
+ OMPClause *ActOnOpenMPWhenClause(Expr *Expr, OpenMPDirectiveKind DKind,
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Called on well-formed 'default' clause.
OMPClause *ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind,
SourceLocation KindLoc,
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -3140,6 +3140,13 @@
/// \param StmtCtx The context in which we're parsing the directive.
StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx);
+ /// Parses clause for metadirective
+ ///
+ /// \param DKind Kind of current directive.
+ /// \param CKind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPMetaClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind);
/// Parses clause of kind \a CKind for directive of a kind \a Kind.
///
/// \param DKind Kind of current directive.
Index: clang/include/clang/Basic/StmtNodes.td
===================================================================
--- clang/include/clang/Basic/StmtNodes.td
+++ clang/include/clang/Basic/StmtNodes.td
@@ -217,6 +217,7 @@
// OpenMP Directives.
def OMPExecutableDirective : StmtNode<Stmt, 1>;
+def OMPMetaDirective : StmtNode<OMPExecutableDirective>;
def OMPLoopDirective : StmtNode<OMPExecutableDirective, 1>;
def OMPParallelDirective : StmtNode<OMPExecutableDirective>;
def OMPSimdDirective : StmtNode<OMPLoopDirective>;
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10366,6 +10366,9 @@
: Note<"jump bypasses OpenMP structured block">;
def note_omp_exits_structured_block
: Note<"jump exits scope of OpenMP structured block">;
+def err_omp_misplaced_default_clause : Error<
+ "misplaced default clause! Only one default clause is allowed in "
+ "metadirective in the end">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
Index: clang/include/clang/AST/StmtOpenMP.h
===================================================================
--- clang/include/clang/AST/StmtOpenMP.h
+++ clang/include/clang/AST/StmtOpenMP.h
@@ -362,6 +362,44 @@
}
};
+/// This represents '#pragma omp metadirective' directive.
+///
+/// \code
+/// #pragma omp metadirective when(user={condition(N>10)}: parallel for)
+/// \endcode
+/// In this example directive '#pragma omp metadirective' has clauses 'when'
+/// with a dynamic user condition to check if a variable 'N > 10'
+///
+class OMPMetaDirective final : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+ Stmt *IfStmt;
+
+ OMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(OMPMetaDirectiveClass,
+ llvm::omp::OMPD_metadirective, StartLoc,
+ EndLoc) {}
+ explicit OMPMetaDirective()
+ : OMPExecutableDirective(OMPMetaDirectiveClass,
+ llvm::omp::OMPD_metadirective, SourceLocation(),
+ SourceLocation()) {}
+
+public:
+ static OMPMetaDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, Stmt *IfStmt);
+ static OMPMetaDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ EmptyShell);
+
+ void setIfStmt(Stmt *stmt) { IfStmt = stmt; }
+ Stmt *getIfStmt() const { return IfStmt; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPMetaDirectiveClass;
+ }
+};
+
/// This represents '#pragma omp parallel' directive.
///
/// \code
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2768,6 +2768,9 @@
return TraverseOMPExecutableDirective(S);
}
+DEF_TRAVERSE_STMT(OMPMetaDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPParallelDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
@@ -3022,6 +3025,12 @@
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPWhenClause(OMPWhenClause *C) {
+ TRY_TO(TraverseStmt(C->getExpr()));
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) {
return true;
Index: clang/include/clang/AST/OpenMPClause.h
===================================================================
--- clang/include/clang/AST/OpenMPClause.h
+++ clang/include/clang/AST/OpenMPClause.h
@@ -860,6 +860,86 @@
}
};
+/// This represents 'when' clause in the '#pragma omp ...' directive
+///
+/// \code
+/// #pragma omp metadirective when(user={condition(N<10)}: parallel)
+/// \endcode
+/// In this example directive '#pragma omp metadirective' has simple 'when'
+/// clause with user defined condition.
+class OMPWhenClause final : public OMPClause {
+ friend class OMPClauseReader;
+
+ Expr *CondExpr;
+ OpenMPDirectiveKind DKind;
+ ArrayRef<OMPClause *> Clauses;
+ Stmt *InnerStmt;
+
+ /// Location of '('.
+ SourceLocation LParenLoc;
+
+ void setExpr(Expr *E) { CondExpr = E; }
+
+public:
+ /// Build 'when' clause with argument \a A ('none' or 'shared').
+ ///
+ /// \param A Argument of the clause ('none' or 'shared').
+ /// \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.
+ OMPWhenClause(Expr *expr, OpenMPDirectiveKind dKind,
+ ArrayRef<OMPClause *> clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(llvm::omp::OMPC_when, StartLoc, EndLoc), CondExpr(expr),
+ DKind(dKind), Clauses(clauses), InnerStmt(AStmt), LParenLoc(LParenLoc) {
+ }
+
+ /// Build an empty clause.
+ OMPWhenClause()
+ : OMPClause(llvm::omp::OMPC_when, SourceLocation(), SourceLocation()) {}
+
+ /// Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+ /// Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// Returns the associated condition expression
+ Expr *getExpr() const { return CondExpr; }
+
+ /// Returns the directive variant kind
+ OpenMPDirectiveKind getDKind() { return DKind; }
+
+ /// Returns the clauses associated with the directive variants
+ ArrayRef<OMPClause *> getClauses() { return Clauses; }
+
+ /// Set the inner statement
+ void setInnerStmt(Stmt *s) { InnerStmt = s; }
+
+ /// Returns the inner statement
+ Stmt *getInnerStmt() { return InnerStmt; }
+
+ 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_when;
+ }
+};
+
/// This represents 'default' clause in the '#pragma omp ...' directive.
///
/// \code
Index: clang/include/clang-c/Index.h
===================================================================
--- clang/include/clang-c/Index.h
+++ clang/include/clang-c/Index.h
@@ -2568,7 +2568,11 @@
*/
CXCursor_OMPScanDirective = 287,
- CXCursor_LastStmt = CXCursor_OMPScanDirective,
+ /** OpenMP metadirective directive.
+ */
+ CXCursor_OMPMetaDirective = 288,
+
+ CXCursor_LastStmt = CXCursor_OMPMetaDirective,
/**
* Cursor that represents the translation unit itself.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits