[ "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<MapTypeTy>
isDeclareTargetDeclaration(const ValueDecl *VD);
static llvm::Optional<DevTypeTy> getDeviceType(const ValueDecl *VD);
+ static llvm::Optional<SourceLocation> getLocation(const ValueDecl *VD);
}];
}
private:
void *VarDataSharingAttributesStack;
/// Number of nested '#pragma omp declare target' directives.
- unsigned DeclareTargetNestingLevel = 0;
+ SmallVector<SourceLocation, 4> DeclareTargetNesting;
/// Initialization of data-sharing attributes stack.
void InitDataSharingAttributesStack();
void DestroyDataSharingAttributesStack();
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;
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
if (!VD->hasAttrs())
return llvm::None;
- if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
- return Attr->getMapType();
+ unsigned Level = 0;
+ const OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
+ for (const auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
+ if (Level < Attr->getLevel()) {
+ Level = Attr->getLevel();
+ FoundAttr = Attr;
+ }
+ }
+ if (FoundAttr)
+ return FoundAttr->getMapType();
return llvm::None;
}
OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {
if (!VD->hasAttrs())
return llvm::None;
- if (const auto *Attr = VD->getAttr<OMPDeclareTargetDeclAttr>())
- return Attr->getDevType();
+ unsigned Level = 0;
+ const OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
+ for (const auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
+ if (Level < Attr->getLevel()) {
+ Level = Attr->getLevel();
+ FoundAttr = Attr;
+ }
+ }
+ if (FoundAttr)
+ return FoundAttr->getDevType();
+
+ return llvm::None;
+}
+
+llvm::Optional<SourceLocation>
+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<OMPDeclareTargetDeclAttr>()) {
+ if (Level < Attr->getLevel()) {
+ Level = Attr->getLevel();
+ FoundAttr = Attr;
+ }
+ }
+ if (FoundAttr)
+ return FoundAttr->getRange().getBegin();
return llvm::None;
}
StringRef HostDevTy =
getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
- Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
+ Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
diag::note_omp_marked_device_type_here)
<< HostDevTy;
return;
StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
- Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(),
+ Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
diag::note_omp_marked_device_type_here)
<< NoHostDevTy;
}
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 *
(ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
Diag(Loc, diag::warn_omp_declare_target_after_first_use);
+ auto *VD = cast<ValueDecl>(ND);
Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(cast<ValueDecl>(ND));
- if (DevTy.hasValue() && *DevTy != DT) {
+ OMPDeclareTargetDeclAttr::getDeviceType(VD);
+ Optional<SourceLocation> 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<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(cast<ValueDecl>(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);
isa<FunctionTemplateDecl>(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);
}
case UPD_DECL_MARKED_OPENMP_DECLARETARGET: {
- OMPDeclareTargetDeclAttr::MapTypeTy MapType =
- static_cast<OMPDeclareTargetDeclAttr::MapTypeTy>(Record.readInt());
- OMPDeclareTargetDeclAttr::DevTypeTy DevType =
- static_cast<OMPDeclareTargetDeclAttr::DevTypeTy>(Record.readInt());
+ auto MapType = Record.readEnum<OMPDeclareTargetDeclAttr::MapTypeTy>();
+ auto DevType = Record.readEnum<OMPDeclareTargetDeclAttr::DevTypeTy>();
+ unsigned Level = Record.readInt();
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
- Reader.getContext(), MapType, DevType, readSourceRange(),
+ Reader.getContext(), MapType, DevType, Level, readSourceRange(),
AttributeCommonInfo::AS_Pragma));
break;
}
// CHECK-NEXT: | `-ReturnStmt {{.+}} <line:[[@LINE-8]]:3, col:10>
// CHECK-NEXT: | `-ImplicitCastExpr {{.+}} <col:10> 'int' <LValueToRValue>
// CHECK-NEXT: | `-DeclRefExpr {{.+}} <col:10> 'int' lvalue Var {{.+}} 'f' 'int'
-// CHECK-NEXT: `-OMPDeclareTargetDeclAttr {{.+}} <<invalid sloc>> Implicit MT_To
+// CHECK-NEXT: `-OMPDeclareTargetDeclAttr {{.+}} <line:75:21> Implicit MT_To DT_Any 1
// 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();
// CHECK: #pragma omp declare target
// CHECK-NEXT: int ts = 1;
// CHECK-NEXT: #pragma omp end declare target
+
#endif