From: Alexey Bataev Date: Thu, 26 Sep 2013 03:24:06 +0000 (+0000) Subject: [OPENMP] Improved variable lookup procedure for threadprivate variables. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d0dbb7e6d4f05f5d0a5978822476897fe3427787;p=clang [OPENMP] Improved variable lookup procedure for threadprivate variables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191416 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 1e2d9d6e08..767f6620a2 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/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(cast(*I)->getDecl()); + Out << (I == D->varlist_begin() ? '(' : ','); + NamedDecl *ND = cast(cast(*I)->getDecl()); + ND->printQualifiedName(Out); } Out << ")"; } diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index a0e6780793..dadfa4129e 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -413,22 +413,55 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope, return ExprError(); } + VarDecl *CanonicalVD = VD->getCanonicalDecl(); + NamedDecl *ND = cast(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(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/test/OpenMP/threadprivate_ast_print.cpp b/test/OpenMP/threadprivate_ast_print.cpp index ddf488250a..823a4d6d8d 100644 --- a/test/OpenMP/threadprivate_ast_print.cpp +++ b/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 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/test/OpenMP/threadprivate_messages.cpp b/test/OpenMP/threadprivate_messages.cpp index a188a0b05d..4858549a70 100644 --- a/test/OpenMP/threadprivate_messages.cpp +++ b/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;