diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3330,13 +3330,15 @@ [ "MT_To", "MT_Link" ]>, EnumArgument<"DevType", "DevTypeTy", [ "host", "nohost", "any" ], - [ "DT_Host", "DT_NoHost", "DT_Any" ]> + [ "DT_Host", "DT_NoHost", "DT_Any" ]>, + UnsignedArgument<"Level"> ]; let AdditionalMembers = [{ void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const; static llvm::Optional isDeclareTargetDeclaration(const ValueDecl *VD); static llvm::Optional getDeviceType(const ValueDecl *VD); + static llvm::Optional getLocation(const ValueDecl *VD); }]; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9974,7 +9974,7 @@ private: void *VarDataSharingAttributesStack; /// Number of nested '#pragma omp declare target' directives. - unsigned DeclareTargetNestingLevel = 0; + SmallVector DeclareTargetNesting; /// Initialization of data-sharing attributes stack. void InitDataSharingAttributesStack(); void DestroyDataSharingAttributesStack(); @@ -10234,7 +10234,7 @@ SourceLocation Loc); /// Return true inside OpenMP declare target region. bool isInOpenMPDeclareTargetContext() const { - return DeclareTargetNestingLevel > 0; + return !DeclareTargetNesting.empty(); } /// Return true inside OpenMP target region. bool isInOpenMPTargetExecutionDirective() const; diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp --- a/clang/lib/AST/AttrImpl.cpp +++ b/clang/lib/AST/AttrImpl.cpp @@ -136,8 +136,16 @@ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) { if (!VD->hasAttrs()) return llvm::None; - if (const auto *Attr = VD->getAttr()) - return Attr->getMapType(); + unsigned Level = 0; + const OMPDeclareTargetDeclAttr *FoundAttr = nullptr; + for (const auto *Attr : VD->specific_attrs()) { + if (Level < Attr->getLevel()) { + Level = Attr->getLevel(); + FoundAttr = Attr; + } + } + if (FoundAttr) + return FoundAttr->getMapType(); return llvm::None; } @@ -146,8 +154,34 @@ OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) { if (!VD->hasAttrs()) return llvm::None; - if (const auto *Attr = VD->getAttr()) - return Attr->getDevType(); + unsigned Level = 0; + const OMPDeclareTargetDeclAttr *FoundAttr = nullptr; + for (const auto *Attr : VD->specific_attrs()) { + if (Level < Attr->getLevel()) { + Level = Attr->getLevel(); + FoundAttr = Attr; + } + } + if (FoundAttr) + return FoundAttr->getDevType(); + + return llvm::None; +} + +llvm::Optional +OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) { + if (!VD->hasAttrs()) + return llvm::None; + unsigned Level = 0; + const OMPDeclareTargetDeclAttr *FoundAttr = nullptr; + for (const auto *Attr : VD->specific_attrs()) { + if (Level < Attr->getLevel()) { + Level = Attr->getLevel(); + FoundAttr = Attr; + } + } + if (FoundAttr) + return FoundAttr->getRange().getBegin(); return llvm::None; } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2473,7 +2473,7 @@ StringRef HostDevTy = getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host); Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0; - Diag(FD->getAttr()->getLocation(), + Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), diag::note_omp_marked_device_type_here) << HostDevTy; return; @@ -2484,7 +2484,7 @@ StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( OMPC_device_type, OMPC_DEVICE_TYPE_nohost); Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1; - Diag(FD->getAttr()->getLocation(), + Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), diag::note_omp_marked_device_type_here) << NoHostDevTy; } @@ -18483,14 +18483,14 @@ Diag(Loc, diag::err_omp_region_not_file_context); return false; } - ++DeclareTargetNestingLevel; + DeclareTargetNesting.push_back(Loc); return true; } void Sema::ActOnFinishOpenMPDeclareTargetDirective() { - assert(DeclareTargetNestingLevel > 0 && + assert(!DeclareTargetNesting.empty() && "Unexpected ActOnFinishOpenMPDeclareTargetDirective"); - --DeclareTargetNestingLevel; + DeclareTargetNesting.pop_back(); } NamedDecl * @@ -18543,19 +18543,25 @@ (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced())) Diag(Loc, diag::warn_omp_declare_target_after_first_use); + auto *VD = cast(ND); Optional DevTy = - OMPDeclareTargetDeclAttr::getDeviceType(cast(ND)); - if (DevTy.hasValue() && *DevTy != DT) { + OMPDeclareTargetDeclAttr::getDeviceType(VD); + Optional AttrLoc = OMPDeclareTargetDeclAttr::getLocation(VD); + if (DevTy.hasValue() && *DevTy != DT && + (DeclareTargetNesting.empty() || + *AttrLoc != DeclareTargetNesting.back())) { Diag(Loc, diag::err_omp_device_type_mismatch) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DT) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(*DevTy); return; } Optional Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(cast(ND)); - if (!Res) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT, - SourceRange(Loc, Loc)); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); + if (!Res || (!DeclareTargetNesting.empty() && + *AttrLoc == DeclareTargetNesting.back())) { + auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( + Context, MT, DT, DeclareTargetNesting.size() + 1, + SourceRange(Loc, Loc)); ND->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); @@ -18647,7 +18653,9 @@ isa(D)) { auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( Context, OMPDeclareTargetDeclAttr::MT_To, - OMPDeclareTargetDeclAttr::DT_Any, SourceRange(IdLoc, IdLoc)); + OMPDeclareTargetDeclAttr::DT_Any, DeclareTargetNesting.size(), + SourceRange(DeclareTargetNesting.back(), + DeclareTargetNesting.back())); D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(D, A); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4666,12 +4666,11 @@ } case UPD_DECL_MARKED_OPENMP_DECLARETARGET: { - OMPDeclareTargetDeclAttr::MapTypeTy MapType = - static_cast(Record.readInt()); - OMPDeclareTargetDeclAttr::DevTypeTy DevType = - static_cast(Record.readInt()); + auto MapType = Record.readEnum(); + auto DevType = Record.readEnum(); + unsigned Level = Record.readInt(); D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit( - Reader.getContext(), MapType, DevType, readSourceRange(), + Reader.getContext(), MapType, DevType, Level, readSourceRange(), AttributeCommonInfo::AS_Pragma)); break; } diff --git a/clang/test/AST/dump.cpp b/clang/test/AST/dump.cpp --- a/clang/test/AST/dump.cpp +++ b/clang/test/AST/dump.cpp @@ -86,4 +86,4 @@ // CHECK-NEXT: | `-ReturnStmt {{.+}} // CHECK-NEXT: | `-ImplicitCastExpr {{.+}} 'int' // CHECK-NEXT: | `-DeclRefExpr {{.+}} 'int' lvalue Var {{.+}} 'f' 'int' -// CHECK-NEXT: `-OMPDeclareTargetDeclAttr {{.+}} <> Implicit MT_To +// CHECK-NEXT: `-OMPDeclareTargetDeclAttr {{.+}} Implicit MT_To DT_Any 1 diff --git a/clang/test/OpenMP/declare_target_ast_print.cpp b/clang/test/OpenMP/declare_target_ast_print.cpp --- a/clang/test/OpenMP/declare_target_ast_print.cpp +++ b/clang/test/OpenMP/declare_target_ast_print.cpp @@ -241,6 +241,28 @@ // CHECK: void cba(); // CHECK: #pragma omp end declare target +#pragma omp declare target +int abc1() { return 1; } +#pragma omp declare target to(abc1) device_type(nohost) +#pragma omp end declare target + +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: #pragma omp declare target device_type(nohost) +// CHECK-NEXT: int abc1() { +// CHECK-NEXT: return 1; +// CHECK-NEXT: } +// CHECK-NEXT: #pragma omp end declare target + +#pragma omp declare target +int inner_link; +#pragma omp declare target link(inner_link) +#pragma omp end declare target + +// CHECK-NEXT: #pragma omp declare target +// CHECK-NEXT: #pragma omp declare target link +// CHECK-NEXT: int inner_link; +// CHECK-NEXT: #pragma omp end declare target + int main (int argc, char **argv) { foo(); foo_c(); @@ -254,4 +276,5 @@ // CHECK: #pragma omp declare target // CHECK-NEXT: int ts = 1; // CHECK-NEXT: #pragma omp end declare target + #endif