https://github.com/balazske updated https://github.com/llvm/llvm-project/pull/208173
From 2891ff62aa1dae5b4371e273be2c63e2f2eae073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <[email protected]> Date: Wed, 8 Jul 2026 09:26:19 +0200 Subject: [PATCH 1/2] [clang][analyzer] Improved message in uninitialized.Assign at default assignment --- .../Checkers/UndefinedAssignmentChecker.cpp | 14 +++++++++++++ clang/test/Analysis/operator-calls.cpp | 20 +++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp index 7f8923c7c09fc..f97dd8ee67d57 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -73,6 +73,20 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, } } + if (const auto *MD = + dyn_cast<CXXMethodDecl>(C.getStackFrame()->getDecl())) { + if ((MD->isCopyAssignmentOperator() || + MD->isMoveAssignmentOperator()) && + MD->isDefaulted() && B->isAssignmentOp()) { + OS << "Value assigned to field '" + << cast<MemberExpr>(B->getRHS()->IgnoreImpCasts()) + ->getMemberDecl() + ->getName() + << "' in " << (!MD->isImplicit() ? "default" : "implicit") + << " assignment operator is uninitialized"; + break; + } + } ex = B->getRHS(); break; } diff --git a/clang/test/Analysis/operator-calls.cpp b/clang/test/Analysis/operator-calls.cpp index a89624d44ac42..5af0d72b60bc0 100644 --- a/clang/test/Analysis/operator-calls.cpp +++ b/clang/test/Analysis/operator-calls.cpp @@ -111,6 +111,11 @@ namespace SynthesizedAssignment { B& operator=(B&&) = default; }; + struct C { + int x; + A a[3]; + }; + // This used to produce a warning about the iteration variable in the // synthesized assignment operator being undefined. // @@ -121,16 +126,16 @@ namespace SynthesizedAssignment { void testNoWarning() { B v, u; - u = v; // expected-warning@110{{Assigned value is uninitialized}} + u = v; // expected-warning@110{{Value assigned to field 'x' in default assignment operator is uninitialized}} // expected-note@-1{{Calling defaulted copy assignment operator for 'B'}} - // expected-note@110{{Assigned value is uninitialized}} + // expected-note@110{{Value assigned to field 'x' in default assignment operator is uninitialized}} } void testNoWarningMove() { B v, u; - u = static_cast<B &&>(v); // expected-warning@111{{Assigned value is uninitialized}} + u = static_cast<B &&>(v); // expected-warning@111{{Value assigned to field 'x' in default assignment operator is uninitialized}} // expected-note@-1{{Calling defaulted move assignment operator for 'B'}} - // expected-note@111{{Assigned value is uninitialized}} + // expected-note@111{{Value assigned to field 'x' in default assignment operator is uninitialized}} } void testConsistency() { @@ -162,4 +167,11 @@ namespace SynthesizedAssignment { clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} } + + void testImplicitAssign() { + C c1, c2; + c1 = c2; // expected-warning@114{{Value assigned to field 'x' in implicit assignment operator is uninitialized}} + // expected-note@-1{{Calling implicit copy assignment operator for 'C'}} + // expected-note@114{{Value assigned to field 'x' in implicit assignment operator is uninitialized}} + } } From 0c3ef2a8006a564d55dceb1f89ed09778b370426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <[email protected]> Date: Mon, 13 Jul 2026 12:36:33 +0200 Subject: [PATCH 2/2] safer MemberExpr check, using label in test --- .../Checkers/UndefinedAssignmentChecker.cpp | 5 +++-- clang/test/Analysis/operator-calls.cpp | 18 +++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp index f97dd8ee67d57..331df5d8c750d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -77,9 +77,10 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, dyn_cast<CXXMethodDecl>(C.getStackFrame()->getDecl())) { if ((MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) && - MD->isDefaulted() && B->isAssignmentOp()) { + MD->isDefaulted() && B->isAssignmentOp() && + isa<MemberExpr>(B->getLHS()->IgnoreImpCasts())) { OS << "Value assigned to field '" - << cast<MemberExpr>(B->getRHS()->IgnoreImpCasts()) + << cast<MemberExpr>(B->getLHS()->IgnoreImpCasts()) ->getMemberDecl() ->getName() << "' in " << (!MD->isImplicit() ? "default" : "implicit") diff --git a/clang/test/Analysis/operator-calls.cpp b/clang/test/Analysis/operator-calls.cpp index 5af0d72b60bc0..57da7cdc16923 100644 --- a/clang/test/Analysis/operator-calls.cpp +++ b/clang/test/Analysis/operator-calls.cpp @@ -107,11 +107,11 @@ namespace SynthesizedAssignment { struct B { int x; A a[3]; - B& operator=(B&) = default; - B& operator=(B&&) = default; + B& operator=(B&) = default; // #b_copy_assign + B& operator=(B&&) = default; // #b_move_assign }; - struct C { + struct C { // #c_definition int x; A a[3]; }; @@ -126,16 +126,16 @@ namespace SynthesizedAssignment { void testNoWarning() { B v, u; - u = v; // expected-warning@110{{Value assigned to field 'x' in default assignment operator is uninitialized}} + u = v; // expected-warning@#b_copy_assign{{Value assigned to field 'x' in default assignment operator is uninitialized}} // expected-note@-1{{Calling defaulted copy assignment operator for 'B'}} - // expected-note@110{{Value assigned to field 'x' in default assignment operator is uninitialized}} + // expected-note@#b_copy_assign{{Value assigned to field 'x' in default assignment operator is uninitialized}} } void testNoWarningMove() { B v, u; - u = static_cast<B &&>(v); // expected-warning@111{{Value assigned to field 'x' in default assignment operator is uninitialized}} + u = static_cast<B &&>(v); // expected-warning@#b_move_assign{{Value assigned to field 'x' in default assignment operator is uninitialized}} // expected-note@-1{{Calling defaulted move assignment operator for 'B'}} - // expected-note@111{{Value assigned to field 'x' in default assignment operator is uninitialized}} + // expected-note@#b_move_assign{{Value assigned to field 'x' in default assignment operator is uninitialized}} } void testConsistency() { @@ -170,8 +170,8 @@ namespace SynthesizedAssignment { void testImplicitAssign() { C c1, c2; - c1 = c2; // expected-warning@114{{Value assigned to field 'x' in implicit assignment operator is uninitialized}} + c1 = c2; // expected-warning@#c_definition{{Value assigned to field 'x' in implicit assignment operator is uninitialized}} // expected-note@-1{{Calling implicit copy assignment operator for 'C'}} - // expected-note@114{{Value assigned to field 'x' in implicit assignment operator is uninitialized}} + // expected-note@#c_definition{{Value assigned to field 'x' in implicit assignment operator is uninitialized}} } } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
