Skip to content

Commit 8905a8c

Browse files
authored
[SYCL] Fix address space assertion with templates (#2798)
In certain complex template instantiations, address space mismatches cause the compiler to assert instead of issuing errors gracefully. This fixes one such case identified in PR #2763. Signed-off-by: Premanand M Rao <[email protected]>
1 parent 0cf42f2 commit 8905a8c

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
lines changed

clang/include/clang/AST/Type.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,8 @@ class Qualifiers {
384384
| (((uint32_t) space) << AddressSpaceShift);
385385
}
386386
void removeAddressSpace() { setAddressSpace(LangAS::Default); }
387-
void addAddressSpace(LangAS space) {
388-
assert(space != LangAS::Default);
387+
void addAddressSpace(LangAS space, bool AllowDefaultAddrSpace = false) {
388+
assert(space != LangAS::Default || AllowDefaultAddrSpace);
389389
setAddressSpace(space);
390390
}
391391

clang/lib/Sema/SemaInit.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4905,7 +4905,8 @@ static void TryReferenceInitializationCore(Sema &S,
49054905
// Add addr space conversion if required.
49064906
if (T1Quals.getAddressSpace() != T2Quals.getAddressSpace()) {
49074907
auto T4Quals = cv1T4.getQualifiers();
4908-
T4Quals.addAddressSpace(T1Quals.getAddressSpace());
4908+
T4Quals.addAddressSpace(T1Quals.getAddressSpace(),
4909+
S.getLangOpts().SYCLIsDevice);
49094910
QualType cv1T4WithAS = S.Context.getQualifiedType(T2, T4Quals);
49104911
Sequence.AddQualificationConversionStep(cv1T4WithAS, ValueKind);
49114912
cv1T4 = cv1T4WithAS;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64 -verify %s
2+
3+
// Test that the compiler no longer asserts while processing this test case.
4+
5+
template <int N>
6+
struct integral_constant {
7+
static constexpr int val = N;
8+
};
9+
template <typename T>
10+
T &&convert(int);
11+
template <typename T>
12+
auto declval(convert<T>(0));
13+
template <typename Op1, typename Op2>
14+
class sub_group {
15+
template <typename T, decltype(declval<T>)>
16+
// expected-note@+1 {{possible target for call}}
17+
static integral_constant<true> binary_op();
18+
// expected-error@+1 {{reference to overloaded function could not be resolved; did you mean to call it?}}
19+
decltype(binary_op<Op1, Op2>) i;
20+
};
21+
// expected-note-re@+2 {{in instantiation {{.*}} requested here}}
22+
template <typename n>
23+
struct group : sub_group<n, int> {
24+
};
25+
template <typename T>
26+
struct wrapper {
27+
typedef T val;
28+
};
29+
class element_type {
30+
};
31+
struct Container {
32+
using __element_type = __attribute__((opencl_global)) element_type;
33+
};
34+
template <bool, class Base, class> using BaseImpl = Base;
35+
// expected-note-re@+1 2{{candidate constructor {{.*}} not viable: {{.*}}}}
36+
template <int> class id_type {
37+
template <class...> struct Base;
38+
// expected-note-re@+1 {{in instantiation {{.*}} requested here}}
39+
template <class Der> struct Base<Der> : BaseImpl<Der::val, Base<>, Der> {};
40+
// expected-note-re@+1 {{in instantiation {{.*}} requested here}}
41+
template <typename T> using Base2 = wrapper<typename Base<group<T>>::val>;
42+
// expected-note-re@+3 {{in instantiation {{.*}} requested here}}
43+
// expected-note-re@+2 {{in instantiation {{.*}} required here}}
44+
// expected-note-re@+1 {{candidate template ignored: {{.*}}}}
45+
template <typename T, typename = Base2<T>> id_type(T &);
46+
};
47+
id_type<1> get() {
48+
Container::__element_type *ElemPtr;
49+
// expected-error@+2 {{no viable conversion from returned value of type 'Container::__element_type' (aka '__global element_type') to function return type 'id_type<1>'}}
50+
// expected-note-re@+1 {{while substituting {{.*}}}}
51+
return ElemPtr[0];
52+
}

0 commit comments

Comments
 (0)