llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-analysis Author: Zhijie Wang (aeft) <details> <summary>Changes</summary> Before this PR, `FactsGenerator` handled cast nodes with `VisitImplicitCastExpr` (`CastKind` switch case) and `VisitCXXFunctionalCastExpr` (handle`gsl::Pointer` types). Other explicit casts (`CStyleCastExpr`, `CXXStaticCastExpr`, ...) had no handler, so origin was silently dropped. This is the root cause of #<!-- -->190912: the dangle in `a = StringView(s);` is missed even though the equivalent `StringView tmp(s); a = tmp;` is reported. The policy for "does this cast propagate origin?" is a function of `CastKind`, independent of whether the cast is implicit or explicit. This PR replaces `VisitImplicitCastExpr` with a generic `VisitCastExpr`. `VisitCXXFunctionalCastExpr` is retained only to preserve the `handleTestPoint` logic, then delegates to `VisitCastExpr`. This mirrors `clang/lib/AST/ExprConstant.cpp`, where each evaluator implements only `VisitCastExpr` and switches on `CastKind`; the few ExprClass-specific overrides (e.g., `VisitCXXDynamicCastExpr`) exist solely to attach constexpr-validity diagnostics before delegating back. Scope: the set of `CastKind`s that propagate origin is unchanged. Fixes: #<!-- -->190912 --- Full diff: https://github.com/llvm/llvm-project/pull/192180.diff 3 Files Affected: - (modified) clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h (+1-1) - (modified) clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp (+7-8) - (modified) clang/test/Sema/warn-lifetime-safety.cpp (+27) ``````````diff diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h index 3cf5971973c2a..a86f22a181a70 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h @@ -41,7 +41,7 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> { void VisitMemberExpr(const MemberExpr *ME); void VisitCallExpr(const CallExpr *CE); void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N); - void VisitImplicitCastExpr(const ImplicitCastExpr *ICE); + void VisitCastExpr(const CastExpr *CE); void VisitUnaryOperator(const UnaryOperator *UO); void VisitReturnStmt(const ReturnStmt *RS); void VisitBinaryOperator(const BinaryOperator *BO); diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index cae56ddd3d7c3..d27eb1be22429 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -270,14 +270,14 @@ void FactsGenerator::VisitCXXNullPtrLiteralExpr( getOriginsList(*N); } -void FactsGenerator::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) { - OriginList *Dest = getOriginsList(*ICE); +void FactsGenerator::VisitCastExpr(const CastExpr *CE) { + OriginList *Dest = getOriginsList(*CE); if (!Dest) return; - const Expr *SubExpr = ICE->getSubExpr(); + const Expr *SubExpr = CE->getSubExpr(); OriginList *Src = getOriginsList(*SubExpr); - switch (ICE->getCastKind()) { + switch (CE->getCastKind()) { case CK_LValueToRValue: // TODO: Decide what to do for x-values here. if (!SubExpr->isLValue()) @@ -288,11 +288,11 @@ void FactsGenerator::VisitImplicitCastExpr(const ImplicitCastExpr *ICE) { // `int *p, *q; p = q;`) should propagate the inner origin (what the pointer // points to), not the outer origin (the pointer's storage location). Strip // the outer lvalue origin. - flow(getOriginsList(*ICE), getRValueOrigins(SubExpr, Src), + flow(getOriginsList(*CE), getRValueOrigins(SubExpr, Src), /*Kill=*/true); return; case CK_NullToPointer: - getOriginsList(*ICE); + getOriginsList(*CE); // TODO: Flow into them a null origin. return; case CK_NoOp: @@ -517,8 +517,7 @@ void FactsGenerator::VisitCXXFunctionalCastExpr( // expression. if (handleTestPoint(FCE)) return; - if (isGslPointerType(FCE->getType())) - killAndFlowOrigin(*FCE, *FCE->getSubExpr()); + VisitCastExpr(FCE); } void FactsGenerator::VisitInitListExpr(const InitListExpr *ILE) { diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp index f87b5cbdd0230..9f4456465281a 100644 --- a/clang/test/Sema/warn-lifetime-safety.cpp +++ b/clang/test/Sema/warn-lifetime-safety.cpp @@ -936,6 +936,33 @@ void lifetimebound_ctor() { (void)v; // expected-note {{later used here}} } +void lifetimebound_ctor_functional_cast() { + LifetimeBoundCtor v; + { + MyObj obj; + v = LifetimeBoundCtor(obj); // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + (void)v; // expected-note {{later used here}} +} + +void lifetimebound_ctor_c_style_cast() { + LifetimeBoundCtor v; + { + MyObj obj; + v = (LifetimeBoundCtor)(obj); // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + (void)v; // expected-note {{later used here}} +} + +void lifetimebound_ctor_static_cast() { + LifetimeBoundCtor v; + { + MyObj obj; + v = static_cast<LifetimeBoundCtor>(obj); // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + (void)v; // expected-note {{later used here}} +} + View lifetimebound_return_of_local() { MyObj stack; return Identity(stack); // expected-warning {{address of stack memory is returned later}} `````````` </details> https://github.com/llvm/llvm-project/pull/192180 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
