[clang] 61760bb - [analyzer] Bind return value for assigment and copies of trivial empty classes

Tomasz Kamiński via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 17 23:46:33 PDT 2023


Author: Tomasz Kamiński
Date: 2023-07-18T08:31:38+02:00
New Revision: 61760bb98c4694651261b2e10df3fa6f669098ed

URL: https://github.com/llvm/llvm-project/commit/61760bb98c4694651261b2e10df3fa6f669098ed
DIFF: https://github.com/llvm/llvm-project/commit/61760bb98c4694651261b2e10df3fa6f669098ed.diff

LOG: [analyzer] Bind return value for assigment and copies of trivial empty classes

We now properly bind return value of the trivial copy constructor
and assignments of the empty objects. Such operations do not
perform any loads from the source, however they preserve identity
of the assigned object:
```
Empty e;
auto& x = (e = Empty());
clang_analyzer_dump(x); // &e, was Unknown
```

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D155442

Added: 
    clang/test/Analysis/ctor-trivial-copy.cpp

Modified: 
    clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index d1894d4447a2e9..7ee7c1394a670a 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -61,30 +61,30 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
     AlwaysReturnsLValue = true;
   }
 
-  assert(ThisRD);
-  if (ThisRD->isEmpty()) {
-    // Do nothing for empty classes. Otherwise it'd retrieve an UnknownVal
-    // and bind it and RegionStore would think that the actual value
-    // in this region at this offset is unknown.
-    return;
-  }
-
   const LocationContext *LCtx = Pred->getLocationContext();
+  const Expr *CallExpr = Call.getOriginExpr();
 
   ExplodedNodeSet Dst;
   Bldr.takeNodes(Pred);
 
-  SVal V = Call.getArgSVal(0);
-
-  // If the value being copied is not unknown, load from its location to get
-  // an aggregate rvalue.
-  if (std::optional<Loc> L = V.getAs<Loc>())
-    V = Pred->getState()->getSVal(*L);
-  else
-    assert(V.isUnknownOrUndef());
+  assert(ThisRD);
+  if (!ThisRD->isEmpty()) {
+    // Load the source value only for non-empty classes.
+    // Otherwise it'd retrieve an UnknownVal
+    // and bind it and RegionStore would think that the actual value
+    // in this region at this offset is unknown.
+    SVal V = Call.getArgSVal(0);
 
-  const Expr *CallExpr = Call.getOriginExpr();
-  evalBind(Dst, CallExpr, Pred, ThisVal, V, true);
+    // If the value being copied is not unknown, load from its location to get
+    // an aggregate rvalue.
+    if (std::optional<Loc> L = V.getAs<Loc>())
+      V = Pred->getState()->getSVal(*L);
+    else
+      assert(V.isUnknownOrUndef());
+    evalBind(Dst, CallExpr, Pred, ThisVal, V, true);
+  } else {
+    Dst.Add(Pred);
+  }
 
   PostStmt PS(CallExpr, LCtx);
   for (ExplodedNode *N : Dst) {

diff  --git a/clang/test/Analysis/ctor-trivial-copy.cpp b/clang/test/Analysis/ctor-trivial-copy.cpp
new file mode 100644
index 00000000000000..5ed188aa8f1eae
--- /dev/null
+++ b/clang/test/Analysis/ctor-trivial-copy.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=constructors -verify %s
+
+
+template<typename T>
+void clang_analyzer_dump(T&);
+
+struct aggr {
+  int x;
+  int y;
+};
+
+struct empty {
+};
+
+void test_copy_return() {
+  aggr s1 = {1, 2};
+  aggr const& cr1 = aggr(s1);
+  clang_analyzer_dump(cr1); // expected-warning-re {{&lifetime_extended_object{aggr, cr1, S{{[0-9]+}}} }}
+
+  empty s2;
+  empty const& cr2 = empty{s2};
+  clang_analyzer_dump(cr2); // expected-warning-re {{&lifetime_extended_object{empty, cr2, S{{[0-9]+}}} }}
+}
+
+void test_assign_return() {
+  aggr s1 = {1, 2};
+  aggr d1;
+  clang_analyzer_dump(d1 = s1); // expected-warning {{&d1 }}
+
+  empty s2;
+  empty d2;
+  clang_analyzer_dump(d2 = s2); // expected-warning {{&d2 }} was Unknown
+}
+


        


More information about the cfe-commits mailing list