Author: Balázs Benics Date: 2026-10-14T19:00:36+01:00 New Revision: ed1cc5b6583155512baf116ab45542de1fc23770
URL: https://github.com/llvm/llvm-project/commit/ed1cc5b6583155512baf116ab45542de1fc23770 DIFF: https://github.com/llvm/llvm-project/commit/ed1cc5b6583155512baf116ab45542de1fc23770.diff LOG: [LifetimeSafety] Propagate origins through BaseToDerived casts (#231896) In addition to what the title says, I added a few tests demonstrating the pre-existing origin shape mismatch detection and borrow drop behavior. Assissted-By: claude Added: Modified: clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp clang/test/Sema/LifetimeSafety/safety.cpp Removed: ################################################################################ diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index b67288a190f17..6a805bb7be2d8 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -309,6 +309,9 @@ void FactsGenerator::VisitCastExpr(const CastExpr *CE) { return; case CK_UncheckedDerivedToBase: case CK_DerivedToBase: + case CK_BaseToDerived: + // The conversion cast doesn't change what it refers to, so preserve the + // borrow if we can. // It is possible that the derived class and base class have diff erent // gsl::Pointer annotations. Skip if their origin shape diff er. if (Dest && Src && Dest->getLength() == Src->getLength()) diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp index 63874c9bb8bae..18800830cb59f 100644 --- a/clang/test/Sema/LifetimeSafety/safety.cpp +++ b/clang/test/Sema/LifetimeSafety/safety.cpp @@ -4804,3 +4804,73 @@ void asm_inout_operand_is_read() { } } // namespace class_reads } // namespace what_is_a_use + +namespace DowncastTests { + +struct Base {}; +struct Derived : Base {}; +Derived *DowncastReturnsStackAddress() { + Derived d; + Base *b = &d; // expected-warning {{stack memory associated with local variable 'd' is returned}} + return static_cast<Derived *>(b); // expected-note {{returned here}} +} + +// A downcast that does not outlive the pointee is fine. +void use(Derived *); +void DowncastWithinScopeIsOk() { + Derived d; + Base *b = &d; + use(static_cast<Derived *>(b)); // ok +} + +struct RefBase {}; +struct RefDerived : RefBase {}; +RefDerived *DowncastReferenceReturnsStackAddress() { + RefDerived d; + RefBase &b = d; // expected-warning {{stack memory associated with local variable 'd' is returned}} + RefDerived &r = static_cast<RefDerived &>(b); + return &r; // expected-note {{returned here}} +} + +void use(Derived &); +void DowncastReferenceWithinScopeIsOk() { + Derived d; + Base &b = d; + use(static_cast<Derived &>(b)); // ok +} + +} // namespace DowncastTests + +namespace DifferentOriginShapes { + +struct [[gsl::Pointer]] GslBase {}; +struct [[gsl::Pointer]] GslDerived : GslBase {}; + +GslDerived *MatchingAnnotationsStillDetected() { + GslDerived d; + GslBase *b = &d; // expected-warning {{stack memory associated with local variable 'd' is returned}} + return static_cast<GslDerived *>(b); // expected-note {{returned here}} +} + +// Base is a gsl::Pointer but the derived is not. +// They have diff erent origin shapes, thus the borrow is dropped, thus no dangling is reported. +struct [[gsl::Pointer]] GslOnlyBase {}; +struct PlainFromGsl : GslOnlyBase {}; + +PlainFromGsl *BaseAnnotatedMismatchDropsBorrow() { + PlainFromGsl d; + GslOnlyBase *b = &d; // FN: See comment above. + return static_cast<PlainFromGsl *>(b); // no note +} + +// Mismatch the other way: derived is a gsl::Pointer, base is not. +// Same outcome. +struct PlainBase2 {}; +struct [[gsl::Pointer]] GslOnlyDerived : PlainBase2 {}; + +GslOnlyDerived *DerivedAnnotatedMismatchDropsBorrow() { + GslOnlyDerived d; + PlainBase2 *b = &d; // FN: See comment above. + return static_cast<GslOnlyDerived *>(b); // no note +} +} // namespace DifferentOriginShapes _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
