[OPENMP] parsing of clause 'safelen' (for directive 'omp simd')

llvm-svn: 204428
This commit is contained in:
Alexey Bataev 2014-03-21 04:51:18 +00:00
parent db55b02e1c
commit 62c87d2509
17 changed files with 363 additions and 6 deletions

View File

@ -2367,6 +2367,13 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(
return true;
}
template<typename Derived>
bool DataRecursiveASTVisitor<Derived>::VisitOMPSafelenClause(
OMPSafelenClause *C) {
TraverseStmt(C->getSafelen());
return true;
}
template<typename Derived>
bool DataRecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
return true;

View File

@ -250,6 +250,62 @@ public:
StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); }
};
/// \brief This represents 'safelen' clause in the '#pragma omp ...'
/// directive.
///
/// \code
/// #pragma omp simd safelen(4)
/// \endcode
/// In this example directive '#pragma omp simd' has clause 'safelen'
/// with single expression '4'.
/// If the safelen clause is used then no two iterations executed
/// concurrently with SIMD instructions can have a greater distance
/// in the logical iteration space than its value. The parameter of
/// the safelen clause must be a constant positive integer expression.
///
class OMPSafelenClause : public OMPClause {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
/// \brief Safe iteration space distance.
Stmt *Safelen;
/// \brief Set safelen.
void setSafelen(Expr *Len) { Safelen = Len; }
public:
/// \brief Build 'safelen' clause.
///
/// \param Len Expression associated with this clause.
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
///
OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc),
Safelen(Len) {}
/// \brief Build an empty clause.
///
explicit OMPSafelenClause()
: OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()),
LParenLoc(SourceLocation()), Safelen(0) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Return safe iteration space distance.
Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_safelen;
}
StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); }
};
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
///
/// \code

View File

@ -2405,6 +2405,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
TraverseStmt(C->getSafelen());
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
return true;

View File

@ -37,12 +37,13 @@ OPENMP_DIRECTIVE(simd)
// OpenMP clauses.
OPENMP_CLAUSE(if, OMPIfClause)
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
OPENMP_CLAUSE(safelen, OMPSafelenClause)
OPENMP_CLAUSE(default, OMPDefaultClause)
OPENMP_CLAUSE(private, OMPPrivateClause)
OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
OPENMP_CLAUSE(shared, OMPSharedClause)
// Clauses allowed for OpenMP directives.
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
OPENMP_PARALLEL_CLAUSE(num_threads)
OPENMP_PARALLEL_CLAUSE(default)
@ -52,6 +53,7 @@ OPENMP_PARALLEL_CLAUSE(shared)
// FIXME: more clauses allowed for directive 'omp simd'.
OPENMP_SIMD_CLAUSE(private)
OPENMP_SIMD_CLAUSE(safelen)
// Static attributes for 'default' clause.
OPENMP_DEFAULT_KIND(none)

View File

@ -7114,6 +7114,8 @@ private:
void InitDataSharingAttributesStack();
void DestroyDataSharingAttributesStack();
ExprResult PerformImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op);
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op,
OpenMPClauseKind CKind);
public:
/// \brief Called on start of new data sharing attribute block.
void StartOpenMPDSABlock(OpenMPDirectiveKind K,
@ -7169,6 +7171,11 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'safelen' clause.
OMPClause *ActOnOpenMPSafelenClause(Expr *Length,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
unsigned Argument,

View File

@ -613,6 +613,12 @@ void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
OS << ")";
}
void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
OS << "safelen(";
Node->getSafelen()->printPretty(OS, 0, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
OS << "default("
<< getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())

View File

@ -274,6 +274,11 @@ void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
Profiler->VisitStmt(C->getNumThreads());
}
void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) {
if (C->getSafelen())
Profiler->VisitStmt(C->getSafelen());
}
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
template<typename T>

View File

@ -79,6 +79,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_threadprivate:
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
@ -104,6 +105,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_threadprivate:
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:

View File

@ -257,7 +257,8 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// \brief Parsing of OpenMP clauses.
///
/// clause:
/// default-clause|private-clause|firstprivate-clause|shared-clause
/// if-clause | num_threads-clause | safelen-clause | default-clause |
/// private-clause | firstprivate-clause | shared-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@ -273,9 +274,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
switch (CKind) {
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
// OpenMP [2.5, Restrictions]
// At most one if clause can appear on the directive.
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
// Only one safelen clause can appear on a simd directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
@ -321,6 +325,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
/// if-clause:
/// 'if' '(' expression ')'
///
/// num_threads-clause:
/// 'num_threads' '(' expression ')'
///
/// safelen-clause:
/// 'safelen' '(' expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
SourceLocation Loc = ConsumeToken();

View File

@ -761,6 +761,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
case OMPC_num_threads:
Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_safelen:
Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_default:
case OMPC_private:
case OMPC_firstprivate:
@ -868,6 +871,38 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
EndLoc);
}
ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
OpenMPClauseKind CKind) {
if (!E)
return ExprError();
if (E->isValueDependent() || E->isTypeDependent() ||
E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
return Owned(E);
llvm::APSInt Result;
ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
if (ICE.isInvalid())
return ExprError();
if (!Result.isStrictlyPositive()) {
Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
<< getOpenMPClauseName(CKind) << E->getSourceRange();
return ExprError();
}
return ICE;
}
OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
// OpenMP [2.8.1, simd construct, Description]
// The parameter of the safelen clause must be a constant
// positive integer expression.
ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
if (Safelen.isInvalid())
return 0;
return new (Context)
OMPSafelenClause(Safelen.take(), StartLoc, LParenLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
unsigned Argument,
SourceLocation ArgumentLoc,
@ -883,6 +918,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
@ -956,6 +992,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_default:
case OMPC_threadprivate:
case OMPC_unknown:

View File

@ -1323,6 +1323,16 @@ public:
LParenLoc, EndLoc);
}
/// \brief Build a new OpenMP 'safelen' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPSafelenClause(Expr *Len, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc);
}
/// \brief Build a new OpenMP 'default' clause.
///
/// By default, performs semantic analysis to build the new statement.
@ -6340,6 +6350,16 @@ TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {
C->getLocEnd());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSafelenClause(OMPSafelenClause *C) {
ExprResult E = getDerived().TransformExpr(C->getSafelen());
if (E.isInvalid())
return 0;
return getDerived().RebuildOMPSafelenClause(
E.take(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
template<typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {

View File

@ -1677,6 +1677,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_num_threads:
C = new (Context) OMPNumThreadsClause();
break;
case OMPC_safelen:
C = new (Context) OMPSafelenClause();
break;
case OMPC_default:
C = new (Context) OMPDefaultClause();
break;
@ -1707,6 +1710,11 @@ void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) {
C->setSafelen(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
C->setDefaultKind(
static_cast<OpenMPDefaultClauseKind>(Record[Idx++]));

View File

@ -1684,6 +1684,11 @@ void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {
Writer->Writer.AddStmt(C->getSafelen());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
Record.push_back(C->getDefaultKind());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);

View File

@ -33,12 +33,22 @@ template<class T> struct S {
T val;
// CHECK: T res;
// CHECK: T val;
#pragma omp simd private(val)
// CHECK-NEXT: #pragma omp simd private(val)
#pragma omp simd private(val) safelen(7)
// CHECK-NEXT: #pragma omp simd private(val) safelen(7)
for (T i = 7; i < m_a; ++i) {
val = v[i-7] + m_a;
res = val;
}
const T clen = 3;
// CHECK: T clen = 3;
#pragma omp simd safelen(clen-1)
// CHECK-NEXT: #pragma omp simd safelen(clen - 1)
for(T i = clen+2; i < 20; ++i) {
// CHECK-NEXT: for (T i = clen + 2; i < 20; ++i) {
v[i] = v[v-clen] + 1;
// CHECK-NEXT: v[i] = v[v - clen] + 1;
}
// CHECK-NEXT: }
return res;
}
~S()
@ -46,6 +56,24 @@ template<class T> struct S {
T m_a;
};
template<int LEN> struct S2 {
static void func(int n, float *a, float *b, float *c) {
#pragma omp simd safelen(LEN)
for(int i = 0; i < n; i++) {
c[i] = a[i] + b[i];
}
}
};
// S2<4>::func is called below in main.
// CHECK: template <int LEN = 4> struct S2 {
// CHECK-NEXT: static void func(int n, float *a, float *b, float *c) {
// CHECK-NEXT: #pragma omp simd safelen(4)
// CHECK-NEXT: for (int i = 0; i < n; i++) {
// CHECK-NEXT: c[i] = a[i] + b[i];
// CHECK-NEXT: }
// CHECK-NEXT: }
int main (int argc, char **argv) {
int b = argc, c, d, e, f, g;
int k1=0,k2=0;
@ -69,11 +97,16 @@ int main (int argc, char **argv) {
for (int i = 0; i < 10; ++i)foo();
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: foo();
#pragma omp simd
// CHECK-NEXT: #pragma omp simd
const int CLEN = 4;
// CHECK-NEXT: const int CLEN = 4;
#pragma omp simd safelen(CLEN)
// CHECK-NEXT: #pragma omp simd safelen(CLEN)
for (int i = 0; i < 10; ++i)foo();
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: foo();
float arr[16];
S2<4>::func(0,arr,arr,arr);
return (0);
}

View File

@ -77,6 +77,75 @@ void test_non_identifiers()
for (i = 0; i < 16; ++i) ;
}
extern int foo();
void test_safelen()
{
int i;
// expected-error@+1 {{expected '('}}
#pragma omp simd safelen
for (i = 0; i < 16; ++i) ;
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(
for (i = 0; i < 16; ++i) ;
// expected-error@+1 {{expected expression}}
#pragma omp simd safelen()
for (i = 0; i < 16; ++i) ;
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(,
for (i = 0; i < 16; ++i) ;
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(,)
for (i = 0; i < 16; ++i) ;
// expected-warning@+2 {{extra tokens at the end of '#pragma omp simd' are ignored}}
// expected-error@+1 {{expected '('}}
#pragma omp simd safelen 4)
for (i = 0; i < 16; ++i) ;
// expected-error@+2 {{expected ')'}}
// expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(4
for (i = 0; i < 16; ++i) ;
// expected-error@+2 {{expected ')'}}
// expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(4,
for (i = 0; i < 16; ++i) ;
// expected-error@+2 {{expected ')'}}
// expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(4,)
for (i = 0; i < 16; ++i) ;
// xxpected-error@+1 {{expected expression}}
#pragma omp simd safelen(4)
for (i = 0; i < 16; ++i) ;
// expected-error@+2 {{expected ')'}}
// expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(4 4)
for (i = 0; i < 16; ++i) ;
// expected-error@+2 {{expected ')'}}
// expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(4,,4)
for (i = 0; i < 16; ++i) ;
#pragma omp simd safelen(4)
for (i = 0; i < 16; ++i) ;
// expected-error@+2 {{expected ')'}}
// expected-note@+1 {{to match this '('}}
#pragma omp simd safelen(4,8)
for (i = 0; i < 16; ++i) ;
// expected-error@+1 {{expression is not an integer constant expression}}
#pragma omp simd safelen(2.5)
for (i = 0; i < 16; ++i);
// expected-error@+1 {{expression is not an integer constant expression}}
#pragma omp simd safelen(foo())
for (i = 0; i < 16; ++i);
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
#pragma omp simd safelen(-5)
for (i = 0; i < 16; ++i);
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
#pragma omp simd safelen(0)
for (i = 0; i < 16; ++i);
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
#pragma omp simd safelen(5-5)
for (i = 0; i < 16; ++i);
}
void test_private()
{
int i;
@ -121,3 +190,4 @@ void test_firstprivate()
#pragma omp simd firstprivate(
for (i = 0; i < 16; ++i) ;
}

View File

@ -0,0 +1,79 @@
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s
void foo() {
}
bool foobool(int argc) {
return argc;
}
struct S1; // expected-note {{declared here}}
template <class T, typename S, int N, int ST> // expected-note {{declared here}}
T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
#pragma omp simd safelen // expected-error {{expected '(' after 'safelen'}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp simd safelen () // expected-error {{expected expression}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
// expected-error@+2 2 {{expression is not an integral constant expression}}
// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
#pragma omp simd safelen (argc
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}}
#pragma omp simd safelen (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp simd safelen ((ST > 0) ? 1 + ST : 2)
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+3 2 {{directive '#pragma omp simd' cannot contain more than one 'safelen' clause}}
// expected-error@+2 2 {{argument to 'safelen' clause must be a positive integer value}}
// expected-error@+1 2 {{expression is not an integral constant expression}}
#pragma omp simd safelen (foobool(argc)), safelen (true), safelen (-5)
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp simd safelen (S) // expected-error {{'S' does not refer to a value}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
// expected-error@+1 2 {{expression is not an integral constant expression}}
#pragma omp simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp simd safelen (4)
for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
#pragma omp simd safelen (N) // expected-error {{argument to 'safelen' clause must be a positive integer value}}
for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
return argc;
}
int main(int argc, char **argv) {
#pragma omp simd safelen // expected-error {{expected '(' after 'safelen'}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp simd safelen () // expected-error {{expected expression}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+3 {{expression is not an integral constant expression}}
// expected-error@+2 2 {{directive '#pragma omp simd' cannot contain more than one 'safelen' clause}}
// expected-error@+1 2 {{argument to 'safelen' clause must be a positive integer value}}
#pragma omp simd safelen (foobool(argc)), safelen (true), safelen (-5)
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
#pragma omp simd safelen (S1) // expected-error {{'S1' does not refer to a value}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+1 {{expression is not an integral constant expression}}
#pragma omp simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
// expected-error@+3 {{statement after '#pragma omp simd' must be a for loop}}
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
#pragma omp simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
foo();
// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
return tmain<int, char, 12, 4>(argc, argv);
}

View File

@ -1932,6 +1932,10 @@ void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
Visitor->AddStmt(C->getNumThreads());
}
void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) {
Visitor->AddStmt(C->getSafelen());
}
void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
template<typename T>