[PATCH] D76287: [analysis][analyzer] Introduce the skeleton of a reaching definitions calculator

Whisperity via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 17 10:44:19 PDT 2020


whisperity added inline comments.


================
Comment at: clang/include/clang/Analysis/Analyses/ReachingDefinitions.h:79
+
+struct VarAndCFGElementLess {
+  bool operator()(Definition Lhs, Definition Rhs) const {
----------------
Shouldn't this be called `DefinitionLess` if this is the "natural" comparator for `Definition`? Also, is this the convention in LLVM, instead of providing an explicit specialisation for `std::less`?


================
Comment at: clang/include/clang/Analysis/Analyses/ReachingDefinitions.h:131
+
+  // Fields that shouldn't change after the construction of the builder object.
+
----------------
I do not feel this is visually separative enough, the fact that there is a free-floating comment (seemingly bogusly not attached to any declaration) breaks reading of the code.

How about this:


```
class X {
  // Fields that should not change after construction
  private:
    Foo bar;
    Bla blah;

  // Fields that change at every step
  private:
     Blah bla;

  public:
    Yadda blebba;
};
```


================
Comment at: clang/include/clang/Analysis/Analyses/ReachingDefinitions.h:140
+  const Decl *D;
+  ASTContext *Context = nullptr;
+
----------------
You do not seem to be using this variable but in one place. Are you sure it is worth the saving as a field? Also, is it valid in the first place to have `this->Context` not to be the same as `this->D->getASTContext()`?


================
Comment at: clang/include/clang/Analysis/Analyses/ReachingDefinitions.h:176-179
+  //===--------------------------------------------------------------------===//
+  // Utility methods for building a GEN set. These are public because the
+  // callback objects will need to call them.
+  //===--------------------------------------------------------------------===//
----------------
Is this the right approach? A public method makes the user itch to call it. If `GenSetMatcherCallback` is a superclass of every possible implementation, I think adding that class as a friend here works, and you could make the methods private, or protected.


================
Comment at: clang/include/clang/Analysis/Analyses/ReachingDefinitions.h:236-242
+  // TODO: Should we change to ImmutableMap? Does this matter that much?
+  std::map<const CFGBlock *, GenSet> Gen;
+  std::map<const CFGBlock *, DefinitionSet> Kill;
+
+public:
+  std::map<const CFGBlock *, DefinitionSet> In;
+  std::map<const CFGBlock *, DefinitionSet> Out;
----------------
The immutability might not(?), but the performance aspects of the RBT behind STL `map` could? `K` is a pointer, why not use `DenseMap`? How large do you expect these containers to be when they peak out?


================
Comment at: clang/lib/Analysis/ReachingDefinitions.cpp:96
+  static internal::Matcher<Stmt> getMatcher() {
+    return binaryOperator(isAssignmentOperator()).bind("assign");
+  }
----------------
I know this is the first patch, but it might be worth mentioning here that this thing does not match user-defined operators.


================
Comment at: clang/lib/Analysis/ReachingDefinitions.cpp:162
+
+  // TODO: Destructor calls? Should we be THAT conservative?
+  // TODO: Regular function calls?
----------------
You mean //explicit// destructor calls here, right?


================
Comment at: clang/lib/Analysis/ReachingDefinitions.cpp:275
+void ReachingDefinitionsCalculator::dumpGenSet() const {
+  llvm::errs() << "GEN sets: blockid (varname [blockid, elementid])\n";
+  for (const std::pair<const CFGBlock *, GenSet> D : Gen) {
----------------
Instead of simply blockID, could you harmonise this output with the CFG dump and say `Bx` instead of just `X`?


================
Comment at: clang/test/Analysis/dump-definitions.cpp:17-18
+
+// CHECK:      GEN sets: blockid (varname [blockid, elementid])
+// CHECK-NEXT: 1 (ptr, [1, 3]) <write>
+// CHECK-NEXT: KILL sets: blockid (varname [blockid, elementid])
----------------
What is an //element//? How do they get their numbers? What does the `3` mean here? I get that basic block 1 (the body of the function) writes `ptr`... but I don't understand this further from looking at the expected output.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76287





More information about the cfe-commits mailing list