mizvekov marked 5 inline comments as done.
mizvekov added inline comments.

================
Comment at: clang/lib/AST/ASTContext.cpp:12218
+        CTN,
+        NExpX && NExpY ? Optional<unsigned>(std::min(*NExpX, *NExpY)) : None);
+  }
----------------
davrec wrote:
> I'm not clear on how `NExpX` could not equal `NExpY` - could you add a test 
> which demonstrates this case?
It may not be needed in this patch, and it might in fact be related to a bug 
which I already solved in the main resugaring patch. I will double check later.


================
Comment at: clang/lib/AST/ASTContext.cpp:12767
+        Ctx.getQualifiedType(Underlying),
+        ::getCommonDecl(EX->getOwnedTagDecl(), EY->getOwnedTagDecl()));
+  }
----------------
davrec wrote:
> mizvekov wrote:
> > davrec wrote:
> > > mizvekov wrote:
> > > > davrec wrote:
> > > > > This last argument should probably be omitted/nullptr passed, since
> > > > > # We probably won't encounter any owned tag decls in the types passed 
> > > > > to this function;
> > > > > # Even if we did, it would not necessarily be true that they both 
> > > > > have non-null owned tag decls, and I don't see any nullptr checks in 
> > > > > getCommonDecl; and
> > > > > # Even if we checked for nullptr there, and say passed the same 
> > > > > argument to X and Y so EX==EY, and that had an owned tag decl, it is 
> > > > > not clear to me it would be appropriate to construct a new type with 
> > > > > the same owned tag decl as another type.
> > > > 1. We can see, a one liner like this will do: `int e = true ? (struct 
> > > > S*)0 : (struct S*)0;`
> > > > 
> > > > Though normally in an example like the above, you would only see the 
> > > > owned decl on X, because when we get to Y the name has already been 
> > > > introduced into the scope.
> > > > 
> > > > I have an idea for a test case, but it's a bit convoluted:
> > > > 
> > > > This also introduces an OwnedTagDecl: `(struct S<T>*)0`.
> > > > 
> > > > So with resugaring, if we resugar T, it might be possible to construct 
> > > > this situatiation. Given if it's appropriate to keep the OwnedTagDecl 
> > > > when resugaring, of course, which goes to 3)
> > > > 
> > > > 2. This is handled by `declaresSameEntity`, if either or both decls are 
> > > > null, we say they are not the same decl.
> > > > 
> > > > 3. That I am not sure. I see that this OwnedTagDecl is only used by the 
> > > > type printer, and it replaces printing the rest of the type by printing 
> > > > the OwnedDecl instead. So why do you think it would not be appropriate 
> > > > that the rebuilt type keeps this?
> > > (Re #3) Because I think the sense ownership is respected in how 
> > > ownedTagDecls are presently handled: at most one ElaboratedType owns a 
> > > particular TagDecl, *and* that type does not seem to be reused elsewhere 
> > > in the AST.  (This is relied on in https://reviews.llvm.org/D131685, 
> > > which was on my mind when I looked at this.)
> > > 
> > > E.g. consider this expansion of your example:
> > > ```
> > > auto e = true ? (struct S*)0 : (true ? (struct S*)0 : (struct S*)0);
> > > ```
> > > The first ElaboratedType has an ownedTagDecl; the second is a distinct 
> > > ElaboratedType without an ownedTagDecl, and the third equals the second.  
> > > 
> > > Now in practice what this means is that `getCommonDecl` when used on 
> > > binary expressions of this sort will always be nullptr, so no harm done.  
> > > But suppose it is called with X=Y=some ET with an ownedTagDecl (which is 
> > > the only time I believe we could see a non null getCommonDecl result 
> > > here).  Should the type that is returned have that same owned tag decl?  
> > > I think that would violate the sense of the original type "owning" that 
> > > decl that seems to be respected elsewhere in the AST.
> > > 
> > > Re type printing, I believe that ownedTagDecls only affects printing of 
> > > defined TagDecls like `struct S { int i; } x;` (which is what I was 
> > > mostly thinking re ownedTagDecls - I don't think we will see those here); 
> > > for undefined ones like `struct S x;`, printing should be unaffected 
> > > whether there is an ownedTagDecl or not.
> > > 
> > With type deduction this can happen:
> > 
> > ```
> > auto x = (struct S*)0; // it will also appear in the type of x
> > using t = decltype(x); // and now also in t
> > ```
> > 
> > With your second example, it can also happen:
> > 
> > ```
> > struct S { int i; } x;
> > int e = true ? &x : (struct S*)0;
> > ```
> > 
> > In those cases, the type node that owns the decl will be the same object, 
> > but that is only because of uniquing.
> > 
> > It may be possible that two different objects end up in this situation, if 
> > for example they come from different modules that got merged.
> > With type deduction this can happen:
> > ```
> > auto x = (struct S*)0; // it will also appear in the type of x
> > using t = decltype(x); // and now also in t
> > ```
> 
> My local clang is out of date - the type of `x` for me is just an AutoType 
> wrapping a PointerType to a RecordType.  In light of the addition of the 
> ElaboratedType there, it seems fine to be consistent here with however that 
> case handles ownedTagDecls, but FWIW I do not think that deduced 
> ElaboratedType should have an ownedTagDecl either.  Only the original type 
> should be the owner - not any type deduced from it.
> 
> This is a minor issue with few if any observable effects for now, but should 
> be kept in mind if issues arise later: the fact the ownership of 
> ownedTagDecls is respected was the only factor that made 
> https://discourse.llvm.org/t/ast-parent-of-class-in-a-friend-declaration/64275
>  easily solvable.
> 
> > With your second example, it can also happen:
> > 
> > ```
> > struct S { int i; } x;
> > int e = true ? &x : (struct S*)0;
> > ```
> 
> The DeclRefExpr `x` indeed reuses the ElaboratedType used in the VarDecl `x`, 
> with its ownedTagDecl and all.  That seems fair, a special case.  For all 
> other type deductions I would mildly object to including an ownedTagDecl.
> 
I think that assumption might work on ElaboratedTypeLocs instead. I think only 
one per TU should appear in the AST.
Resugaring might make us rebuild such TypeLocs, but the non-resugared one 
should be unreachable from the AST.


================
Comment at: clang/lib/AST/ASTContext.cpp:12872
   }
 
   SplitQualType SX = X.split(), SY = Y.split();
----------------
davrec wrote:
> It would be very helpful to incorporate your description and the description 
> from D111283 as comments in this function.  E.g. something like the following 
> ...
Thanks! I also added some extras in there.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130308

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

Reply via email to