Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -2087,6 +2087,33 @@ } } +/// Adding OMPDeclareTargetDeclAttr to variables with static storage +/// duration that is referenced in the initializer expression list of +/// variables with static storage duration in declare target directive. +void ParseImplicitDeclareTargetAttr(Decl *TargetDecl) { + if (TargetDecl && TargetDecl->hasAttr() && + isa(TargetDecl)) { + VarDecl *TargetVarDecl = cast(TargetDecl); + Expr *Ex = TargetVarDecl->getInit()->IgnoreCasts(); + const DeclRefExpr *DeclRef = nullptr; + if (Ex && isa(Ex) && TargetVarDecl->hasGlobalStorage()) { + if (auto *unary = cast(Ex)) { + if (unary->getOpcode() == UnaryOperator::Opcode::UO_AddrOf) { + for (auto child : unary->children()) { + if (isa(child)) { + DeclRef = dyn_cast(child); + Decl *DeclVar = (Decl *)DeclRef->getDecl(); + DeclVar->addAttr(TargetDecl->getAttr()); + ParseImplicitDeclareTargetAttr(DeclVar); + } + } + } + } + } + } + return; +} + /// ParseDeclGroup - Having concluded that this is either a function /// definition or a group of object declarations, actually parse the /// result. @@ -2242,6 +2269,12 @@ SmallVector DeclsInGroup; Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes( D, ParsedTemplateInfo(), FRI); + if (FirstDecl && FirstDecl->hasAttr() && + isa(FirstDecl)) { + VarDecl *VarFirstDecl = cast(FirstDecl); + if (VarFirstDecl->hasGlobalStorage()) + ParseImplicitDeclareTargetAttr(FirstDecl); + } if (LateParsedAttrs.size() > 0) ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); D.complete(FirstDecl); Index: clang/test/OpenMP/declare_target_messages.cpp =================================================================== --- clang/test/OpenMP/declare_target_messages.cpp +++ clang/test/OpenMP/declare_target_messages.cpp @@ -233,6 +233,36 @@ #pragma omp declare target to(MultiDevTy) device_type(host) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(host)' does not match previously specified 'device_type(any)' for the same declaration}} omp51-error {{'device_type(host)' does not match previously specified 'device_type(any)' for the same declaration}} omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}} #pragma omp declare target to(MultiDevTy) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(nohost)' does not match previously specified 'device_type(any)' for the same declaration}} // omp51-error {{'device_type(nohost)' does not match previously specified 'device_type(any)' for the same declaration}} omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}} +static int var = 1; //expected-warning {{declaration is not declared in any declare target region}} + +static int var1 = 10; +static int *var2 = &var1; +static int **ptr1 = &var2; //expected-warning {{declaration is not declared in any declare target region}} + +int arr[2] = {1,2}; +int (*arrptr)[2] = &arr; //expected-warning {{declaration is not declared in any declare target region}} + +class declare{ + public: int x; + void print(); +}; +declare obj1; +declare *obj2 = &obj1; //expected-warning {{declaration is not declared in any declare target region}} + +struct target{ + int x; + void print(); +}; +static target S; //expected-warning {{declaration is not declared in any declare target region}} + +#pragma omp declare target +int *ptr = &var; //expected-note {{used here}} +int ***ptr2 = &ptr1; //expected-note {{used here}} +int (**ptr3)[2] = &arrptr; //expected-note {{used here}} +declare **obj3 = &obj2; //expected-note {{used here}} +target *S1 = &S; //expected-note {{used here}} +#pragma omp end declare target + #if TESTENDINC #include "unterminated_declare_target_include.h" #elif TESTEND Index: clang/test/OpenMP/declare_target_variables_ast_print.cpp =================================================================== --- /dev/null +++ clang/test/OpenMP/declare_target_variables_ast_print.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -w -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK +// expected-no-diagnostics + +static int var = 1; + +static int var1 = 10; +static int *var2 = &var1; +static int **ptr1 = &var2; + +int arr[2] = {1,2}; +int (*arrptr)[2] = &arr; + +class declare{ + public: int x; + void print(); +}; +declare obj1; +declare *obj2 = &obj1; + +struct target{ + int x; + void print(); +}; +static target S; + +#pragma omp declare target +int *ptr = &var; +int ***ptr2 = &ptr1; +int (**ptr3)[2] = &arrptr; +declare **obj3 = &obj2; +target *S1 = &S; +#pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK-NEXT: static int var = 1; +// CHECK-NEXT: #pragma omp end declare target + +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: static int var1 = 10; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: static int *var2 = &var1; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: static int **ptr1 = &var2; +// CHECK-NEXT: #pragma omp end declare target + +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: int arr[2] = {1, 2}; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: int (*arrptr)[2] = &arr; +// CHECK-NEXT: #pragma omp end declare target + +// CHECK-NEXT: class declare { +// CHECK-NEXT: public: +// CHECK-NEXT: int x; +// CHECK-NEXT: void print(); +// CHECK-NEXT: }; +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: declare obj1; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: declare *obj2 = &obj1; +// CHECK-NEXT: #pragma omp end declare target + +// CHECK-NEXT: struct target { +// CHECK-NEXT: int x; +// CHECK-NEXT: void print(); +// CHECK-NEXT: }; +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: static target S; +// CHECK-NEXT: #pragma omp end declare target + +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: int *ptr = &var; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: int ***ptr2 = &ptr1; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: int (**ptr3)[2] = &arrptr; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: declare **obj3 = &obj2; +// CHECK-NEXT: #pragma omp end declare target +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: target *S1 = &S; +// CHECK-NEXT: #pragma omp end declare target Index: clang/test/OpenMP/nvptx_target_exceptions_messages.cpp =================================================================== --- clang/test/OpenMP/nvptx_target_exceptions_messages.cpp +++ clang/test/OpenMP/nvptx_target_exceptions_messages.cpp @@ -95,7 +95,7 @@ int (*D)() = C; // expected-note {{used here}} // host-note@-1 {{used here}} #pragma omp end declare target -int foobar3() { throw 1; } +int foobar3() { throw 1; } // expected-error {{cannot use 'throw' with exceptions disabled}} // Check no infinite recursion in deferred diagnostic emitter. long E = (long)&E;