forked from OSchip/llvm-project
[OPENMP] parsing of clause 'safelen' (for directive 'omp simd')
llvm-svn: 204428
This commit is contained in:
parent
db55b02e1c
commit
62c87d2509
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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++]));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue