[PATCH] D159284: [clang][dataflow] Fix Record initialization with InitListExpr and inheritances

Martin Böhme via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 6 01:02:04 PDT 2023


mboehme accepted this revision.
mboehme added inline comments.
This revision is now accepted and ready to land.


================
Comment at: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp:2498
+TEST(TransferTest, ReturnStructWithInheritance) {
+  // This is a crash repro. (Returning a struct involves copy/move constructor)
+  std::string Code = R"(
----------------
kinu wrote:
> mboehme wrote:
> > kinu wrote:
> > > mboehme wrote:
> > > > I don't think this is true -- the `return S1` in `target()` will use NRVO.
> > > > 
> > > > But I also don't think it's relevant -- I believe the crash this is reproducing was triggered by the `InitListExpr`, not the return statement?
> > > > 
> > > > Given the other tests added in this patch, do we need this test?
> > > It will use NRVO but in AST this still seems to generate CXXConstructExpr with isCopyOrMoveConstructor() == true because omitting the ctor is not mandatory in compilers.
> > > 
> > > I can drop this one, but I'm also a bit torn because this was the original crash repro that puzzled me a bit.
> > > 
> > > I refined the comment to explain it a bit better; how does it look now?
> > > It will use NRVO but in AST this still seems to generate CXXConstructExpr with isCopyOrMoveConstructor() == true
> > 
> > Ah, true, I see this now:
> > 
> > https://godbolt.org/z/z9enG8cW7
> > 
> > > because omitting the ctor is not mandatory in compilers.
> > 
> > TIL that NRVO [isn't guaranteed](https://en.cppreference.com/w/cpp/language/copy_elision). (I always thought it was!)
> > 
> > I'm still pretty sure though that the `CXXConstructExpr` will have `isElidable() == true`, and in this case we [don't call `copyRecord()`](https://github.com/llvm/llvm-project/blob/6c6a2d3445671ada6a58b9ab5ce4a1e11e3dd610/clang/lib/Analysis/FlowSensitive/Transfer.cpp#L474):
> > 
> > ```
> >       if (S->isElidable()) {
> >         if (Value *Val = Env.getValue(*ArgLoc))
> >           Env.setValue(*S, *Val);
> >       } else {
> >         auto &Val = *cast<RecordValue>(Env.createValue(S->getType()));
> >         Env.setValue(*S, Val);
> >         copyRecord(*ArgLoc, Val.getLoc(), Env);
> >       }
> > ```
> > 
> > So I'm not sure that this repro actually triggers the crash? (Can you verify? If it does trigger the crash, where am I going wrong in my thinking above?)
> > 
> > > I can drop this one, but I'm also a bit torn because this was the original crash repro that puzzled me a bit.
> > 
> > OK, good to know that this is the original scenario that triggered the crash.
> > 
> > I still think it would be OK to keep only AssignmentOperatorWithInitAndInheritance because it also triggers a call to `copyRecord()` but does so in a more obvious fashion. And I think for a test it's actually useful if it's obvious what is happening.
> 
> > I'm still pretty sure though that the `CXXConstructExpr` will have `isElidable() == true`, and in this case we [don't call `copyRecord()`](https://github.com/llvm/llvm-project/blob/6c6a2d3445671ada6a58b9ab5ce4a1e11e3dd610/clang/lib/Analysis/FlowSensitive/Transfer.cpp#L474):
> 
> Interesting, so I looked into it:
> 
> Looks like after C++17 isElidable is no longer used in AST:
> https://github.com/llvm/llvm-project/blob/2a603deec49cb6a27f3a29480ed8a133eef31cee/clang/include/clang/ASTMatchers/ASTMatchers.h#L8351
> 
> (So this test code doesn't take the branch)
> 
> NRVO seems to be handled around ReturnStmt, not in each Expr:
> https://github.com/llvm/llvm-project/blob/2a603deec49cb6a27f3a29480ed8a133eef31cee/clang/lib/AST/Stmt.cpp#L1202
> 
> > [...] because it also triggers a call to `copyRecord()` but does so in a more obvious fashion. And I think for a test it's actually useful if it's obvious what is happening.
> 
> Makes sense, now I dropped this.
> 
> > I'm still pretty sure though that the `CXXConstructExpr` will have `isElidable() == true`, and in this case we [don't call `copyRecord()`](https://github.com/llvm/llvm-project/blob/6c6a2d3445671ada6a58b9ab5ce4a1e11e3dd610/clang/lib/Analysis/FlowSensitive/Transfer.cpp#L474):
> 
> Interesting, so I looked into it:
> 
> Looks like after C++17 isElidable is no longer used in AST:
> https://github.com/llvm/llvm-project/blob/2a603deec49cb6a27f3a29480ed8a133eef31cee/clang/include/clang/ASTMatchers/ASTMatchers.h#L8351
> 
> (So this test code doesn't take the branch)

Interesting -- wasn't aware!

> NRVO seems to be handled around ReturnStmt, not in each Expr:
> https://github.com/llvm/llvm-project/blob/2a603deec49cb6a27f3a29480ed8a133eef31cee/clang/lib/AST/Stmt.cpp#L1202

Thanks for the pointer, makes sese!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D159284



More information about the cfe-commits mailing list