diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 021548617503..065e0be1d026 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6956,6 +6956,8 @@ def err_omp_linear_expected_int_or_ptr : Error< def warn_omp_linear_step_zero : Warning< "zero linear step (%0 %select{|and other variables in clause }1should probably be const)">, InGroup; +def err_omp_local_var_in_threadprivate_init : Error< + "variable with local storage in initial value of threadprivate variable">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 603dd56c4fe8..e616232540bc 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -553,6 +553,35 @@ Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc, return DeclGroupPtrTy(); } +namespace { +class LocalVarRefChecker : public ConstStmtVisitor { + Sema &SemaRef; + +public: + bool VisitDeclRefExpr(const DeclRefExpr *E) { + if (auto VD = dyn_cast(E->getDecl())) { + if (VD->hasLocalStorage()) { + SemaRef.Diag(E->getLocStart(), + diag::err_omp_local_var_in_threadprivate_init) + << E->getSourceRange(); + SemaRef.Diag(VD->getLocation(), diag::note_defined_here) + << VD << VD->getSourceRange(); + return true; + } + } + return false; + } + bool VisitStmt(const Stmt *S) { + for (auto Child : S->children()) { + if (Child && Visit(Child)) + return true; + } + return false; + } + LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {} +}; +} // namespace + OMPThreadPrivateDecl * Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef VarList) { SmallVector Vars; @@ -592,6 +621,13 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef VarList) { continue; } + // Check if initial value of threadprivate variable reference variable with + // local storage (it is not supported by runtime). + if (auto Init = VD->getAnyInitializer()) { + LocalVarRefChecker Checker(*this); + if (Checker.Visit(Init)) continue; + } + Vars.push_back(RefExpr); DSAStack->addDSA(VD, DE, OMPC_threadprivate); } diff --git a/clang/test/OpenMP/threadprivate_messages.cpp b/clang/test/OpenMP/threadprivate_messages.cpp index 4b4f9e014632..c922f190ad04 100644 --- a/clang/test/OpenMP/threadprivate_messages.cpp +++ b/clang/test/OpenMP/threadprivate_messages.cpp @@ -108,10 +108,12 @@ int o; // expected-note {{candidate found by name lookup is '(anonymous namespac int main(int argc, char **argv) { // expected-note {{'argc' defined here}} - int x, y = argc; // expected-note {{'y' defined here}} + int x, y = argc; // expected-note 2 {{'y' defined here}} static double d1; static double d2; static double d3; // expected-note {{'d3' defined here}} + static Class LocalClass(y); // expected-error {{variable with local storage in initial value of threadprivate variable}} +#pragma omp threadprivate(LocalClass) d.a = a; d2++;