donat.nagy added a comment.

This checker is a straightforward, clean implementation of the SEI-CERT rule 
EXP51-CPP, it'll be a good addition to Static Analyzer. I'm satisfied with the 
implementation, although there might be others who have a more refined taste in 
C++ coding style. The only issue that I found is the misleading name of the 
"common ancestor" hidden checker that I mentioned in the inline comment.

The test suite nicely covers all the basic situations, but I'd be happy to see 
some corner cases like virtual and non-virtual diamond inheritance or even a 
degenerate example like

  class Base { /*...*/ };
  class Derived: public Base {
    Base basesAsMember[10];
    /*...*/
  };
  void f() {
    Derived *d = new Derived(...);
    delete[] (d->basesAsMember);
  }



================
Comment at: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td:757-760
+def CXXArrayModeling: Checker<"CXXArrayModeling">,
+  HelpText<"The base of a few CXX array related checkers.">,
+  Documentation<NotDocumented>,
+  Hidden;
----------------
The name and help text of this hidden dependency is very misleading: it's not 
particularly connected to arrays (the connection between the two child checkers 
is that they both handle the "delete" operator) and it's not a modeling checker 
(which would provide function evaluation, constraints and transitions) but an 
"empty shell" checker that does nothing by itself, but provides a singleton 
checker object where the registration of the child checkers can enable the two 
analysis modes.

Please rename this to `CXXDeleteHelper` or something similar.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp:88
+  const auto *BaseClassRegion = MR->getAs<TypedValueRegion>();
+  const auto *DerivedClassRegion = 
MR->getBaseRegion()->getAs<SymbolicRegion>();
+  if (!BaseClassRegion || !DerivedClassRegion)
----------------
This logic (which is inherited from the earlier checker) is a bit surprising 
because it strips //all// Element, Field, BaseObject and DerivedObject layers 
from the MemRegion object.

I think it works in practice because
(1) there is an `isDerivedFrom() check after it and
(2) it's rare to write (buggy) code like
```lang=c++
struct Inner { /*...*/ };
struct Outer { Inner inner; /*...*/ };
void f() {
  Outer *o = new Outer(...);
  delete(o->inner);
}
```

Perhaps this could be explained by a comment if you feel that it's warranted; 
but I mostly wrote this as a note for myself and other reviewers. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158156

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to