if (Function->getStorageClass() == SC_PrivateExtern)
LV.mergeVisibility(HiddenVisibility, true);
+ // OpenMP target declare device functions are not callable from the host so
+ // they should not be exported from the device image. This applies to all
+ // functions as the host-callable kernel functions are emitted at codegen.
+ if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice &&
+ ((Context.getTargetInfo().getTriple().isAMDGPU() ||
+ Context.getTargetInfo().getTriple().isNVPTX()) ||
+ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Function)))
+ LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false);
+
// Note that Sema::MergeCompatibleFunctionDecls already takes care of
// merging storage classes and visibility attributes, so we don't have to
// look at previous decls in here.
#pragma omp declare target (bar)
int caz() { return 0; }
-// DEVICE-DAG: define{{ protected | }}noundef i32 [[FOO:@.*foo.*]]()
-// DEVICE-DAG: define{{ protected | }}noundef i32 [[BAR:@.*bar.*]]()
-// DEVICE-DAG: define{{ protected | }}noundef i32 [[BAZ:@.*baz.*]]()
-// DEVICE-DAG: define{{ protected | }}noundef i32 [[DOO:@.*doo.*]]()
-// DEVICE-DAG: define{{ protected | }}noundef i32 [[CAR:@.*car.*]]()
-// DEVICE-DAG: define{{ protected | }}noundef i32 [[CAZ:@.*caz.*]]()
+// DEVICE-DAG: define hidden noundef i32 [[FOO:@.*foo.*]]()
+// DEVICE-DAG: define hidden noundef i32 [[BAR:@.*bar.*]]()
+// DEVICE-DAG: define hidden noundef i32 [[BAZ:@.*baz.*]]()
+// DEVICE-DAG: define hidden noundef i32 [[DOO:@.*doo.*]]()
+// DEVICE-DAG: define hidden noundef i32 [[CAR:@.*car.*]]()
+// DEVICE-DAG: define hidden noundef i32 [[CAZ:@.*caz.*]]()
static int c = foo() + bar() + baz();
#pragma omp declare target (c)
#pragma omp declare target
T a = T();
T f = a;
-// CHECK: define{{ protected | }}void @{{.+}}foo{{.+}}([[T]]* noundef byval([[T]]) align {{.+}})
+// CHECK: define{{ hidden | }}void @{{.+}}foo{{.+}}([[T]]* noundef byval([[T]]) align {{.+}})
void foo(T a = T()) {
return;
}
-// CHECK: define{{ protected | }}[6 x i64] @{{.+}}bar{{.+}}()
+// CHECK: define{{ hidden | }}[6 x i64] @{{.+}}bar{{.+}}()
T bar() {
// CHECK: bitcast [[T]]* %{{.+}} to [6 x i64]*
// CHECK-NEXT: load [6 x i64], [6 x i64]* %{{.+}},
// CHECK-NEXT: ret [6 x i64]
return T();
}
-// CHECK: define{{ protected | }}void @{{.+}}baz{{.+}}()
+// CHECK: define{{ hidden | }}void @{{.+}}baz{{.+}}()
void baz() {
// CHECK: call [6 x i64] @{{.+}}bar{{.+}}()
// CHECK-NEXT: bitcast [[T]]* %{{.+}} to [6 x i64]*
}
T1 a1 = T1();
T1 f1 = a1;
-// CHECK: define{{ protected | }}void @{{.+}}foo1{{.+}}([[T1]]* noundef byval([[T1]]) align {{.+}})
+// CHECK: define{{ hidden | }}void @{{.+}}foo1{{.+}}([[T1]]* noundef byval([[T1]]) align {{.+}})
void foo1(T1 a = T1()) {
return;
}
-// CHECK: define{{ protected | }}[[T1]] @{{.+}}bar1{{.+}}()
+// CHECK: define{{ hidden | }}[[T1]] @{{.+}}bar1{{.+}}()
T1 bar1() {
// CHECK: load [[T1]], [[T1]]*
// CHECK-NEXT: ret [[T1]]
return T1();
}
-// CHECK: define{{ protected | }}void @{{.+}}baz1{{.+}}()
+// CHECK: define{{ hidden | }}void @{{.+}}baz1{{.+}}()
void baz1() {
// CHECK: call [[T1]] @{{.+}}bar1{{.+}}()
T1 t = bar1();
#pragma omp end declare target
// CHECK: Function Attrs: {{.*}}convergent{{.*}}
-// CHECK: define protected void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]]
+// CHECK: define hidden void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]]
// CHECK: attributes [[ATTRIBUTE_NUMBER]] = { {{.*}}convergent{{.*}} }