[PATCH] D52008: [analyzer] Handle forwarding reference better in ExprMutationAnalyzer.

Shuai Wang via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 13 21:55:33 PDT 2018


shuaiwang added a comment.

In https://reviews.llvm.org/D52008#1232923, @lebedev.ri wrote:

> Thanks for working on this! I tried, and it appears to not fix the issue at hand.
>
> - ``` struct C1 { C1(const C1* c, int num); };
>
>   int x = 0; auto y = std::make_unique<C1>(nullptr, x); // <- still considered a mutation? ``` * ``` struct C3 {}; // some class
>
>   struct C2 { C2(const int* whatever, int n, C3 zz); };
>
>   int x = 0; std::vector<C2> v; v.emplace_back(nullptr, x, {}); // <- still considered a mutation? ```
>
>   And so on. These are hand-reduced, so hopefully you can reproduce?


I've patched https://reviews.llvm.org/D51870 and tried these cases, they work correctly with this change plus the change making `std::move` & `std::forward` considered casts. I also tested

  struct D {
    D(int&);
  };
  void h() {
    std::vector<D> v;
    for (int i = 0; i < 10; ++i) {
      v.emplace_back(i);
    }
  }

and that's also correctly considered as mutation at `emplace_back`



================
Comment at: include/clang/Analysis/Analyses/ExprMutationAnalyzer.h:60
+public:
+  FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context);
+
----------------
JonasToth wrote:
> shuaiwang wrote:
> > JonasToth wrote:
> > > Why do we need a separate class for this?
> > > I think you can just create another object of `ExprMutAnalyzer` and do the analysis with `findDeclMutation(FunctioParm)`.
> > > 
> > > The `Stmt` is the `functionDecl().getBody()`. Right now it could be that you pass in an functionDecl without body.
> > > 
> > > Could there something happen with extern templates that the body is not accessible?
> > It's mostly for the special handling of constructors in which case initializer list also could mutate param.
> Hmm, still why not within `ExprMutAnalyzer`?
> You could make it a class living within ExprMutAnalyzer in the private section. Then its clear its an implementation detail.
Oh actually I'm planning to use this also in UnnecessaryValueParamCheck


================
Comment at: lib/Analysis/ExprMutationAnalyzer.cpp:201
       equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType())));
+  const auto NotInstantiated = unless(hasDeclaration(isInstantiated()));
   const auto AsNonConstRefArg = anyOf(
----------------
JonasToth wrote:
> I think this will not all cases correctly.
> 
> Say
> ```
> template <typename T>
> struct Foo {
>   static void bar() { SomethingWith(T()); }
> };
> ```
> 
> `bar` it self is not a template and `NotInstantiated` will be `false` (only 90% sure on that) as the declaration of `bar` does not match.
> In another check I had to do this: `unless(has(expr(anyOf(isTypeDependent(), isValueDependent()))))` to ensure that there are no unresolved constructs in the stmt.
I think it's fine here since we only care about skipping those with forwarding references.


================
Comment at: lib/Analysis/ExprMutationAnalyzer.cpp:367
+    // function body, check them eagerly here since they're typically trivial.
+    for (const CXXCtorInitializer *Init : Ctor->inits()) {
+      ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context);
----------------
JonasToth wrote:
> Just to be sure, this will recurse ?
> 
> ```
> struct Foo {
>   std::string s;
>   Foo(std::string s) : s (std::move(s)) {}
> };
> ```
> 
> `std::move` will be resolved through the new mechanism right?
This diff along won't handle `std::move` "properly" yet.
We'll look into definition of `std::move`, it'll be something like
```
return static_cast<remove_reference<T>::type&&>(t);
```
and we'll simply conclude `t` is mutated: because it's being returned.

So for you case, we'll see `s` is mutated by `std::move(s)` and stop there, when we treat `std::move` as cast, we'll go one step further and found `std::move(s)` is passed as non-const argument to constructor of std::string, and we'll stop there concluding `s` is mutated.


Repository:
  rC Clang

https://reviews.llvm.org/D52008





More information about the cfe-commits mailing list