[PATCH] D116596: [clang][dataflow] Add transfer functions for assignment

Yitzhak Mandelbaum via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 5 05:59:57 PST 2022


ymandel added inline comments.


================
Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:36
+/// FIXME: Consider replacing this with a model that is more aligned with C++
+/// value categories.
+enum class SkipPast {
----------------
I'm not sure that value categories are right here.  The key is that skipping is optional, unlike value categories which are fixed.  I think the problem is just that C++ references are weird (for lack of a technical term). A reference variable exists simultaneously in two different categories -- a pointer and the value it points to. That's what this is trying to capture.

So, I'd recommend just changing the name to reflect that. WDYT of something like this?

```
/// Indicates how to treat references, if encountered -- as a reference or the value referred to -- when retrieving
/// storage locations or values.
enum class RefTreatment {
   /// Consider the reference itself.
  AsSelf,
  /// Consider the referent.
  AsReferent,
};
```


================
Comment at: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h:111
+  /// value in the environment.
+  Value *getValue(const StorageLocation &Loc, SkipPast SP) const;
+
----------------
Why have a SkipPast argument here? I understand the concept for considering var-decls - it corresponds to the weirdness of lvalue-refs themselves. But StorageLocation is a lower-level (and simpler) concept, to which this doesn't seem to map. I'm fine with resolving indirections, but what is the value of only doing so conditionally?


================
Comment at: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp:242-247
+    if (auto *Val =
+            dyn_cast_or_null<ReferenceValue>(getValue(Loc, SkipPast::None))) {
+      return Val->getPointeeLoc();
+    } else {
+      return Loc;
+    }
----------------



================
Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:37
+      assert(S->getLHS() != nullptr);
+      const Expr *LHS = S->getLHS()->IgnoreParens();
+      assert(LHS != nullptr);
----------------
maybe comment as to why this is necessary? I'd have thought that CFG's flattening of expressions would handle this (why, in general, we don't need to look deep into expressions).


================
Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:135
+
+    if (const Expr *InitExpr = D.getInit()) {
+      if (D.getType()->isReferenceType()) {
----------------
nit: might be easier to read if you invert this:
```
const Expr *InitExpr = D.getInit();
if (InitExpr == nullptr) return;
```


================
Comment at: clang/lib/Analysis/FlowSensitive/Transfer.cpp:144-145
+        }
+      } else {
+        if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
+          Env.setValue(Loc, *InitExprVal);
----------------
nit: else-if (one line)?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116596/new/

https://reviews.llvm.org/D116596



More information about the cfe-commits mailing list