зеркало из https://github.com/microsoft/clang-1.git
[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:
Родитель
01ee2dcc30
Коммит
ff45f6913b
|
@ -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());
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче