]> granicus.if.org Git - clang/commitdiff
[OPENMP] Improved variable lookup procedure for threadprivate variables.
authorAlexey Bataev <a.bataev@hotmail.com>
Thu, 26 Sep 2013 03:24:06 +0000 (03:24 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Thu, 26 Sep 2013 03:24:06 +0000 (03:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191416 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/DeclPrinter.cpp
lib/Sema/SemaOpenMP.cpp
test/OpenMP/threadprivate_ast_print.cpp
test/OpenMP/threadprivate_messages.cpp

index 1e2d9d6e0846bd885a2eb3d82b6e27a387590983..767f6620a29524aeebcce3d27cbae9118287f9bb 100644 (file)
@@ -1189,8 +1189,9 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
     for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
                                                 E = D->varlist_end();
                                                 I != E; ++I) {
-      Out << (I == D->varlist_begin() ? '(' : ',')
-          << *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
+      Out << (I == D->varlist_begin() ? '(' : ',');
+      NamedDecl *ND = cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
+      ND->printQualifiedName(Out);
     }
     Out << ")";
   }
index a0e6780793596373b3a65b898f80c768e57b61be..dadfa4129ea4653be48387bc195a2d3b692ff7a2 100644 (file)
@@ -413,22 +413,55 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
     return ExprError();
   }
 
+  VarDecl *CanonicalVD = VD->getCanonicalDecl();
+  NamedDecl *ND = cast<NamedDecl>(CanonicalVD);
   // OpenMP [2.9.2, Restrictions, C/C++, p.2]
   //   A threadprivate directive for file-scope variables must appear outside
   //   any definition or declaration.
+  if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
+      !getCurLexicalContext()->isTranslationUnit()) {
+    Diag(Id.getLoc(), diag::err_omp_var_scope)
+      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                  VarDecl::DeclarationOnly;
+    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+                                     diag::note_defined_here) << VD;
+    return ExprError();
+  }
   // OpenMP [2.9.2, Restrictions, C/C++, p.3]
   //   A threadprivate directive for static class member variables must appear
   //   in the class definition, in the same scope in which the member
   //   variables are declared.
+  if (CanonicalVD->isStaticDataMember() &&
+      !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
+    Diag(Id.getLoc(), diag::err_omp_var_scope)
+      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                  VarDecl::DeclarationOnly;
+    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+                                     diag::note_defined_here) << VD;
+    return ExprError();
+  }
   // OpenMP [2.9.2, Restrictions, C/C++, p.4]
   //   A threadprivate directive for namespace-scope variables must appear
   //   outside any definition or declaration other than the namespace
   //   definition itself.
+  if (CanonicalVD->getDeclContext()->isNamespace() &&
+      (!getCurLexicalContext()->isFileContext() ||
+       !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
+    Diag(Id.getLoc(), diag::err_omp_var_scope)
+      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
+    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+                  VarDecl::DeclarationOnly;
+    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
+                                     diag::note_defined_here) << VD;
+    return ExprError();
+  }
   // OpenMP [2.9.2, Restrictions, C/C++, p.6]
   //   A threadprivate directive for static block-scope variables must appear
   //   in the scope of the variable and not in a nested scope.
-  NamedDecl *ND = cast<NamedDecl>(VD);
-  if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
+  if (CanonicalVD->isStaticLocal() && CurScope &&
+      !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
     Diag(Id.getLoc(), diag::err_omp_var_scope)
       << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
     bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
index ddf488250aadbe095926b3b3bbeb4c43f5b11f08..823a4d6d8dd88305720fefabde9f0159f2ac2456 100644 (file)
@@ -15,7 +15,7 @@ struct St1{
  static int b;
 // CHECK: static int b;
 #pragma omp threadprivate(b)
-// CHECK-NEXT: #pragma omp threadprivate(b)
+// CHECK-NEXT: #pragma omp threadprivate(St1::b)
 } d;
 
 int a, b;
@@ -38,6 +38,15 @@ template <class T> T foo() {
 //CHECK-NEXT: static T v;
 //CHECK-NEXT: #pragma omp threadprivate(v)
 
+namespace ns{
+  int a;
+}
+// CHECK: namespace ns {
+// CHECK-NEXT: int a;
+// CHECK-NEXT: }
+#pragma omp threadprivate(ns::a)
+// CHECK-NEXT: #pragma omp threadprivate(ns::a)
+
 int main () {
   static int a;
 // CHECK: static int a;
index a188a0b05d6c899a0e6c82f3fd4bebacc608cefd..4858549a7038677a22b856de4e8cbec27b80e46a 100644 (file)
@@ -60,12 +60,12 @@ class Class {
 #pragma omp threadprivate (g)
 
 namespace ns {
-  int m; // expected-note 2 {{'m' defined here}}
+  int m;
 #pragma omp threadprivate (m)
 }
 #pragma omp threadprivate (m) // expected-error {{use of undeclared identifier 'm'}}
-#pragma omp threadprivate (ns::m) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'ns::m' variable declaration}}
-#pragma omp threadprivate (ns:m) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'ns::m' variable declaration}}
+#pragma omp threadprivate (ns::m) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'ns::m'}}
+#pragma omp threadprivate (ns:m) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'ns::m'}}
 
 const int h = 12;
 const volatile int i = 10;