summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DataRecursiveASTVisitor.h7
-rw-r--r--clang/include/clang/AST/OpenMPClause.h54
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h7
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td14
-rw-r--r--clang/include/clang/Basic/OpenMPKinds.def2
-rw-r--r--clang/include/clang/Sema/Sema.h6
-rw-r--r--clang/lib/AST/StmtPrinter.cpp6
-rw-r--r--clang/lib/AST/StmtProfile.cpp5
-rw-r--r--clang/lib/Basic/OpenMPKinds.cpp2
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp2
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp80
-rw-r--r--clang/lib/Sema/TreeTransform.h24
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp8
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp5
-rw-r--r--clang/test/OpenMP/parallel_ast_print.cpp45
-rw-r--r--clang/test/OpenMP/parallel_num_threads_messages.cpp44
-rw-r--r--clang/tools/libclang/CIndex.cpp4
17 files changed, 298 insertions, 17 deletions
diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h
index cbefbdc287e..f3481c15bfe 100644
--- a/clang/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h
@@ -2371,6 +2371,13 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
}
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;
}
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 4a3c9e0a493..c710cddf5ac 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -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
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 8e3c9f724da..92c26c4235b 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2395,6 +2395,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
}
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;
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1e2a5aae803..36ebc82af46 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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 {
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index 41b77ef843c..da43a58d17f 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -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)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b56995ba82f..ffbaa48cc9c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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,
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index eb983b2db01..748a40160d1 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -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())
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index e9b1da49dd4..b871ffb73b4 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -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>
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 99c2fd2ebdd..0a25b240cb7 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -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:
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index df8f17bd13d..037dd36fc77 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 9ee89a3169a..a377815ffaf 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -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:
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index d164bdd650d..ac5a678eeb1 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -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.
@@ -6318,6 +6330,18 @@ TreeTransform<Derived>::TransformOMPIfClause(OMPIfClause *C) {
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) {
return getDerived().RebuildOMPDefaultClause(C->getDefaultKind(),
C->getDefaultKindKwLoc(),
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 3f83beb0a03..b83e8fa5ca0 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -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++]));
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 08228d07544..eb25d060e4e 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -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);
diff --git a/clang/test/OpenMP/parallel_ast_print.cpp b/clang/test/OpenMP/parallel_ast_print.cpp
index bd5171435e5..beb29ec15a2 100644
--- a/clang/test/OpenMP/parallel_ast_print.cpp
+++ b/clang/test/OpenMP/parallel_ast_print.cpp
@@ -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
diff --git a/clang/test/OpenMP/parallel_num_threads_messages.cpp b/clang/test/OpenMP/parallel_num_threads_messages.cpp
new file mode 100644
index 00000000000..facca5e3587
--- /dev/null
+++ b/clang/test/OpenMP/parallel_num_threads_messages.cpp
@@ -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}}
+}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index b5507a63495..1c24e6b7b27 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -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>
OpenPOWER on IntegriCloud