Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -11314,6 +11314,11 @@ class Sema final {
void
checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
SourceLocation IdLoc = SourceLocation());

/// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of explaining what the function does literally, a comment describing the goal of the function would be easier to understand.

/// directive.
void ActOnOpenMPImplicitDeclareTarget(Decl *D);

/// Finishes analysis of the deferred functions calls that may be declared as
/// host/nohost during device/host compilation.
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14473,6 +14473,13 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,

for (unsigned i = 0, e = Group.size(); i != e; ++i) {
if (Decl *D = Group[i]) {
// Check if the Decl has been declared in '#pragma omp declare target'
// directive and has static storage duration.
if (auto *VD = dyn_cast_or_null<VarDecl>(D);
LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
VD->hasGlobalStorage()) {
ActOnOpenMPImplicitDeclareTarget(D);
}
Comment on lines +14478 to +14482
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you run git-clang-format on all your changes ?

// For declarators, there are some additional syntactic-ish checks we need
// to perform.
if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {
Expand Down
53 changes: 53 additions & 0 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23094,6 +23094,59 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
}

class MyStmtVisitor final : public ConstStmtVisitor<MyStmtVisitor> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggesting not to use My in the class and method names

public:
SmallVector<Decl *> DeclVector;
Decl *TargetDecl;
void VisitDeclRefExpr(const DeclRefExpr *Node) {
Decl *DeclVar = nullptr;
if (const VarDecl *VD = dyn_cast<VarDecl>(Node->getDecl())) {
DeclVar = (Decl *)Node->getDecl();
DeclVar->addAttr((this->TargetDecl)->getAttr<OMPDeclareTargetDeclAttr>());
(this->DeclVector).push_back(DeclVar);
}
}
void VisitMyExpr(const Expr *Ex) {
for (Expr::const_child_iterator it = Ex->child_begin();
it != Ex->child_end(); ++it) {
if (isa<Expr>(*it))
VisitMyExpr(dyn_cast<Expr>(*it));
if (isa<DeclRefExpr>(*it))
Visit(*it);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am assuming this Visit() calls the MyStmtVisitor::VisitDeclRefExpr() indirectly via overriding, as *it is a DeclRefExpr. Why not call MyStmtVisitor::VisitDeclRefExpr() yourself, if you know that *it is a DeclRefExpr ?

}
}
};

/// Adding OMPDeclareTargetDeclAttr to variables with static storage
/// duration that are referenced in the initializer expression list of
/// variables with static storage duration in declare target directive.
void Sema::ActOnOpenMPImplicitDeclareTarget(Decl *TargetDecl) {
MyStmtVisitor visitor;
visitor.TargetDecl = TargetDecl;
VarDecl *TargetVarDecl = nullptr;
if (TargetVarDecl = dyn_cast_or_null<VarDecl>(TargetDecl))
visitor.DeclVector.push_back(TargetDecl);
while (!visitor.DeclVector.empty()) {
Decl *D = visitor.DeclVector.pop_back_val();
TargetVarDecl = dyn_cast_or_null<VarDecl>(D);
if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>()) {
if (TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
Expr *Ex = TargetVarDecl->getInit();
const DeclRefExpr *DeclRef = nullptr;
if (Ex) {
if (isa<DeclRefExpr>(Ex)) {
DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(Ex);
visitor.VisitDeclRefExpr(DeclRef);
continue;
}
visitor.VisitMyExpr(Ex);
}
}
}
}
return;
}

OMPClause *Sema::ActOnOpenMPToClause(
ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
ArrayRef<SourceLocation> MotionModifiersLoc,
Expand Down
36 changes: 36 additions & 0 deletions clang/test/OpenMP/declare_target_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,42 @@ int MultiDevTy;
#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 variable = 100; //expected-warning {{declaration is not declared in any declare target region}}
static float variable1 = 200;
static float variable2 = variable1; //expected-warning {{declaration is not declared in any declare target region}}

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 target_var = variable; //expected-note {{used here}}
float target_var1 = variable2; //expected-note {{used here}}
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
Expand Down
112 changes: 112 additions & 0 deletions clang/test/OpenMP/declare_target_variables_ast_print.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// RUN: %clang_cc1 -w -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK
// expected-no-diagnostics

static int variable = 100;
static float variable1 = 200;
static float variable2 = variable1;

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 target_var = variable;
float target_var1 = variable2;
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 variable = 100;
// CHECK-NEXT: #pragma omp end declare target

// CHECK-NEXT: #pragma omp declare target
// CHECK-NEXT: static float variable1 = 200;
// CHECK-NEXT: #pragma omp end declare target
// CHECK-NEXT: #pragma omp declare target
// CHECK-NEXT: static float variable2 = variable1;
// CHECK-NEXT: #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 target_var = variable;
// CHECK-NEXT: #pragma omp end declare target
// CHECK-NEXT: #pragma omp declare target
// CHECK-NEXT: float target_var1 = variable2;
// 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

2 changes: 1 addition & 1 deletion clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ int (*C)() = &foobar3; // expected-warning {{declaration is not declared in any
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;
Expand Down