summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2013-09-26 03:24:06 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2013-09-26 03:24:06 +0000
commit7d2960bd2a137cbb9ed416e6abcf5acd411562dc (patch)
tree895bf3feb39bb496cfb7129d88ac88d4be0c0539
parent3eb663b03730e5571f8c75fbf20d6a6701114696 (diff)
downloadbcm5719-llvm-7d2960bd2a137cbb9ed416e6abcf5acd411562dc.tar.gz
bcm5719-llvm-7d2960bd2a137cbb9ed416e6abcf5acd411562dc.zip
[OPENMP] Improved variable lookup procedure for threadprivate variables.
llvm-svn: 191416
-rw-r--r--clang/lib/AST/DeclPrinter.cpp5
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp37
-rw-r--r--clang/test/OpenMP/threadprivate_ast_print.cpp11
-rw-r--r--clang/test/OpenMP/threadprivate_messages.cpp6
4 files changed, 51 insertions, 8 deletions
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 1e2d9d6e084..767f6620a29 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -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 << ")";
}
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index a0e67807935..dadfa4129ea 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -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) ==
diff --git a/clang/test/OpenMP/threadprivate_ast_print.cpp b/clang/test/OpenMP/threadprivate_ast_print.cpp
index ddf488250aa..823a4d6d8dd 100644
--- a/clang/test/OpenMP/threadprivate_ast_print.cpp
+++ b/clang/test/OpenMP/threadprivate_ast_print.cpp
@@ -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;
diff --git a/clang/test/OpenMP/threadprivate_messages.cpp b/clang/test/OpenMP/threadprivate_messages.cpp
index a188a0b05d6..4858549a703 100644
--- a/clang/test/OpenMP/threadprivate_messages.cpp
+++ b/clang/test/OpenMP/threadprivate_messages.cpp
@@ -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;
OpenPOWER on IntegriCloud