Skip to content

Commit 753f7e8

Browse files
authored
[OpenCL] Fix an infinite loop in builidng AddrSpaceQualType (#92612)
In building AddrSpaceQualType (#90048), there is a bug in removeAddrSpaceQualType() for arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. This results in an infinite loop in removeAddrSpaceQualType. To fix the issue, we use ASTContext::getUnqualifiedArrayType instead, which strips the qualifier off the element type, then reconstruct the array type.
1 parent 1f07bfb commit 753f7e8

File tree

3 files changed

+45
-14
lines changed

3 files changed

+45
-14
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2611,7 +2611,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
26112611
///
26122612
/// \returns if this is an array type, the completely unqualified array type
26132613
/// that corresponds to it. Otherwise, returns T.getUnqualifiedType().
2614-
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
2614+
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals) const;
26152615

26162616
/// Determine whether the given types are equivalent after
26172617
/// cvr-qualifiers have been removed.

clang/lib/AST/ASTContext.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3054,21 +3054,27 @@ QualType ASTContext::removeAddrSpaceQualType(QualType T) const {
30543054
if (!T.hasAddressSpace())
30553055
return T;
30563056

3057-
// If we are composing extended qualifiers together, merge together
3058-
// into one ExtQuals node.
30593057
QualifierCollector Quals;
30603058
const Type *TypeNode;
3059+
// For arrays, strip the qualifier off the element type, then reconstruct the
3060+
// array type
3061+
if (T.getTypePtr()->isArrayType()) {
3062+
T = getUnqualifiedArrayType(T, Quals);
3063+
TypeNode = T.getTypePtr();
3064+
} else {
3065+
// If we are composing extended qualifiers together, merge together
3066+
// into one ExtQuals node.
3067+
while (T.hasAddressSpace()) {
3068+
TypeNode = Quals.strip(T);
3069+
3070+
// If the type no longer has an address space after stripping qualifiers,
3071+
// jump out.
3072+
if (!QualType(TypeNode, 0).hasAddressSpace())
3073+
break;
30613074

3062-
while (T.hasAddressSpace()) {
3063-
TypeNode = Quals.strip(T);
3064-
3065-
// If the type no longer has an address space after stripping qualifiers,
3066-
// jump out.
3067-
if (!QualType(TypeNode, 0).hasAddressSpace())
3068-
break;
3069-
3070-
// There might be sugar in the way. Strip it and try again.
3071-
T = T.getSingleStepDesugaredType(*this);
3075+
// There might be sugar in the way. Strip it and try again.
3076+
T = T.getSingleStepDesugaredType(*this);
3077+
}
30723078
}
30733079

30743080
Quals.removeAddressSpace();
@@ -6093,7 +6099,7 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) const {
60936099
}
60946100

60956101
QualType ASTContext::getUnqualifiedArrayType(QualType type,
6096-
Qualifiers &quals) {
6102+
Qualifiers &quals) const {
60976103
SplitQualType splitType = type.getSplitUnqualifiedType();
60986104

60996105
// FIXME: getSplitUnqualifiedType() actually walks all the way to
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
2+
//RUN: %clang_cc1 %s -triple spir -emit-llvm -O1 -o - | FileCheck %s
3+
4+
// CHECK-LABEL: define dso_local spir_kernel void @test(
5+
// CHECK-SAME: ptr addrspace(1) nocapture noundef readonly align 8 [[IN:%.*]], ptr addrspace(1) nocapture noundef writeonly align 8 [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !kernel_arg_addr_space [[META3:![0-9]+]] !kernel_arg_access_qual [[META4:![0-9]+]] !kernel_arg_type [[META5:![0-9]+]] !kernel_arg_base_type [[META5]] !kernel_arg_type_qual [[META6:![0-9]+]] {
6+
// CHECK-NEXT: entry:
7+
// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[IN]], i32 8
8+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(1) [[ARRAYIDX1]], align 8, !tbaa [[TBAA7:![0-9]+]]
9+
// CHECK-NEXT: store i64 [[TMP0]], ptr addrspace(1) [[OUT]], align 8, !tbaa [[TBAA7]]
10+
// CHECK-NEXT: ret void
11+
//
12+
__kernel void test(__global long *In, __global long *Out) {
13+
long m[4] = { In[0], In[1], 0, 0 };
14+
*Out = m[1];
15+
}
16+
//.
17+
// CHECK: [[META3]] = !{i32 1, i32 1}
18+
// CHECK: [[META4]] = !{!"none", !"none"}
19+
// CHECK: [[META5]] = !{!"long*", !"long*"}
20+
// CHECK: [[META6]] = !{!"", !""}
21+
// CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0}
22+
// CHECK: [[META8]] = !{!"long", [[META9:![0-9]+]], i64 0}
23+
// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0}
24+
// CHECK: [[META10]] = !{!"Simple C++ TBAA"}
25+
//.

0 commit comments

Comments
 (0)