Skip to content

Commit dfb6c76

Browse files
authored
[clang] ASTContex: fix getCommonSugaredType for array types (#132559)
This corrects the behaviour for getCommonSugaredType with regards to array top level qualifiers: remove differing top level qualifiers, as they must be redundant with element qualifiers. Fixes #97005
1 parent 2f8d699 commit dfb6c76

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ Bug Fixes to C++ Support
340340
by template argument deduction.
341341
- Clang is now better at instantiating the function definition after its use inside
342342
of a constexpr lambda. (#GH125747)
343+
- Clang no longer crashes when trying to unify the types of arrays with
344+
certain differences in qualifiers (this could happen during template argument
345+
deduction or when building a ternary operator). (#GH97005)
343346
- The initialization kind of elements of structured bindings
344347
direct-list-initialized from an array is corrected to direct-initialization.
345348
- Clang no longer crashes when a coroutine is declared ``[[noreturn]]``. (#GH127327)

clang/lib/AST/ASTContext.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13650,7 +13650,11 @@ static QualType getCommonArrayElementType(ASTContext &Ctx, const T *X,
1365013650
QualType EX = X->getElementType(), EY = Y->getElementType();
1365113651
QualType R = Ctx.getCommonSugaredType(EX, EY,
1365213652
/*Unqualified=*/true);
13653+
// Qualifiers common to both element types.
1365313654
Qualifiers RQ = R.getQualifiers();
13655+
// For each side, move to the top level any qualifiers which are not common to
13656+
// both element types. The caller must assume top level qualifiers might
13657+
// be different, even if they are the same type, and can be treated as sugar.
1365413658
QX += EX.getQualifiers() - RQ;
1365513659
QY += EY.getQualifiers() - RQ;
1365613660
return R;
@@ -14371,6 +14375,22 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
1437114375
// necessarily canonical types, as they may still have sugared properties.
1437214376
// QX and QY will store the sum of all qualifiers in Xs and Ys respectively.
1437314377
auto Xs = ::unwrapSugar(SX, QX), Ys = ::unwrapSugar(SY, QY);
14378+
14379+
// If this is an ArrayType, the element qualifiers are interchangeable with
14380+
// the top level qualifiers.
14381+
// * In case the canonical nodes are the same, the elements types are already
14382+
// the same.
14383+
// * Otherwise, the element types will be made the same, and any different
14384+
// element qualifiers will be moved up to the top level qualifiers, per
14385+
// 'getCommonArrayElementType'.
14386+
// In both cases, this means there may be top level qualifiers which differ
14387+
// between X and Y. If so, these differing qualifiers are redundant with the
14388+
// element qualifiers, and can be removed without changing the canonical type.
14389+
// The desired behaviour is the same as for the 'Unqualified' case here:
14390+
// treat the redundant qualifiers as sugar, remove the ones which are not
14391+
// common to both sides.
14392+
bool KeepCommonQualifiers = Unqualified || isa<ArrayType>(SX.Ty);
14393+
1437414394
if (SX.Ty != SY.Ty) {
1437514395
// The canonical nodes differ. Build a common canonical node out of the two,
1437614396
// unifying their sugar. This may recurse back here.
@@ -14386,7 +14406,7 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
1438614406
SY = Ys.pop_back_val();
1438714407
}
1438814408
}
14389-
if (Unqualified)
14409+
if (KeepCommonQualifiers)
1439014410
QX = Qualifiers::removeCommonQualifiers(QX, QY);
1439114411
else
1439214412
assert(QX == QY);

clang/test/SemaCXX/sugar-common-types.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,43 @@ namespace GH67603 {
146146
}
147147
template void h<int>();
148148
} // namespace GH67603
149+
150+
namespace arrays {
151+
namespace same_canonical {
152+
using ConstB1I = const B1[];
153+
using ConstB1C = const B1[1];
154+
const ConstB1I a = {0};
155+
const ConstB1C b = {0};
156+
N ta = a;
157+
// expected-error@-1 {{lvalue of type 'const B1[1]' (aka 'const int[1]')}}
158+
N tb = b;
159+
// expected-error@-1 {{lvalue of type 'const ConstB1C' (aka 'const const int[1]')}}
160+
N tc = 0 ? a : b;
161+
// expected-error@-1 {{lvalue of type 'const B1[1]' (aka 'const int[1]')}}
162+
} // namespace same_canonical
163+
namespace same_element {
164+
using ConstB1 = const B1;
165+
using ConstB1I = ConstB1[];
166+
using ConstB1C = ConstB1[1];
167+
const ConstB1I a = {0};
168+
const ConstB1C b = {0};
169+
N ta = a;
170+
// expected-error@-1 {{lvalue of type 'const ConstB1[1]' (aka 'const int[1]')}}
171+
N tb = b;
172+
// expected-error@-1 {{lvalue of type 'const ConstB1C' (aka 'const const int[1]')}}
173+
N tc = 0 ? a : b;
174+
// expected-error@-1 {{lvalue of type 'ConstB1[1]' (aka 'const int[1]')}}
175+
} // namespace same_element
176+
namespace balanced_qualifiers {
177+
using ConstX1C = const volatile X1[1];
178+
using Y1C = volatile Y1[1];
179+
extern volatile ConstX1C a;
180+
extern const volatile Y1C b;
181+
N ta = a;
182+
// expected-error@-1 {{lvalue of type 'volatile ConstX1C' (aka 'volatile const volatile int[1]')}}
183+
N tb = b;
184+
// expected-error@-1 {{lvalue of type 'const volatile Y1C' (aka 'const volatile volatile int[1]')}}
185+
N tc = 0 ? a : b;
186+
// expected-error@-1 {{lvalue of type 'const volatile volatile B1[1]' (aka 'const volatile volatile int[1]')}}
187+
} // namespace balanced_qualifiers
188+
} // namespace arrays

0 commit comments

Comments
 (0)