ayzhao added a comment.

In D129531#3880875 <https://reviews.llvm.org/D129531#3880875>, @ayzhao wrote:

> In D129531#3873872 <https://reviews.llvm.org/D129531#3873872>, @royjacobson 
> wrote:
>
>> Thanks for working on it! It looks really good. Please remember to update 
>> the feature test macro (__cpp_aggregate_paren_init).
>
> Done
>
>> Also, I think there's no test coverage for the ASTReader/Writer changes? I 
>> would like to see some as well.
>
> I added a precompiled header test. Currently, the ASTReader/Writer change is 
> broken with the following error:
>
> ...
>
> I'm currently looking into this - I suspect it has to do with 
> `CXXParenListInitExpr` storing all it's subexpressions in an 
> `llvm::TrailingObjects` base class, but I have yet to confirm one way or 
> another.

The PCH test is fixed now, so we now have coverage for the ASTReader/Writer 
changes.



================
Comment at: clang/lib/AST/Expr.cpp:3699
+    // FIXME: unimplemented
+    llvm_unreachable("unimplemented");
   }
----------------
shafik wrote:
> cor3ntin wrote:
> > You can probably just fall through, a list of expression only has side 
> > effects if the individual expressions do, which the code just below is 
> > doing.
> On Discourse, the suggestion was made to have use `InitListExpr` as a base 
> class and in that case I believe we should do the same that that we do for 
> `InitListExpr`.
See the response from @ilya-biryukov for why I decided against inheriting from 
`InitListExpr`.


================
Comment at: clang/lib/AST/ExprClassification.cpp:446
+
+  case Expr::CXXParenListInitExprClass:
+    // FIXME: unimplemented
----------------
shafik wrote:
> This looks like we should handle this similar to `InitListExpr` but I am not 
> sure if single element if it is bound to a reference can be an lvalue holds 
> as well here as well CC @erichkeane 
IMO; no. 

I believe the comment for `InitListExpr` refers to statements like:

```
int a;
int &b{a};
```

This doesn't apply to `CXXParenListInitExprClass` because the corresponding 
statement with parentheses wouldn't be parsed as a `CXXParenListInitExpr` in 
the first place.


================
Comment at: clang/lib/AST/StmtPrinter.cpp:2459
+void StmtPrinter::VisitCXXParenListInitExpr(CXXParenListInitExpr *Node) {
+  // FIXME: unimplemented
+  llvm_unreachable("unimplemented");
----------------
shafik wrote:
> Assuming we go w/ `InitListExpr` as a base class then you should do something 
> similar to ` StmtPrinter::VisitInitListExpr(...)`  except with parens.
See the response from @ilya-biryukov for why I decided against inheriting from 
`InitListExpr`.


================
Comment at: clang/lib/Sema/TreeTransform.h:13922
 
+template <typename Derived>
+ExprResult
----------------
This is an extra change, but `clang-format` would always make it.


================
Comment at: clang/lib/Serialization/ASTReaderStmt.cpp:2179
+  for (unsigned I = 0; I < E->NumExprs; I++)
+    E->getTrailingObjects<Expr *>()[I] = Record.readSubExpr();
+}
----------------
ilya-biryukov wrote:
> ayzhao wrote:
> > ilya-biryukov wrote:
> > > FYI: I think this is where the crash comes from.
> > > We should allocate the trailing objects first.
> > > E.g. see how `PragmaCommentDecl::CreateDeserialized` does this.
> > This sounds like it could be the solution - thanks for looking at it!
> > 
> > Currently, I'm working on the refactor that shafik@ suggested, which was to 
> > inherit from `InitListExpr`. Hopefully, that refactor will fix this issue 
> > as `InitListExpr` stores it's subexpressions in a class member instead of 
> > using `llvm::TrailingObjects`.
> Are we trying to share code between two implementations? If so, I suggest to 
> consider alternatives, e.g. creating a new base class and inheriting both 
> `InitListExpr` and `CXXParentInitListExpr` to share the common code.
> 
> Inheriting `CXXParentInitListExpr` from `InitListExpr` breaks [Liskov 
> substitution 
> principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle) and 
> will likely to lead to bugs that are hard to chase.  `InitListExpr` is widely 
> used and means`{}`. `CXXParenInitListExpr` is not `{}` and we do not know in 
> advance which code is going to work for both and which code is only valid for 
> `{}`. Reviewing all callsites that use `InitListExpr` does not seem 
> plausible. Note that in addition to Clang, there are also uses in 
> ast-matchers and in clang-tidy checks (quite a few of those are downstream).
So I figured out why this was failing. When I created the 
`CXXParenListInitExpr` object on the heap in 
`ASTReader::ReadStmtFromStream(...)` below, I just called `new` without 
allocating any space for the `TrailingObjects`. This is fixed now, and the PCH 
test passes.

> Inheriting CXXParentInitListExpr from InitListExpr breaks Liskov substitution 
> principle and will likely to lead to bugs that are hard to chase. 
> InitListExpr is widely used and means`{}. CXXParenInitListExpr` is not {} and 
> we do not know in advance which code is going to work for both and which code 
> is only valid for {}. Reviewing all callsites that use InitListExpr does not 
> seem plausible. Note that in addition to Clang, there are also uses in 
> ast-matchers and in clang-tidy checks (quite a few of those are downstream).

+1, I am convinced that inheriting from `InitListExpr` is the wrong thing to do 
here. Additionally, when I tried to inherit from `InitListExpr`, I found that 
there were a lot of things in that class that were specific to `InitListExpr` 
that I had to wrap with an `if` statement to make it work with 
`CXXParenListInitExpr`, and that the amount of code that I had to add 
considerably decreases readability.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129531

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

Reply via email to