diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 47ef2f80ac3f2..2f43dc4021fd8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -909,6 +909,8 @@ Bug Fixes in This Version being deleted has a potentially throwing destructor (#GH118660). - Clang now outputs correct values when #embed data contains bytes with negative signed char values (#GH102798). +- Fix crash due to unknown references and pointer implementation and handling of + base classes. (GH139452) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 23602362eaa79..e0746f4532245 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3311,7 +3311,11 @@ static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, return false; // Extract most-derived object and corresponding type. - DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); + // FIXME: After implementing P2280R4 it became possible to get references + // here. We do MostDerivedType->getAsCXXRecordDecl() in several other + // locations and if we see crashes in those locations in the future + // it may make more sense to move this fix into Lvalue::set. + DerivedDecl = D.MostDerivedType.getNonReferenceType()->getAsCXXRecordDecl(); if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) return false; diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 6c9a87267109c..87beeb4d3dc84 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -179,3 +179,24 @@ namespace extern_reference_used_as_unknown { int y; constinit int& g = (x,y); // expected-warning {{left operand of comma operator has no effect}} } + +namespace GH139452 { +struct Dummy { + explicit operator bool() const noexcept { return true; } +}; + +struct Base { int error; }; +struct Derived : virtual Base { }; + +template +constexpr R get_value() { + const auto& derived_val = Derived{}; + if (derived_val.error != 0) + /* nothing */; + return R{}; +} + +int f() { + return !get_value(); // contextually convert the function call result to bool +} +}