[clang] [clang] Reject invalid record declarations in builtin bit_cast checks (PR #235341)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 04:03:33 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Daniel Petrovic (daniel-petrovic)
<details>
<summary>Changes</summary>
Prevent crash when evaluating builtin bit_cast with invalid record types.
The crash is caused by the unconditional recursive call in constexpr eligibility check.
This fix checks RecordDecl::isInvalidDecl() before the recursive call in constexpr evaluator as well as in bytecode interpreter.
Fixes: #<!-- -->235252
---
Full diff: https://github.com/llvm/llvm-project/pull/235341.diff
3 Files Affected:
- (modified) clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp (+2)
- (modified) clang/lib/AST/ExprConstant.cpp (+2)
- (modified) clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp (+15)
``````````diff
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index 3bec4f3bf1396b..ebaf4ecb2da637 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -295,6 +295,8 @@ static bool CheckBitcastType(InterpState &S, CodePtr OpPC, QualType T,
return diag(E_Volatile);
if (const RecordDecl *RD = T->getAsRecordDecl()) {
+ if (RD->isInvalidDecl())
+ return false;
if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
for (const CXXBaseSpecifier &BS : CXXRD->bases()) {
if (!CheckBitcastType(S, OpPC, BS.getType(), IsToType))
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 3762bc83c779b0..d8e3b0538a9bb8 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8604,6 +8604,8 @@ static bool checkBitCastConstexprEligibilityType(SourceLocation Loc,
return diag(3);
if (RecordDecl *Record = Ty->getAsRecordDecl()) {
+ if (Record->isInvalidDecl())
+ return false;
if (auto *CXXRD = dyn_cast<CXXRecordDecl>(Record)) {
for (CXXBaseSpecifier &BS : CXXRD->bases())
if (!checkBitCastConstexprEligibilityType(Loc, BS.getType(), Info, Ctx,
diff --git a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
index ea5333df0b4698..09a53ea6d4ea54 100644
--- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
+++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
@@ -550,3 +550,18 @@ namespace InvalidBaseClass {
};
static_assert(__builtin_bit_cast(char, E()) == 0); // expected-error {{not an integral constant expression}}
}
+
+namespace InvalidRecord {
+ template <class To, class From>
+ constexpr To cast(const From& from) {
+ __builtin_bit_cast(To, from); // expected-warning {{expression result unused}}
+ }
+
+ struct S { // expected-note {{definition of 'InvalidRecord::S' is not complete until the closing '}'}}
+ S s; // expected-error {{field has incomplete type 'S'}}
+ enum E { e } E;
+ };
+
+ static_assert(cast<S>((char)42).E == S::E::e); // expected-error {{static assertion expression is not an integral constant expression}}
+ // expected-note at -1 {{in instantiation of function template specialization 'InvalidRecord::cast<InvalidRecord::S, char>' requested here}}
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/235341
More information about the cfe-commits
mailing list