diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2013-09-26 03:24:06 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2013-09-26 03:24:06 +0000 |
commit | 7d2960bd2a137cbb9ed416e6abcf5acd411562dc (patch) | |
tree | 895bf3feb39bb496cfb7129d88ac88d4be0c0539 | |
parent | 3eb663b03730e5571f8c75fbf20d6a6701114696 (diff) | |
download | bcm5719-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.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 37 | ||||
-rw-r--r-- | clang/test/OpenMP/threadprivate_ast_print.cpp | 11 | ||||
-rw-r--r-- | clang/test/OpenMP/threadprivate_messages.cpp | 6 |
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; |