]> granicus.if.org Git - clang/commitdiff
[OPENMP] Additional checking for local vars in initial values for threadprivate vars
authorAlexey Bataev <a.bataev@hotmail.com>
Wed, 28 May 2014 07:40:25 +0000 (07:40 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Wed, 28 May 2014 07:40:25 +0000 (07:40 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209716 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOpenMP.cpp
test/OpenMP/threadprivate_messages.cpp

index 021548617503b1f4be8de1907c11e6c14929f2dc..065e0be1d026007106028e89a63005b717d293d8 100644 (file)
@@ -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<OpenMPClauses>;
+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 {
index 603dd56c4fe88b544cedf41bb57cabbf198a3848..e616232540bcd40b83f1e53dcc8d14385a1690c3 100644 (file)
@@ -553,6 +553,35 @@ Sema::ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
   return DeclGroupPtrTy();
 }
 
+namespace {
+class LocalVarRefChecker : public ConstStmtVisitor<LocalVarRefChecker, bool> {
+  Sema &SemaRef;
+
+public:
+  bool VisitDeclRefExpr(const DeclRefExpr *E) {
+    if (auto VD = dyn_cast<VarDecl>(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<Expr *> VarList) {
   SmallVector<Expr *, 8> Vars;
@@ -592,6 +621,13 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> 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);
   }
index 4b4f9e0146322a55260c34e19acfc105b5fd9026..c922f190ad04d37008b914c2858f3794475db93d 100644 (file)
@@ -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 {{'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++;