Skip to content

Commit 573e0fe

Browse files
committed
[clang] ASTContex: fix getCommonSugaredType for array types
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 fb44c54 commit 573e0fe

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-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, per ternary operator or template argument
345+
deduction. (#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: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14371,6 +14371,22 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
1437114371
// necessarily canonical types, as they may still have sugared properties.
1437214372
// QX and QY will store the sum of all qualifiers in Xs and Ys respectively.
1437314373
auto Xs = ::unwrapSugar(SX, QX), Ys = ::unwrapSugar(SY, QY);
14374+
14375+
// If this is an ArrayType, the element qualifiers are interchangeable with
14376+
// the top level qualifiers.
14377+
// * In case the canonical nodes are the same, the elements types are already
14378+
// the same.
14379+
// * Otherwise, the element types will be made the same, and any different
14380+
// element qualifiers will be pumped up to the top level qualifiers, per
14381+
// 'getCommonArrayElementType'.
14382+
// In both cases, this means there may be top level qualifiers which differ
14383+
// between X and Y. If so, these differing qualifiers are redundant with the
14384+
// element qualifiers, and can be removed without changing the canonical type.
14385+
// The desired behaviour is the same as for the 'Unqualified' case here:
14386+
// treat the redundant qualifiers as sugar, remove the ones which are not
14387+
// common to both sides.
14388+
bool KeepCommonQualifiers = Unqualified || isa<ArrayType>(SX.Ty);
14389+
1437414390
if (SX.Ty != SY.Ty) {
1437514391
// The canonical nodes differ. Build a common canonical node out of the two,
1437614392
// unifying their sugar. This may recurse back here.
@@ -14386,7 +14402,7 @@ QualType ASTContext::getCommonSugaredType(QualType X, QualType Y,
1438614402
SY = Ys.pop_back_val();
1438714403
}
1438814404
}
14389-
if (Unqualified)
14405+
if (KeepCommonQualifiers)
1439014406
QX = Qualifiers::removeCommonQualifiers(QX, QY);
1439114407
else
1439214408
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)