Skip to content

Commit a6d26c5

Browse files
authored
[clang] Fix dangling false positives for conditional operators. (llvm#120233)
When analyzing a dangling gsl pointer, we currently filter out all field access `MemberExpr` to avoid common false positives (`string_view sv = Temp().sv`), However, this filter only applies to direct MemberExpr instances, leaving the conditional operator as an escaping example (`GSLPointer pointer(Cond ? Owner().ptr : GSLPointer());`). This patch extends the MemberExpr logic to handle the conditional operator. The heuristic is intentionally simple, which may result in some false negatives. However, it effectively covers common cases like `std::string_view sv = cond ? "123" : std::string();`, which is a reasonable trade-off. Fixes llvm#120206
1 parent 93743ee commit a6d26c5

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,8 @@ Improvements to Clang's diagnostics
706706
return ptr + index < ptr; // warning
707707
}
708708
709+
- Fix -Wdangling false positives on conditional operators (#120206).
710+
709711
Improvements to Clang's time-trace
710712
----------------------------------
711713

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,15 @@ static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call,
582582
// Temp().ptr; // Here ptr might not dangle.
583583
if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
584584
return;
585+
// Avoid false positives when the object is constructed from a conditional
586+
// operator argument. A common case is:
587+
// // 'ptr' might not be owned by the Owner object.
588+
// std::string_view s = cond() ? Owner().ptr : sv;
589+
if (const auto *Cond =
590+
dyn_cast<AbstractConditionalOperator>(Arg->IgnoreImpCasts());
591+
Cond && isPointerLikeType(Cond->getType()))
592+
return;
593+
585594
auto ReturnType = Callee->getReturnType();
586595

587596
// Once we initialized a value with a non gsl-owner reference, it can no

clang/test/Sema/warn-lifetime-analysis-nocfg.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,3 +777,32 @@ void test4() {
777777
}
778778

779779
} // namespace LifetimeboundInterleave
780+
781+
namespace GH120206 {
782+
struct S {
783+
std::string_view s;
784+
};
785+
786+
struct [[gsl::Owner]] Q1 {
787+
const S* get() const [[clang::lifetimebound]];
788+
};
789+
std::string_view test1(int c, std::string_view sv) {
790+
std::string_view k = c > 1 ? Q1().get()->s : sv;
791+
if (c == 1)
792+
return c > 1 ? Q1().get()->s : sv;
793+
Q1 q;
794+
return c > 1 ? q.get()->s : sv;
795+
}
796+
797+
struct Q2 {
798+
const S* get() const [[clang::lifetimebound]];
799+
};
800+
std::string_view test2(int c, std::string_view sv) {
801+
std::string_view k = c > 1 ? Q2().get()->s : sv;
802+
if (c == 1)
803+
return c > 1 ? Q2().get()->s : sv;
804+
Q2 q;
805+
return c > 1 ? q.get()->s : sv;
806+
}
807+
808+
} // namespace GH120206

0 commit comments

Comments
 (0)