mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-09 17:43:57 +00:00
[OPENMP] Improved variable lookup procedure for threadprivate variables.
llvm-svn: 191416
This commit is contained in:
parent
3eb663b037
commit
7d2960bd2a
@ -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 << ")";
|
||||
}
|
||||
|
@ -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) ==
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user