forked from OSchip/llvm-project
parent
f6863f1aab
commit
568a833f68
clang
include/clang
AST
Basic
Sema
lib
AST
Basic
Parse
Sema
Serialization
test/OpenMP
tools/libclang
|
@ -2370,6 +2370,13 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool DataRecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(
|
||||
OMPNumThreadsClause *C) {
|
||||
TraverseStmt(C->getNumThreads());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool DataRecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||
return true;
|
||||
|
|
|
@ -186,6 +186,60 @@ public:
|
|||
StmtRange children() { return StmtRange(&Condition, &Condition + 1); }
|
||||
};
|
||||
|
||||
/// \brief This represents 'num_threads' clause in the '#pragma omp ...'
|
||||
/// directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp parallel num_threads(6)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp parallel' has simple 'num_threads'
|
||||
/// clause with number of threads '6'.
|
||||
///
|
||||
class OMPNumThreadsClause : public OMPClause {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
/// \brief Condition of the 'num_threads' clause.
|
||||
Stmt *NumThreads;
|
||||
|
||||
/// \brief Set condition.
|
||||
///
|
||||
void setNumThreads(Expr *NThreads) { NumThreads = NThreads; }
|
||||
|
||||
public:
|
||||
/// \brief Build 'num_threads' clause with condition \a NumThreads.
|
||||
///
|
||||
/// \param NumThreads Number of threads for the construct.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
///
|
||||
OMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_num_threads, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
NumThreads(NumThreads) {}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
OMPNumThreadsClause()
|
||||
: OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()),
|
||||
LParenLoc(SourceLocation()), NumThreads(0) {}
|
||||
|
||||
/// \brief Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
/// \brief Returns the location of '('.
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
/// \brief Returns number of threads.
|
||||
Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); }
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_num_threads;
|
||||
}
|
||||
|
||||
StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); }
|
||||
};
|
||||
|
||||
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
|
||||
///
|
||||
/// \code
|
||||
|
|
|
@ -2394,6 +2394,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(
|
||||
OMPNumThreadsClause *C) {
|
||||
TraverseStmt(C->getNumThreads());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||
return true;
|
||||
|
|
|
@ -6866,6 +6866,20 @@ def note_omp_predetermined_dsa : Note<
|
|||
"predetermined as %0">;
|
||||
def err_omp_not_for : Error<
|
||||
"statement after '#pragma omp %0' must be a for loop">;
|
||||
def err_omp_negative_expression_in_clause : Error<
|
||||
"argument to '%0' clause must be a positive integer value">;
|
||||
def err_omp_not_integral : Error<
|
||||
"expression must have integral or unscoped enumeration "
|
||||
"type, not %0">;
|
||||
def err_omp_incomplete_type : Error<
|
||||
"expression has incomplete class type %0">;
|
||||
def err_omp_explicit_conversion : Error<
|
||||
"expression requires explicit conversion from %0 to %1">;
|
||||
def note_omp_conversion_here : Note<
|
||||
"conversion to %select{integral|enumeration}0 type %1 declared here">;
|
||||
def err_omp_ambiguous_conversion : Error<
|
||||
"ambiguous conversion from type %0 to an integral or unscoped "
|
||||
"enumeration type">;
|
||||
} // end of OpenMP category
|
||||
|
||||
let CategoryName = "Related Result Type Issue" in {
|
||||
|
|
|
@ -36,6 +36,7 @@ OPENMP_DIRECTIVE(simd)
|
|||
|
||||
// OpenMP clauses.
|
||||
OPENMP_CLAUSE(if, OMPIfClause)
|
||||
OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
|
||||
OPENMP_CLAUSE(default, OMPDefaultClause)
|
||||
OPENMP_CLAUSE(private, OMPPrivateClause)
|
||||
OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
|
||||
|
@ -43,6 +44,7 @@ OPENMP_CLAUSE(shared, OMPSharedClause)
|
|||
|
||||
// Clauses allowed for OpenMP directives.
|
||||
OPENMP_PARALLEL_CLAUSE(if)
|
||||
OPENMP_PARALLEL_CLAUSE(num_threads)
|
||||
OPENMP_PARALLEL_CLAUSE(default)
|
||||
OPENMP_PARALLEL_CLAUSE(private)
|
||||
OPENMP_PARALLEL_CLAUSE(firstprivate)
|
||||
|
|
|
@ -7078,6 +7078,7 @@ private:
|
|||
/// \brief Initialization of data-sharing attributes stack.
|
||||
void InitDataSharingAttributesStack();
|
||||
void DestroyDataSharingAttributesStack();
|
||||
ExprResult PerformImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op);
|
||||
public:
|
||||
/// \brief Called on start of new data sharing attribute block.
|
||||
void StartOpenMPDSABlock(OpenMPDirectiveKind K,
|
||||
|
@ -7128,6 +7129,11 @@ public:
|
|||
OMPClause *ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'num_threads' clause.
|
||||
OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
||||
unsigned Argument,
|
||||
|
|
|
@ -612,6 +612,12 @@ void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
|
|||
OS << ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
|
||||
OS << "num_threads(";
|
||||
Node->getNumThreads()->printPretty(OS, 0, Policy, 0);
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
|
||||
OS << "default("
|
||||
<< getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
|
||||
|
|
|
@ -270,6 +270,11 @@ void OMPClauseProfiler::VisitOMPIfClause(const OMPIfClause *C) {
|
|||
Profiler->VisitStmt(C->getCondition());
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
|
||||
if (C->getNumThreads())
|
||||
Profiler->VisitStmt(C->getNumThreads());
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -78,6 +78,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
|||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
|
@ -102,6 +103,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
|||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
|
|
|
@ -272,8 +272,10 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|||
|
||||
switch (CKind) {
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
// 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.
|
||||
if (!FirstClause) {
|
||||
Diag(Tok, diag::err_omp_more_one_clause)
|
||||
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
|
||||
|
|
|
@ -758,6 +758,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
|||
case OMPC_if:
|
||||
Res = ActOnOpenMPIfClause(Expr, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_num_threads:
|
||||
Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_default:
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
|
@ -790,6 +793,81 @@ OMPClause *Sema::ActOnOpenMPIfClause(Expr *Condition,
|
|||
return new (Context) OMPIfClause(ValExpr, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
ExprResult Sema::PerformImplicitIntegerConversion(SourceLocation Loc,
|
||||
Expr *Op) {
|
||||
if (!Op)
|
||||
return ExprError();
|
||||
|
||||
class IntConvertDiagnoser : public ICEConvertDiagnoser {
|
||||
public:
|
||||
IntConvertDiagnoser()
|
||||
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
|
||||
false, true) {}
|
||||
virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
|
||||
QualType T) {
|
||||
return S.Diag(Loc, diag::err_omp_not_integral) << T;
|
||||
}
|
||||
virtual SemaDiagnosticBuilder diagnoseIncomplete(
|
||||
Sema &S, SourceLocation Loc, QualType T) {
|
||||
return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
|
||||
}
|
||||
virtual SemaDiagnosticBuilder diagnoseExplicitConv(
|
||||
Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
|
||||
return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
|
||||
}
|
||||
virtual SemaDiagnosticBuilder noteExplicitConv(
|
||||
Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
|
||||
return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
|
||||
<< ConvTy->isEnumeralType() << ConvTy;
|
||||
}
|
||||
virtual SemaDiagnosticBuilder diagnoseAmbiguous(
|
||||
Sema &S, SourceLocation Loc, QualType T) {
|
||||
return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
|
||||
}
|
||||
virtual SemaDiagnosticBuilder noteAmbiguous(
|
||||
Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {
|
||||
return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
|
||||
<< ConvTy->isEnumeralType() << ConvTy;
|
||||
}
|
||||
virtual SemaDiagnosticBuilder diagnoseConversion(
|
||||
Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {
|
||||
llvm_unreachable("conversion functions are permitted");
|
||||
}
|
||||
} ConvertDiagnoser;
|
||||
return PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
Expr *ValExpr = NumThreads;
|
||||
if (!NumThreads->isValueDependent() && !NumThreads->isTypeDependent() &&
|
||||
!NumThreads->isInstantiationDependent() &&
|
||||
!NumThreads->containsUnexpandedParameterPack()) {
|
||||
SourceLocation NumThreadsLoc = NumThreads->getLocStart();
|
||||
ExprResult Val =
|
||||
PerformImplicitIntegerConversion(NumThreadsLoc, NumThreads);
|
||||
if (Val.isInvalid())
|
||||
return 0;
|
||||
|
||||
ValExpr = Val.take();
|
||||
|
||||
// OpenMP [2.5, Restrictions]
|
||||
// The num_threads expression must evaluate to a positive integer value.
|
||||
llvm::APSInt Result;
|
||||
if (ValExpr->isIntegerConstantExpr(Result, Context) &&
|
||||
Result.isSigned() && !Result.isStrictlyPositive()) {
|
||||
Diag(NumThreadsLoc, diag::err_omp_negative_expression_in_clause)
|
||||
<< "num_threads" << NumThreads->getSourceRange();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return new (Context) OMPNumThreadsClause(ValExpr, StartLoc, LParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
||||
unsigned Argument,
|
||||
SourceLocation ArgumentLoc,
|
||||
|
@ -804,6 +882,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
|||
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
|
@ -876,6 +955,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
|||
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_default:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
|
|
|
@ -1312,6 +1312,18 @@ public:
|
|||
LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'num_threads' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPNumThreadsClause(Expr *NumThreads,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPNumThreadsClause(NumThreads, StartLoc,
|
||||
LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'default' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
|
@ -6316,6 +6328,18 @@ TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
|
|||
C->getLParenLoc(), C->getLocEnd());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
||||
ExprResult NumThreads = getDerived().TransformExpr(C->getNumThreads());
|
||||
if (NumThreads.isInvalid())
|
||||
return 0;
|
||||
return getDerived().RebuildOMPNumThreadsClause(NumThreads.take(),
|
||||
C->getLocStart(),
|
||||
C->getLParenLoc(),
|
||||
C->getLocEnd());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
|
||||
|
|
|
@ -1676,6 +1676,9 @@ OMPClause *OMPClauseReader::readClause() {
|
|||
case OMPC_if:
|
||||
C = new (Context) OMPIfClause();
|
||||
break;
|
||||
case OMPC_num_threads:
|
||||
C = new (Context) OMPNumThreadsClause();
|
||||
break;
|
||||
case OMPC_default:
|
||||
C = new (Context) OMPDefaultClause();
|
||||
break;
|
||||
|
@ -1701,6 +1704,11 @@ void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
|
|||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
||||
C->setNumThreads(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::VisitOMPIfClause(OMPIfClause *C) {
|
|||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
||||
Writer->Writer.AddStmt(C->getNumThreads());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||
Record.push_back(C->getDefaultKind());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
|
|
|
@ -8,61 +8,72 @@
|
|||
|
||||
void foo() {}
|
||||
|
||||
template <class T>
|
||||
struct S {
|
||||
operator T() {return T();}
|
||||
};
|
||||
|
||||
template <typename T, int C>
|
||||
T tmain(T argc, T *argv) {
|
||||
T b = argc, c, d, e, f, g;
|
||||
static T a;
|
||||
S<T> s;
|
||||
#pragma omp parallel
|
||||
a=2;
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0)
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C)
|
||||
foo();
|
||||
#pragma omp parallel if (C)
|
||||
#pragma omp parallel if (C) num_threads(s)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
// CHECK: template <typename T = int, int C = 2> int tmain(int argc, int *argv) {
|
||||
// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
|
||||
// CHECK-NEXT: int b = argc, c, d, e, f, g;
|
||||
// CHECK-NEXT: static int a;
|
||||
// CHECK-NEXT: S<int> s;
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: a = 2;
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp parallel if(2)
|
||||
// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK: template <typename T = float, int C = 0> float tmain(float argc, float *argv) {
|
||||
// CHECK-NEXT: float b = argc, c, d, e, f, g;
|
||||
// CHECK-NEXT: static float a;
|
||||
// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
|
||||
// CHECK-NEXT: long b = argc, c, d, e, f, g;
|
||||
// CHECK-NEXT: static long a;
|
||||
// CHECK-NEXT: S<long> s;
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: a = 2;
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp parallel if(0)
|
||||
// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
|
||||
// CHECK-NEXT: T b = argc, c, d, e, f, g;
|
||||
// CHECK-NEXT: static T a;
|
||||
// CHECK-NEXT: S<T> s;
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: a = 2;
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp parallel if(C)
|
||||
// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s)
|
||||
// CHECK-NEXT: foo()
|
||||
|
||||
enum Enum { };
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
float x;
|
||||
long x;
|
||||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
// CHECK: static int a;
|
||||
Enum ee;
|
||||
// CHECK: Enum ee;
|
||||
#pragma omp parallel
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
a=2;
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0)
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee)
|
||||
foo();
|
||||
// CHECK-NEXT: foo();
|
||||
return tmain<int, 2>(b, &b) + tmain<float, 0>(x, &x);
|
||||
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// 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, typename S, int N> // expected-note {{declared here}}
|
||||
T tmain(T argc, S **argv) {
|
||||
#pragma omp parallel num_threads // expected-error {{expected '(' after 'num_threads'}}
|
||||
#pragma omp parallel num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel num_threads () // expected-error {{expected expression}}
|
||||
#pragma omp parallel num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel num_threads (argc)) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}}
|
||||
#pragma omp parallel num_threads ((argc > 0) ? argv[1] : argv[2]) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
#pragma omp parallel num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a positive integer value}}
|
||||
#pragma omp parallel num_threads (S) // expected-error {{'S' does not refer to a value}}
|
||||
#pragma omp parallel num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
#pragma omp parallel num_threads (argc)
|
||||
#pragma omp parallel num_threads (N) // expected-error {{argument to 'num_threads' clause must be a positive integer value}}
|
||||
foo();
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#pragma omp parallel num_threads // expected-error {{expected '(' after 'num_threads'}}
|
||||
#pragma omp parallel num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel num_threads () // expected-error {{expected expression}}
|
||||
#pragma omp parallel num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel num_threads (argc)) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}}
|
||||
#pragma omp parallel num_threads (argc > 0 ? argv[1] : argv[2]) // expected-error {{integral }}
|
||||
#pragma omp parallel num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp parallel' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a positive integer value}}
|
||||
#pragma omp parallel num_threads (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
#pragma omp parallel num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
#pragma omp parallel num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}}
|
||||
foo();
|
||||
|
||||
return tmain<int, char, 3>(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<int, char, 3>' requested here}}
|
||||
}
|
|
@ -1936,6 +1936,10 @@ void OMPClauseEnqueue::VisitOMPIfClause(const OMPIfClause *C) {
|
|||
Visitor->AddStmt(C->getCondition());
|
||||
}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
|
||||
Visitor->AddStmt(C->getNumThreads());
|
||||
}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||
|
||||
template<typename T>
|
||||
|
|
Loading…
Reference in New Issue