[OPENMP] Initial parsing and sema analysis for 'final' clause.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213232 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alexey Bataev 2014-07-17 07:32:53 +00:00
Родитель 01ee2dcc30
Коммит ff45f6913b
16 изменённых файлов: 212 добавлений и 12 удалений

Просмотреть файл

@ -2330,6 +2330,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
TRY_TO(TraverseStmt(C->getCondition()));
return true;
}
template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {

Просмотреть файл

@ -196,6 +196,59 @@ public:
StmtRange children() { return StmtRange(&Condition, &Condition + 1); }
};
/// \brief This represents 'final' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp task final(a > 5)
/// \endcode
/// In this example directive '#pragma omp task' has simple 'final'
/// clause with condition 'a > 5'.
///
class OMPFinalClause : public OMPClause {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
/// \brief Condition of the 'if' clause.
Stmt *Condition;
/// \brief Set condition.
///
void setCondition(Expr *Cond) { Condition = Cond; }
public:
/// \brief Build 'final' clause with condition \a Cond.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param Cond Condition of the clause.
/// \param EndLoc Ending location of the clause.
///
OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc),
Condition(Cond) {}
/// \brief Build an empty clause.
///
OMPFinalClause()
: OMPClause(OMPC_final, SourceLocation(), SourceLocation()),
LParenLoc(SourceLocation()), Condition(nullptr) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_final;
}
StmtRange children() { return StmtRange(&Condition, &Condition + 1); }
};
/// \brief This represents 'num_threads' clause in the '#pragma omp ...'
/// directive.
///

Просмотреть файл

@ -2352,6 +2352,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
TRY_TO(TraverseStmt(C->getCondition()));
return true;
}
template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {

Просмотреть файл

@ -69,6 +69,7 @@ OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
// OpenMP clauses.
OPENMP_CLAUSE(if, OMPIfClause)
OPENMP_CLAUSE(final, OMPFinalClause)
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
OPENMP_CLAUSE(safelen, OMPSafelenClause)
OPENMP_CLAUSE(collapse, OMPCollapseClause)
@ -175,6 +176,7 @@ OPENMP_PARALLEL_SECTIONS_CLAUSE(lastprivate)
// TODO more clauses allowed for OpenMP directive 'task'.
OPENMP_TASK_CLAUSE(if)
OPENMP_TASK_CLAUSE(final)
OPENMP_TASK_CLAUSE(default)
OPENMP_TASK_CLAUSE(private)
OPENMP_TASK_CLAUSE(firstprivate)

Просмотреть файл

@ -7374,6 +7374,10 @@ public:
OMPClause *ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'final' clause.
OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'num_threads' clause.
OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads,
SourceLocation StartLoc,

Просмотреть файл

@ -603,6 +603,12 @@ void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
OS << ")";
}
void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) {
OS << "final(";
Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
OS << "num_threads(";
Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0);

Просмотреть файл

@ -273,6 +273,11 @@ void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) {
Profiler->VisitStmt(C->getCondition());
}
void OMPClauseProfiler::VisitOMPFinalClause(const OMPFinalClause *C) {
if (C->getCondition())
Profiler->VisitStmt(C->getCondition());
}
void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
if (C->getNumThreads())
Profiler->VisitStmt(C->getNumThreads());

Просмотреть файл

@ -88,6 +88,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_collapse:
@ -143,6 +144,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_collapse:

Просмотреть файл

@ -286,11 +286,11 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// \brief Parsing of OpenMP clauses.
///
/// clause:
/// if-clause | num_threads-clause | safelen-clause | default-clause |
/// private-clause | firstprivate-clause | shared-clause | linear-clause |
/// aligned-clause | collapse-clause | lastprivate-clause |
/// reduction-clause | proc_bind-clause | schedule-clause |
/// copyin-clause | copyprivate-clause
/// if-clause | final-clause | num_threads-clause | safelen-clause |
/// default-clause | private-clause | firstprivate-clause | shared-clause
/// | linear-clause | aligned-clause | collapse-clause |
/// lastprivate-clause | reduction-clause | proc_bind-clause |
/// schedule-clause | copyin-clause | copyprivate-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@ -305,6 +305,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
switch (CKind) {
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_collapse:
@ -314,6 +315,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP [2.8.1, simd construct, Restrictions]
// Only one safelen clause can appear on a simd directive.
// Only one collapse clause can appear on a simd directive.
// OpenMP [2.11.1, task Construct, Restrictions]
// At most one if clause can appear on the directive.
// At most one final clause can appear on the directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
<< getOpenMPClauseName(CKind);
@ -384,12 +388,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
}
/// \brief Parsing of OpenMP clauses with single expressions like 'if',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
/// 'thread_limit'.
///
/// if-clause:
/// 'if' '(' expression ')'
///
/// final-clause:
/// 'final' '(' expression ')'
///
/// num_threads-clause:
/// 'num_threads' '(' expression ')'
///

Просмотреть файл

@ -1992,6 +1992,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_if:
Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_final:
Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_num_threads:
Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
@ -2040,6 +2043,25 @@ OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
Expr *ValExpr = Condition;
if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
!Condition->isInstantiationDependent() &&
!Condition->containsUnexpandedParameterPack()) {
ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(),
Condition->getExprLoc(), Condition);
if (Val.isInvalid())
return nullptr;
ValExpr = Val.get();
}
return new (Context) OMPFinalClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
ExprResult Sema::PerformOpenMPImplicitIntegerConversion(SourceLocation Loc,
Expr *Op) {
if (!Op)
@ -2180,6 +2202,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_collapse:
@ -2290,6 +2313,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
LParenLoc, ArgumentLoc, CommaLoc, EndLoc);
break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_collapse:
@ -2381,6 +2405,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_collapse:
@ -2451,6 +2476,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_collapse:

Просмотреть файл

@ -1318,6 +1318,17 @@ public:
LParenLoc, EndLoc);
}
/// \brief Build a new OpenMP 'final' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPFinalClause(Expr *Condition, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPFinalClause(Condition, StartLoc, LParenLoc,
EndLoc);
}
/// \brief Build a new OpenMP 'num_threads' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@ -6542,6 +6553,15 @@ OMPClause *TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
C->getLParenLoc(), C->getLocEnd());
}
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPFinalClause(OMPFinalClause *C) {
ExprResult Cond = getDerived().TransformExpr(C->getCondition());
if (Cond.isInvalid())
return nullptr;
return getDerived().RebuildOMPFinalClause(Cond.get(), C->getLocStart(),
C->getLParenLoc(), C->getLocEnd());
}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {

Просмотреть файл

@ -1682,6 +1682,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_if:
C = new (Context) OMPIfClause();
break;
case OMPC_final:
C = new (Context) OMPFinalClause();
break;
case OMPC_num_threads:
C = new (Context) OMPNumThreadsClause();
break;
@ -1746,6 +1749,11 @@ void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) {
C->setCondition(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
C->setNumThreads(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));

Просмотреть файл

@ -1687,6 +1687,11 @@ void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) {
Writer->Writer.AddStmt(C->getCondition());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
Writer->Writer.AddStmt(C->getNumThreads());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);

Просмотреть файл

@ -35,7 +35,7 @@ T tmain(T argc, T *argv) {
S<T> s;
#pragma omp task
a = 2;
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0)
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0) final(S<T>::TS > 0)
foo();
#pragma omp task if (C)
foo();
@ -48,7 +48,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<int> s;
// CHECK-NEXT: #pragma omp task
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<int>::TS > 0)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp task if(5)
// CHECK-NEXT: foo()
@ -58,7 +58,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<long> s;
// CHECK-NEXT: #pragma omp task
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<long>::TS > 0)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp task if(1)
// CHECK-NEXT: foo()
@ -68,7 +68,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: #pragma omp task
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<T>::TS > 0)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp task if(C)
// CHECK-NEXT: foo()
@ -86,8 +86,8 @@ int main(int argc, char **argv) {
// CHECK-NEXT: #pragma omp task
a = 2;
// CHECK-NEXT: a = 2;
#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0)
#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0) final(a > 0)
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0) final(a > 0)
foo();
// CHECK-NEXT: foo();
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);

Просмотреть файл

@ -0,0 +1,46 @@
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
void foo() {
}
bool foobool(int argc) {
return argc;
}
struct S1; // expected-note {{declared here}}
template <class T, class S> // expected-note {{declared here}}
int tmain(T argc, S **argv) {
#pragma omp task final // expected-error {{expected '(' after 'final'}}
#pragma omp task final ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final () // expected-error {{expected expression}}
#pragma omp task final (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final (argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
#pragma omp task final (argc > 0 ? argv[1] : argv[2])
#pragma omp task final (foobool(argc)), final (true) // expected-error {{directive '#pragma omp task' cannot contain more than one 'final' clause}}
#pragma omp task final (S) // expected-error {{'S' does not refer to a value}}
#pragma omp task final (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final(argc)
foo();
return 0;
}
int main(int argc, char **argv) {
#pragma omp task final // expected-error {{expected '(' after 'final'}}
#pragma omp task final ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final () // expected-error {{expected expression}}
#pragma omp task final (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final (argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
#pragma omp task final (argc > 0 ? argv[1] : argv[2])
#pragma omp task final (foobool(argc)), final (true) // expected-error {{directive '#pragma omp task' cannot contain more than one 'final' clause}}
#pragma omp task final (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp task final (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task final(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
foo();
return tmain(argc, argv);
}

Просмотреть файл

@ -1939,6 +1939,10 @@ void OMPClauseEnqueue::VisitOMPIfClause(const OMPIfClause *C) {
Visitor->AddStmt(C->getCondition());
}
void OMPClauseEnqueue::VisitOMPFinalClause(const OMPFinalClause *C) {
Visitor->AddStmt(C->getCondition());
}
void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
Visitor->AddStmt(C->getNumThreads());
}