Skip to content

Commit 9977314

Browse files
committed
address feedback
1 parent 2733642 commit 9977314

File tree

5 files changed

+41
-11
lines changed

5 files changed

+41
-11
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,10 +1922,12 @@ The ``__builtin_structured_binding_size(T)`` type trait returns
19221922
the *structured binding size* ([dcl.struct.bind]) of type ``T``
19231923

19241924
This is equivalent to the size of the pack ``p`` in ``auto&& [...p] = declval<T&>();``.
1925-
If the argument cannot be decomposed (ie not a builtin array, builtin SIMD vector,
1926-
builtin complex, *tuple-like* type or destructurable class type),
1927-
``__builtin_structured_binding_size(T)`` is not a valid expression
1928-
(``__builtin_structured_binding_size`` is SFINAE-friendly).
1925+
If the argument cannot be decomposed, ``__builtin_structured_binding_size(T)``
1926+
is not a valid expression (``__builtin_structured_binding_size`` is SFINAE-friendly).
1927+
1928+
builtin arrays, builtin SIMD vectors,
1929+
builtin complex types, *tuple-like* types, and decomposable class types
1930+
are decomposable types.
19291931

19301932
A type is considered a valid *tuple-like* if ``std::tuple_size_v<T>`` is a valid expression,
19311933
even if there is no valid ``std::tuple_element`` specialization or suitable

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,7 +1479,7 @@ static bool CheckMemberDecompositionFields(Sema &S, SourceLocation Loc,
14791479
const CXXRecordDecl *OrigRD,
14801480
QualType DecompType,
14811481
DeclAccessPair BasePair) {
1482-
const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
1482+
const auto *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
14831483
if (!RD)
14841484
return true;
14851485

@@ -1527,7 +1527,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
15271527
CXXCastPath BasePath;
15281528
DeclAccessPair BasePair =
15291529
findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);
1530-
const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
1530+
const auto *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
15311531
if (!RD)
15321532
return true;
15331533
QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD),
@@ -1698,7 +1698,7 @@ std::optional<unsigned> Sema::GetDecompositionElementCount(QualType T,
16981698
CXXCastPath BasePath;
16991699
DeclAccessPair BasePair =
17001700
findDecomposableBaseClass(*this, Loc, OrigRD, BasePath);
1701-
const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
1701+
const auto *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
17021702
if (!RD)
17031703
return std::nullopt;
17041704

clang/lib/Sema/SemaExpr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4685,9 +4685,9 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
46854685
} else if (ExprKind == UETT_VecStep) {
46864686
isInvalid = CheckVecStepExpr(E);
46874687
} else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {
4688-
Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
4689-
isInvalid = true;
4690-
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
4688+
Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
4689+
isInvalid = true;
4690+
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
46914691
Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0;
46924692
isInvalid = true;
46934693
} else if (ExprKind == UETT_VectorElements) {

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5066,7 +5066,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
50665066
case UTT_IsInterfaceClass:
50675067
return true;
50685068

5069-
// We diagnose incomplete class types later
5069+
// We diagnose incomplete class types later.
50705070
case UTT_StructuredBindingSize:
50715071
return true;
50725072

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ struct S0 {};
66
struct S1 {int a;};
77
struct S2 {int a; int b;};
88
struct S3 {double a; int b; int c;};
9+
struct S4 {int a: 1; int b :2;};
10+
struct S5 {int : 1; int b :2;};
11+
struct S6 {union {int a;}; }; // #note-anon-union
12+
struct S7 {int a[];};
913

1014

1115

@@ -29,6 +33,20 @@ static_assert(__builtin_structured_binding_size(S1) == 0);
2933
// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S1) == 0'}} \
3034
// expected-note@-1 {{expression evaluates to '1 == 0'}}
3135
static_assert(__builtin_structured_binding_size(S1) == 1);
36+
static_assert(__builtin_structured_binding_size(S2) == 2);
37+
static_assert(__builtin_structured_binding_size(S3) == 3);
38+
static_assert(__builtin_structured_binding_size(S4) == 2);
39+
static_assert(__builtin_structured_binding_size(S5) == 2);
40+
// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S5) == 2'}} \
41+
// expected-note@-1 {{expression evaluates to '1 == 2'}}
42+
static_assert(__builtin_structured_binding_size(S6) == 2);
43+
// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S6) == 2'}} \
44+
// expected-error@-1 {{cannot decompose class type 'S6' because it has an anonymous union member}} \
45+
// expected-note@-1 {{expression evaluates to '1 == 2'}}
46+
// expected-note@#note-anon-union {{declared here}}
47+
static_assert(__builtin_structured_binding_size(S7) == 1);
48+
49+
3250
static_assert(__builtin_structured_binding_size(SD) == 1);
3351
static_assert(__builtin_structured_binding_size(SE1) == 1);
3452
// expected-error@-1 {{cannot decompose class type 'SE1': both it and its base class 'S1' have non-static data members}} \
@@ -151,6 +169,16 @@ static_assert(!is_destructurable<TSizeError>);
151169
}
152170

153171

172+
struct S {
173+
int x;
174+
int y;
175+
static_assert(__builtin_structured_binding_size(S) == 2);
176+
//expected-error@-1 {{incomplete type 'S' where a complete type is required}} \
177+
// expected-error@-1 {{type 'S' cannot be decomposed}} \
178+
// expected-error@-1 {{static assertion expression is not an integral constant expression}} \
179+
// expected-note@-4 {{definition of 'S' is not complete until the closing '}'}}
180+
};
181+
154182
// Check we can implement std::exec::tag_of_t
155183
template <typename T>
156184
struct type_identity {

0 commit comments

Comments
 (0)