llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Ella Ma (Snape3058) <details> <summary>Changes</summary> Addressing #<!-- -->173210 in terms of path-sensitive analysis. The self-assignment initialization `Type var = var;` is an idiom in C code. The analyzer is expected to suppress uninitialized assignment reports for this idiom and delay reporting until the uninitialized variable is actually used. Since GCC will not generate assembly code for such usage, even if under -O0 optimization (but Clang will), this patch resolves this problem by ignoring such self-assigned `DeclStmt`s in the `ExprEngine`. This is only a C idiom. In C++, both the frontend warning and the analyzer are expected to report this usage. --- Full diff: https://github.com/llvm/llvm-project/pull/187530.diff 2 Files Affected: - (modified) clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp (+14) - (added) clang/test/Analysis/issue-173210-self-assign-init.c (+29) ``````````diff diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 67beed5dbb6fb..214f266e21e4c 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -624,6 +624,20 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, return; } + // Bypass a nop initialization that assign to itself at variable declaration. + // I.e., int x = x; + // This is an idiom in C code and GCC will not generate any assemblies for + // this self initialization, even under -O0, but Clang will. + // Since the frontend will warn in C++ code, and it is ill-formed for C++ + // reference types, the bypass is effected to C code only. + if (getContext().getLangOpts().getCLangStd()) + if (const Expr *EI = VD->getInit()) + if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(EI->IgnoreImpCasts())) + if (VD == DR->getDecl()) { + Dst.insert(Pred); + return; + } + // FIXME: all pre/post visits should eventually be handled by ::Visit(). ExplodedNodeSet dstPreVisit; getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); diff --git a/clang/test/Analysis/issue-173210-self-assign-init.c b/clang/test/Analysis/issue-173210-self-assign-init.c new file mode 100644 index 0000000000000..c9e5e2be58875 --- /dev/null +++ b/clang/test/Analysis/issue-173210-self-assign-init.c @@ -0,0 +1,29 @@ +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core,debug.ExprInspection \ +// RUN: -verify + +// Self assignment initialization in C code will be treated as nop. +// We will not report the VarDecl, but the following DeclRefExpr if it has not +// yet been initialized then. + +void clang_analyzer_warnIfReached(); + +struct S { int x; }; +union U { int x; }; + +void nowarn() { + int x = x; // no-warning + int *p = p; // no-warning + struct S s = s; // no-warning + union U u = u; // no-warning + // Ensure the analysis is not terminated sliently. + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +int warn() { + int x = x; + return x; // expected-warning{{Undefined or garbage value returned to caller}} +} + +// NOTE: The self assignment of reference type is tested with stack-addr-ps.cpp. +// I.e., `int& i = i;` in function f5 `````````` </details> https://github.com/llvm/llvm-project/pull/187530 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
