[clang] [Clang][Sema] Fix malformed AST for anonymous class access in template. (PR #90842)

via cfe-commits cfe-commits at lists.llvm.org
Tue May 7 01:16:17 PDT 2024


martinboehme wrote:

> Another possibility to consider: when [transforming a member access](https://github.com/llvm/llvm-project/blob/ff210b94d449de8ebe1f32cf0d7763ba63b27b39/clang/lib/Sema/TreeTransform.h#L11950), strip off any implicit member accesses from the base expression before transforming the base. That way, we'll rebuild the implicit member access from scratch, which might be a little more work, but should get details like this one right. (We can then probably also remove the logic to deal with an absent `DeclName` in `RebuildMemberExpr` since that shouldn't happen any more.)

This sounds enticing, but after experimenting with this a bit, I’ve concluded that it’s unfortunately not so simple to get this working (unless there’s something I’m overlooking).

Looking at the relevant part of the AST:

```cxx
    `-MemberExpr <col:10, col:14> 'int' xvalue .i 0xbdcb3c0
      `-MemberExpr <col:10, col:14> 'S::(anonymous struct at line:2:3)' xvalue .S::(anonymous struct at line:2:3) 0xbdcb488
        `-MaterializeTemporaryExpr <col:10, col:12> 'S' xvalue
          `-CXXTemporaryObjectExpr <col:10, col:12> 'S' 'void () noexcept' zeroing
```

What I think you’re suggesting is that while processing the base for the outer `MemberExpr` (the one for `.i`), we strip the inner `MemberExpr` (the one for the anonymous field). The idea would be that the `MemberExpr` for the anonymous field should get recreated within `Sema::BuildMemberReferenceExpr()` when it’s called with the field declaration for `i`.

This _would_ work if we handed an `IndirectFieldDecl` to `BuildMemberReferenceExpr()`, but the problem is that we have no easy way of getting to the `IndirectFieldDecl`. The `getMemberDecl()` for the outer `MemberExpr` is a plain `FieldDecl`; the `getFoundDecl()` is, too.

The `getFoundDecl()` for the _inner_ `MemberExpr` does refer to the `IndirectFieldDecl` we want. So we could try to retain only this `MemberExpr` and strip the others – but then we run into the issue that there may not even _be_ an inner `MemberExpr` if the anonymous union is declared inside a function rather than inside a class ([example](https://godbolt.org/z/s1qqj5rY3)).

My feeling is that rather than trying to deal with all of the various cases involved in stripping, then recreating the implicit `MemberExpr`s, we retain them and merely recreate the `MaterializeTemporaryExpr` if needed.

https://github.com/llvm/llvm-project/pull/90842


More information about the cfe-commits mailing list