Skip to content

Commit 94efaa9

Browse files
committed
[clang] diagnose invalid std::tuple_size sizes
Fixes #159563
1 parent 3fe85ca commit 94efaa9

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ Improvements to Clang's diagnostics
262262
Moved the warning for a missing (though implied) attribute on a redeclaration into this group.
263263
Added a new warning in this group for the case where the attribute is missing/implicit on
264264
an override of a virtual method.
265+
- Implemented diagnostics when retrieving the tuple size for types where its specialization of `std::tuple_size`
266+
produces an invalid size (either negative or greater than the implementation limit). (#GH159563)
265267
- Fixed fix-it hint for fold expressions. Clang now correctly places the suggested right
266268
parenthesis when diagnosing malformed fold expressions. (#GH151787)
267269
- Added fix-it hint for when scoped enumerations require explicit conversions for binary operations. (#GH24265)
@@ -347,8 +349,8 @@ Bug Fixes in This Version
347349
and vector of 4 ``float`` values. (#GH155405)
348350
- Fixed inconsistent shadow warnings for lambda capture of structured bindings.
349351
Previously, ``[val = val]`` (regular parameter) produced no warnings with ``-Wshadow``
350-
while ``[a = a]`` (where ``a`` is from ``auto [a, b] = std::make_pair(1, 2)``)
351-
incorrectly produced warnings. Both cases now consistently show no warnings with
352+
while ``[a = a]`` (where ``a`` is from ``auto [a, b] = std::make_pair(1, 2)``)
353+
incorrectly produced warnings. Both cases now consistently show no warnings with
352354
``-Wshadow`` and show uncaptured-local warnings with ``-Wshadow-all``. (#GH68605)
353355
- Fixed a failed assertion with a negative limit parameter value inside of
354356
``__has_embed``. (#GH157842)

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,9 @@ def err_decomp_decl_std_tuple_element_not_specialized : Error<
638638
def err_decomp_decl_std_tuple_size_not_constant : Error<
639639
"cannot decompose this type; 'std::tuple_size<%0>::value' "
640640
"is not a valid integral constant expression">;
641+
def err_decomp_decl_std_tuple_size_invalid
642+
: Error<"cannot decompose this type; 'std::tuple_size<%0>::value' "
643+
"is not a valid size: %1">;
641644
def note_in_binding_decl_init : Note<
642645
"in implicit initialization of binding declaration %0">;
643646
def err_arg_is_not_destructurable : Error<

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,16 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
12221222
if (E.isInvalid())
12231223
return IsTupleLike::Error;
12241224

1225+
if (Size < 0 || Size >= UINT_MAX) {
1226+
llvm::SmallVector<char, 16> Str;
1227+
Size.toString(Str);
1228+
S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_invalid)
1229+
<< printTemplateArgs(S.Context.getPrintingPolicy(), Args,
1230+
/*Params=*/nullptr)
1231+
<< StringRef(Str.data(), Str.size());
1232+
return IsTupleLike::Error;
1233+
}
1234+
12251235
return IsTupleLike::TupleLike;
12261236
}
12271237

clang/test/SemaCXX/builtin-structured-binding-size.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -verify
2-
// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -verify -fexperimental-new-constant-interpreter
1+
// RUN: %clang_cc1 %s -triple=x86_64 -std=c++2c -fsyntax-only -verify
2+
// RUN: %clang_cc1 %s -triple=x86_64 -std=c++2c -fsyntax-only -verify -fexperimental-new-constant-interpreter
33

44

55
struct S0 {};
@@ -229,3 +229,19 @@ static_assert(__is_same_as(tag_of_t<S1>, int));
229229
static_assert(__is_same_as(tag_of_t<int>, int)); // error
230230
// expected-error@-1 {{constraints not satisfied for alias template 'tag_of_t' [with T = int]}}
231231
// expected-note@#tag-of-constr {{because substituted constraint expression is ill-formed: type 'int' cannot be decomposed}}
232+
233+
struct MinusOne;
234+
template <> struct ::std::tuple_size<MinusOne> {
235+
static constexpr int value = -1;
236+
};
237+
int minus_one = __builtin_structured_binding_size(MinusOne);
238+
// expected-error@-1 {{cannot decompose this type; 'std::tuple_size<MinusOne>::value' is not a valid size: -1}}
239+
// expected-error@-2 {{type 'MinusOne' cannot be decomposed}}
240+
241+
struct UintMax;
242+
template <> struct ::std::tuple_size<UintMax> {
243+
static constexpr unsigned value = -1;
244+
};
245+
int uint_max = __builtin_structured_binding_size(UintMax);
246+
// expected-error@-1 {{cannot decompose this type; 'std::tuple_size<UintMax>::value' is not a valid size: 4294967295}}
247+
// expected-error@-2 {{type 'UintMax' cannot be decomposed}}

0 commit comments

Comments
 (0)