Skip to content

Commit fecd937

Browse files
authored
[Clang] Fix UB in #131515 (#132091)
It turns out trailing objects are uninitialized and APValue assignment operator requires a fully initialized object. Additionally, do some drive-by post-commit-review fixes.
1 parent 93afd8f commit fecd937

File tree

4 files changed

+15
-7
lines changed

4 files changed

+15
-7
lines changed

clang/include/clang/AST/ExprCXX.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2777,7 +2777,7 @@ class TypeTraitExpr final
27772777
ArrayRef<TypeSourceInfo *> Args, SourceLocation RParenLoc,
27782778
std::variant<bool, APValue> Value);
27792779

2780-
TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) {}
2780+
TypeTraitExpr(EmptyShell Empty, bool IsStoredAsBool);
27812781

27822782
size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
27832783
return getNumArgs();

clang/lib/AST/ExprCXX.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,7 +1868,8 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
18681868
if (TypeTraitExprBits.IsBooleanTypeTrait)
18691869
TypeTraitExprBits.Value = std::get<bool>(Value);
18701870
else
1871-
*getTrailingObjects<APValue>() = std::get<APValue>(std::move(Value));
1871+
::new (getTrailingObjects<APValue>())
1872+
APValue(std::get<APValue>(std::move(Value)));
18721873

18731874
TypeTraitExprBits.NumArgs = Args.size();
18741875
assert(Args.size() == TypeTraitExprBits.NumArgs &&
@@ -1884,6 +1885,13 @@ TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
18841885
"Only int values are supported by clang");
18851886
}
18861887

1888+
TypeTraitExpr::TypeTraitExpr(EmptyShell Empty, bool IsStoredAsBool)
1889+
: Expr(TypeTraitExprClass, Empty) {
1890+
TypeTraitExprBits.IsBooleanTypeTrait = IsStoredAsBool;
1891+
if (!IsStoredAsBool)
1892+
::new (getTrailingObjects<APValue>()) APValue();
1893+
}
1894+
18871895
TypeTraitExpr *TypeTraitExpr::Create(const ASTContext &C, QualType T,
18881896
SourceLocation Loc,
18891897
TypeTrait Kind,
@@ -1909,7 +1917,7 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C,
19091917
unsigned NumArgs) {
19101918
void *Mem = C.Allocate(totalSizeToAlloc<APValue, TypeSourceInfo *>(
19111919
IsStoredAsBool ? 0 : 1, NumArgs));
1912-
return new (Mem) TypeTraitExpr(EmptyShell());
1920+
return new (Mem) TypeTraitExpr(EmptyShell(), IsStoredAsBool);
19131921
}
19141922

19151923
CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config,

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,7 +1681,7 @@ std::optional<unsigned> Sema::GetDecompositionElementCount(QualType T,
16811681
llvm::APSInt TupleSize(Ctx.getTypeSize(Ctx.getSizeType()));
16821682
switch (isTupleLike(*this, Loc, T, TupleSize)) {
16831683
case IsTupleLike::Error:
1684-
return {};
1684+
return std::nullopt;
16851685
case IsTupleLike::TupleLike:
16861686
return TupleSize.getExtValue();
16871687
case IsTupleLike::NotTupleLike:
@@ -1706,7 +1706,7 @@ std::optional<unsigned> Sema::GetDecompositionElementCount(QualType T,
17061706
RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitField(); });
17071707

17081708
if (CheckMemberDecompositionFields(*this, Loc, OrigRD, T, BasePair))
1709-
return true;
1709+
return std::nullopt;
17101710

17111711
return NumFields;
17121712
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ static_assert(__builtin_structured_binding_size(S5) == 2);
4040
// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S5) == 2'}} \
4141
// expected-note@-1 {{expression evaluates to '1 == 2'}}
4242
static_assert(__builtin_structured_binding_size(S6) == 2);
43-
// expected-error@-1 {{static assertion failed due to requirement '__builtin_structured_binding_size(S6) == 2'}} \
4443
// expected-error@-1 {{cannot decompose class type 'S6' because it has an anonymous union member}} \
45-
// expected-note@-1 {{expression evaluates to '1 == 2'}}
44+
// expected-error@-1 {{type 'S6' cannot be decomposed}} \
45+
// expected-error@-1 {{static assertion expression is not an integral constant expression}} \
4646
// expected-note@#note-anon-union {{declared here}}
4747
static_assert(__builtin_structured_binding_size(S7) == 1);
4848

0 commit comments

Comments
 (0)