[OpenMP 5.1] Parsing and Sema support for scope directive
structured-block where clause is one of the following: private(list) reduction([reduction-modifier ,] reduction-identifier : list) nowait Differential Revision: https://reviews.llvm.org/D157933
This commit is contained in:
parent
e4cb692526
commit
e4c7298bea
@ -321,7 +321,7 @@ implementation.
|
||||
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
|
||||
| misc | error directive | :none:`unclaimed` | |
|
||||
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
|
||||
| misc | scope construct | :none:`unclaimed` | |
|
||||
| misc | scope construct | :none:`worked on` | D157933 |
|
||||
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
|
||||
| misc | routines for controlling and querying team regions | :none:`unclaimed` | |
|
||||
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
|
||||
|
||||
@ -2136,7 +2136,11 @@ enum CXCursorKind {
|
||||
*/
|
||||
CXCursor_OMPErrorDirective = 305,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPErrorDirective,
|
||||
/** OpenMP scope directive.
|
||||
*/
|
||||
CXCursor_OMPScopeDirective = 306,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPScopeDirective,
|
||||
|
||||
/**
|
||||
* Cursor that represents the translation unit itself.
|
||||
|
||||
@ -2980,6 +2980,9 @@ DEF_TRAVERSE_STMT(OMPSectionsDirective,
|
||||
DEF_TRAVERSE_STMT(OMPSectionDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPScopeDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPSingleDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
|
||||
@ -1931,6 +1931,57 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp scope' directive.
|
||||
/// \code
|
||||
/// #pragma omp scope private(a,b) nowait
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp scope' has clauses 'private' with
|
||||
/// the variables 'a' and 'b' and nowait.
|
||||
///
|
||||
class OMPScopeDirective 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.
|
||||
///
|
||||
OMPScopeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
|
||||
: OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
|
||||
StartLoc, EndLoc) {}
|
||||
|
||||
/// Build an empty directive.
|
||||
///
|
||||
explicit OMPScopeDirective()
|
||||
: OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
|
||||
SourceLocation(), SourceLocation()) {}
|
||||
|
||||
public:
|
||||
/// Creates directive.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending Location of the directive.
|
||||
/// \param AssociatedStmt Statement, associated with the directive.
|
||||
///
|
||||
static OMPScopeDirective *Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt);
|
||||
|
||||
/// Creates an empty directive.
|
||||
///
|
||||
/// \param C AST context.
|
||||
///
|
||||
static OMPScopeDirective *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses, EmptyShell);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPScopeDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp single' directive.
|
||||
///
|
||||
/// \code
|
||||
|
||||
@ -259,6 +259,7 @@ def OMPTargetUpdateDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTeamsDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPCancellationPointDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPCancelDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPScopeDirective : StmtNode<OMPExecutableDirective>;
|
||||
def OMPTaskLoopDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPTaskLoopSimdDirective : StmtNode<OMPLoopDirective>;
|
||||
def OMPMasterTaskLoopDirective : StmtNode<OMPLoopDirective>;
|
||||
|
||||
@ -11554,6 +11554,11 @@ public:
|
||||
/// associated statement.
|
||||
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed '\#pragma omp scope' after parsing of the
|
||||
/// associated statement.
|
||||
StmtResult ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed '\#pragma omp single' after parsing of the
|
||||
/// associated statement.
|
||||
StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
|
||||
|
||||
@ -1995,6 +1995,7 @@ enum StmtCode {
|
||||
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
|
||||
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
|
||||
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
|
||||
STMT_OMP_SCOPE_DIRECTIVE,
|
||||
STMT_OMP_INTEROP_DIRECTIVE,
|
||||
STMT_OMP_DISPATCH_DIRECTIVE,
|
||||
STMT_OMP_MASKED_DIRECTIVE,
|
||||
|
||||
@ -531,6 +531,23 @@ OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C,
|
||||
/*HasAssociatedStmt=*/true);
|
||||
}
|
||||
|
||||
OMPScopeDirective *OMPScopeDirective::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt) {
|
||||
return createDirective<OMPScopeDirective>(C, Clauses, AssociatedStmt,
|
||||
/*NumChildren=*/0, StartLoc,
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
OMPScopeDirective *OMPScopeDirective::CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses,
|
||||
EmptyShell) {
|
||||
return createEmptyDirective<OMPScopeDirective>(C, NumClauses,
|
||||
/*HasAssociatedStmt=*/true);
|
||||
}
|
||||
|
||||
OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc,
|
||||
|
||||
@ -777,6 +777,11 @@ void StmtPrinter::VisitOMPSectionDirective(OMPSectionDirective *Node) {
|
||||
PrintOMPExecutableDirective(Node);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitOMPScopeDirective(OMPScopeDirective *Node) {
|
||||
Indent() << "#pragma omp scope";
|
||||
PrintOMPExecutableDirective(Node);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) {
|
||||
Indent() << "#pragma omp single";
|
||||
PrintOMPExecutableDirective(Node);
|
||||
|
||||
@ -996,6 +996,10 @@ void StmtProfiler::VisitOMPSectionDirective(const OMPSectionDirective *S) {
|
||||
VisitOMPExecutableDirective(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOMPScopeDirective(const OMPScopeDirective *S) {
|
||||
VisitOMPExecutableDirective(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOMPSingleDirective(const OMPSingleDirective *S) {
|
||||
VisitOMPExecutableDirective(S);
|
||||
}
|
||||
|
||||
@ -848,6 +848,7 @@ void clang::getOpenMPCaptureRegions(
|
||||
case OMPD_atomic:
|
||||
case OMPD_target_data:
|
||||
case OMPD_distribute_simd:
|
||||
case OMPD_scope:
|
||||
case OMPD_dispatch:
|
||||
CaptureRegions.push_back(OMPD_unknown);
|
||||
break;
|
||||
|
||||
@ -409,6 +409,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
|
||||
case Stmt::OMPDispatchDirectiveClass:
|
||||
llvm_unreachable("Dispatch directive not supported yet.");
|
||||
break;
|
||||
case Stmt::OMPScopeDirectiveClass:
|
||||
llvm_unreachable("scope not supported with FE outlining");
|
||||
case Stmt::OMPMaskedDirectiveClass:
|
||||
EmitOMPMaskedDirective(cast<OMPMaskedDirective>(*S));
|
||||
break;
|
||||
|
||||
@ -2418,6 +2418,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||
case OMPD_distribute_simd:
|
||||
case OMPD_target_parallel_for_simd:
|
||||
case OMPD_target_simd:
|
||||
case OMPD_scope:
|
||||
case OMPD_teams_distribute:
|
||||
case OMPD_teams_distribute_simd:
|
||||
case OMPD_teams_distribute_parallel_for_simd:
|
||||
@ -2810,6 +2811,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||
case OMPD_target_teams_loop:
|
||||
case OMPD_parallel_loop:
|
||||
case OMPD_target_parallel_loop:
|
||||
case OMPD_scope:
|
||||
case OMPD_taskloop:
|
||||
case OMPD_taskloop_simd:
|
||||
case OMPD_master_taskloop:
|
||||
|
||||
@ -1496,6 +1496,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
|
||||
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
|
||||
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
|
||||
case Stmt::OMPTargetUpdateDirectiveClass:
|
||||
case Stmt::OMPScopeDirectiveClass:
|
||||
case Stmt::OMPTaskDirectiveClass:
|
||||
case Stmt::OMPTaskgroupDirectiveClass:
|
||||
case Stmt::OMPTaskLoopDirectiveClass:
|
||||
|
||||
@ -3709,6 +3709,7 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
|
||||
S->getDirectiveKind() == OMPD_section ||
|
||||
S->getDirectiveKind() == OMPD_master ||
|
||||
S->getDirectiveKind() == OMPD_masked ||
|
||||
S->getDirectiveKind() == OMPD_scope ||
|
||||
isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
|
||||
Visit(S->getAssociatedStmt());
|
||||
return;
|
||||
@ -4319,6 +4320,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
|
||||
case OMPD_distribute:
|
||||
case OMPD_distribute_simd:
|
||||
case OMPD_ordered:
|
||||
case OMPD_scope:
|
||||
case OMPD_target_data:
|
||||
case OMPD_dispatch: {
|
||||
Sema::CapturedParamNameType Params[] = {
|
||||
@ -5130,7 +5132,10 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
|
||||
diag::note_omp_previous_critical_region);
|
||||
return true;
|
||||
}
|
||||
} else if (CurrentRegion == OMPD_barrier) {
|
||||
} else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
|
||||
// OpenMP 5.1 [2.22, Nesting of Regions]
|
||||
// A scope region may not be closely nested inside a worksharing, loop,
|
||||
// task, taskloop, critical, ordered, atomic, or masked region.
|
||||
// OpenMP 5.1 [2.22, Nesting of Regions]
|
||||
// A barrier region may not be closely nested inside a worksharing, loop,
|
||||
// task, taskloop, critical, ordered, atomic, or masked region.
|
||||
@ -6449,6 +6454,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
|
||||
if (LangOpts.OpenMP >= 50)
|
||||
AllowedNameModifiers.push_back(OMPD_simd);
|
||||
break;
|
||||
case OMPD_scope:
|
||||
Res =
|
||||
ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
|
||||
break;
|
||||
case OMPD_parallel_master:
|
||||
Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
|
||||
StartLoc, EndLoc);
|
||||
@ -23904,6 +23913,17 @@ OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
|
||||
Vars);
|
||||
}
|
||||
|
||||
StmtResult Sema::ActOnOpenMPScopeDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
if (!AStmt)
|
||||
return StmtError();
|
||||
|
||||
setFunctionHasBranchProtectedScope();
|
||||
|
||||
return OMPScopeDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
||||
@ -8925,6 +8925,17 @@ TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) {
|
||||
return Res;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPScopeDirective(OMPScopeDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_scope, DirName, nullptr,
|
||||
D->getBeginLoc());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {
|
||||
|
||||
@ -2391,6 +2391,11 @@ void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) {
|
||||
D->setHasCancel(Record.readBool());
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOMPScopeDirective(OMPScopeDirective *D) {
|
||||
VisitStmt(D);
|
||||
VisitOMPExecutableDirective(D);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) {
|
||||
VisitStmt(D);
|
||||
VisitOMPExecutableDirective(D);
|
||||
@ -3352,6 +3357,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||
S = OMPSectionDirective::CreateEmpty(Context, Empty);
|
||||
break;
|
||||
|
||||
case STMT_OMP_SCOPE_DIRECTIVE:
|
||||
S = OMPScopeDirective::CreateEmpty(
|
||||
Context, Record[ASTStmtReader::NumStmtFields], Empty);
|
||||
break;
|
||||
|
||||
case STMT_OMP_SINGLE_DIRECTIVE:
|
||||
S = OMPSingleDirective::CreateEmpty(
|
||||
Context, Record[ASTStmtReader::NumStmtFields], Empty);
|
||||
|
||||
@ -2308,6 +2308,12 @@ void ASTStmtWriter::VisitOMPSectionDirective(OMPSectionDirective *D) {
|
||||
Code = serialization::STMT_OMP_SECTION_DIRECTIVE;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOMPScopeDirective(OMPScopeDirective *D) {
|
||||
VisitStmt(D);
|
||||
VisitOMPExecutableDirective(D);
|
||||
Code = serialization::STMT_OMP_SCOPE_DIRECTIVE;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) {
|
||||
VisitStmt(D);
|
||||
VisitOMPExecutableDirective(D);
|
||||
|
||||
@ -1746,6 +1746,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
||||
case Stmt::OMPForSimdDirectiveClass:
|
||||
case Stmt::OMPSectionsDirectiveClass:
|
||||
case Stmt::OMPSectionDirectiveClass:
|
||||
case Stmt::OMPScopeDirectiveClass:
|
||||
case Stmt::OMPSingleDirectiveClass:
|
||||
case Stmt::OMPMasterDirectiveClass:
|
||||
case Stmt::OMPCriticalDirectiveClass:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
88
clang/test/OpenMP/scope_ast_print.cpp
Normal file
88
clang/test/OpenMP/scope_ast_print.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
|
||||
//RUN: -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
|
||||
//RUN: -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -ast-dump %s | FileCheck %s --check-prefix=DUMP
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
|
||||
//RUN: -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -emit-pch -o %t %s
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
|
||||
//RUN: -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu\
|
||||
//RUN: -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
int foo1() {
|
||||
int a;
|
||||
int i = 1;
|
||||
#pragma omp scope private(a) reduction(+:i) nowait
|
||||
{
|
||||
a = 123;
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//DUMP: FunctionDecl {{.*}}foo1 'int ()'
|
||||
//DUMP: OMPScopeDirective
|
||||
//DUMP: OMPPrivateClause
|
||||
//DUMP: DeclRefExpr {{.*}}'int' lvalue Var{{.*}}'a' 'int'
|
||||
//DUMP: OMPReductionClause
|
||||
//DUMP: DeclRefExpr {{.*}}'int' lvalue Var{{.*}}'i' 'int'
|
||||
//DUMP: OMPNowaitClause
|
||||
//PRINT: #pragma omp scope private(a) reduction(+: i) nowait
|
||||
|
||||
template <typename T>
|
||||
T run() {
|
||||
T a;
|
||||
T b;
|
||||
|
||||
#pragma omp scope private(a) reduction(*:b)
|
||||
{
|
||||
b *= a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
int template_test() {
|
||||
double d;
|
||||
d = run<double>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//DUMP: FunctionTemplateDecl {{.*}}run
|
||||
//DUMP: TemplateTypeParmDecl {{.*}}referenced typename depth 0 index 0 T
|
||||
//DUMP: FunctionDecl {{.*}}run 'T ()'
|
||||
//DUMP: OMPScopeDirective
|
||||
//DUMP: OMPPrivateClause
|
||||
//DUMP: DeclRefExpr {{.*}}'T' lvalue Var {{.*}} 'a' 'T'
|
||||
//DUMP: OMPReductionClause
|
||||
//DUMP: DeclRefExpr {{.*}}'T' lvalue Var {{.*}} 'b' 'T'
|
||||
//DUMP: FunctionDecl {{.*}}used run 'double ()'
|
||||
//DUMP: TemplateArgument type 'double'
|
||||
//DUMP: BuiltinType {{.*}}'double'
|
||||
//DUMP: OMPScopeDirective
|
||||
//DUMP: OMPPrivateClause
|
||||
//DUMP: DeclRefExpr {{.*}}'double':'double' lvalue Var {{.*}} 'a' 'double':'double'
|
||||
//DUMP: OMPReductionClause
|
||||
//DUMP: DeclRefExpr {{.*}}'double':'double' lvalue Var {{.*}} 'b' 'double':'double'
|
||||
//PRINT: #pragma omp scope private(a) reduction(*: b)
|
||||
#endif // HEADER
|
||||
13
clang/test/OpenMP/scope_messages.cpp
Normal file
13
clang/test/OpenMP/scope_messages.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 %s -verify=expected,omp51
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 %s -verify=expected,omp51
|
||||
|
||||
void test1()
|
||||
{
|
||||
int var1;
|
||||
int var2;
|
||||
int var3 = 1;
|
||||
|
||||
// expected-error@+1 {{directive '#pragma omp scope' cannot contain more than one 'nowait' clause}} //omp51-error@+1{{unexpected OpenMP clause 'firstprivate' in directive '#pragma omp scope'}}
|
||||
#pragma omp scope private(var1) firstprivate(var3) nowait nowait
|
||||
{ var1 = 123; ++var2; var3 = 2;}
|
||||
}
|
||||
@ -5951,6 +5951,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||
return cxstring::createRef("OMPSectionsDirective");
|
||||
case CXCursor_OMPSectionDirective:
|
||||
return cxstring::createRef("OMPSectionDirective");
|
||||
case CXCursor_OMPScopeDirective:
|
||||
return cxstring::createRef("OMPScopeDirective");
|
||||
case CXCursor_OMPSingleDirective:
|
||||
return cxstring::createRef("OMPSingleDirective");
|
||||
case CXCursor_OMPMasterDirective:
|
||||
|
||||
@ -680,6 +680,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
||||
case Stmt::OMPSectionDirectiveClass:
|
||||
K = CXCursor_OMPSectionDirective;
|
||||
break;
|
||||
case Stmt::OMPScopeDirectiveClass:
|
||||
K = CXCursor_OMPScopeDirective;
|
||||
break;
|
||||
case Stmt::OMPSingleDirectiveClass:
|
||||
K = CXCursor_OMPSingleDirective;
|
||||
break;
|
||||
|
||||
@ -1979,6 +1979,15 @@ def OMP_BeginAssumes : Directive<"begin assumes"> {}
|
||||
def OMP_EndAssumes : Directive<"end assumes"> {}
|
||||
def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {}
|
||||
def OMP_EndDeclareVariant : Directive<"end declare variant"> {}
|
||||
def OMP_scope : Directive<"scope"> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<OMPC_Private, 51>,
|
||||
VersionedClause<OMPC_Reduction, 51>,
|
||||
];
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<OMPC_NoWait, 51>
|
||||
];
|
||||
}
|
||||
def OMP_ParallelWorkshare : Directive<"parallel workshare"> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<OMPC_Allocate>,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user