<div dir="ltr">Richard, Aaron, thanks for your input!<div>I've came up with a quick (draft) patch to solve the issue. I might not cover all cases, and perhaps the change should have a better place in another function, please take a look if you have some time.</div><div>Besides, I ended up using the test infrastructure of the ASTImporter. We could do a refactor to make that infra usable in other AST related tests, if you find that direction okay.</div><div><a href="https://reviews.llvm.org/D92101">https://reviews.llvm.org/D92101</a><br></div><div><br></div><div>Gabor</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 24, 2020 at 7:43 PM Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">This looks like a bug. We intentionally clone typedef declarations into deduction guide declarations in some cases:<div><br></div><div>template<typename T> struct A {</div><div> typedef T U;</div><div> A(U);</div><div>};</div><div><br></div><div>... should generate a deduction guide</div><div><br></div><div>template<typename T> [typedef T U;]</div><div>A(U) -> A<T>;</div><div><br></div><div>that has a local clone of the typedef declaration. That's important because we want the typedef declaration to be part of the current instantiation when deducing / instantiating with the deduction guide, in order to allow us to properly "look through" U to T. (We tried other approaches here and this is the one that worked best.)</div><div><br></div><div>But this should only be happening for typedefs that are declared within the enclosing class template.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 20 Nov 2020 at 08:49, Aaron Ballman <<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Fri, Nov 20, 2020 at 11:30 AM Gábor Márton <<a href="mailto:martongabesz@gmail.com" target="_blank">martongabesz@gmail.com</a>> wrote:<br>
><br>
> Hi,<br>
><br>
> Considering the below code:<br>
> 01<br>
> 02 struct A {};<br>
> 03 typedef A AT;<br>
> 04<br>
> 05 template <typename T> struct ClassT {<br>
> 06 ClassT(AT p0, T* p1) {}<br>
> 07 };<br>
> 08<br>
> 09 A a;<br>
> 10 int x;<br>
> 11 auto y = ClassT(a, &x);<br>
><br>
> The deduction guide's first parameter refers to a TypedefDecl that is isolated<br>
> from the first TypedefDecl. First declaration:<br>
><br>
> |-TypedefDecl 0x5555561eaec0 <line:3:3, col:13> col:13 referenced AT 'A'<br>
> | `-RecordType 0x5555561ead80 'A'<br>
> | `-CXXRecord 0x5555561eacf0 'A'<br>
><br>
> Vs the function prototype of the deduction guide refers to an isolated<br>
> (out-of-the-redecl-chain) TypedefDecl:<br>
><br>
> FunctionProtoType 0x55555621bc80 'auto (AT, T *) -> ClassT<T>' dependent trailing_return cdecl<br>
> |-InjectedClassNameType 0x5555561eb220 'ClassT<T>' dependent<br>
> | `-CXXRecord 0x5555561eafe0 'ClassT'<br>
> |-TypedefType 0x55555621bb20 'AT' sugar<br>
> | |-Typedef 0x55555621bac0 'AT'<br>
> | `-RecordType 0x5555561ead80 'struct A'<br>
> | `-CXXRecord 0x5555561eacf0 'A'<br>
> `-PointerType 0x5555561eb410 'T *' dependent<br>
> `-TemplateTypeParmType 0x5555561eafa0 'T' dependent depth 0 index 0<br>
> `-TemplateTypeParm 0x5555561eaf18 'T'<br>
><br>
> So, in the translation unit, we have two distinct TypedefDecl AST nodes. The<br>
> first one's DeclContext is the TranslationUnidDecl, however, the second's is<br>
> the CXXDeductionGuideDecl.<br>
><br>
> This is strange, because when dealing with regular function template<br>
> instantiations, the two typedefs are the same and we have only one universal<br>
> TypedefDecl node in the AST.<br>
> 01<br>
> 02 struct A {};<br>
> 03 typedef A AT;<br>
> 04<br>
> 05 template <typename T><br>
> 06 int fun(AT p0, T* p1) {}<br>
> 07<br>
> 08 A a;<br>
> 09 int x;<br>
> 10 int y = fun(a, &x);<br>
><br>
> TypedefDecl 0x5555561eaf70 <input.cc:3:3, col:13> col:13 referenced AT 'A'<br>
> `-RecordType 0x5555561eae30 'A'<br>
> `-CXXRecord 0x5555561eada0 'A'<br>
><br>
> FunctionProtoType 0x5555561eb240 'int (AT, T *)' dependent cdecl<br>
> |-BuiltinType 0x5555561ab0a0 'int'<br>
> |-TypedefType 0x5555561eb090 'AT' sugar<br>
> | |-Typedef 0x5555561eaf70 'AT'<br>
> | `-RecordType 0x5555561eae30 'struct A'<br>
> | `-CXXRecord 0x5555561eada0 'A'<br>
> `-PointerType 0x5555561eb160 'T *' dependent<br>
> `-TemplateTypeParmType 0x5555561eb050 'T' dependent depth 0 index 0<br>
> `-TemplateTypeParm 0x5555561eafc8 'T'<br>
><br>
> I was wondering whether this discrepancy is deliberate. IMO, the deduction<br>
> guide should refer to the TypedefDecl in the TranslationUnidDecl and it should<br>
> not create a new TypedefDecl. Can someone confirm if this is a bug or not?<br>
<br>
I can't confirm that this behavior is a bug, but it certainly smells<br>
like one to me. We use pointer comparisons to establish declaration<br>
identity and that would fail with this (and this also gets used in<br>
things like the JSON AST dumper). That said, I'm not certain why the<br>
behavior is the way it is, so it's possible there's something deeper<br>
going on here (but I'd argue it's still likely a bug).<br>
<br>
~Aaron<br>
<br>
><br>
> Context: I am trying to fix an infinite loop in the ASTImporter that is related<br>
> to importing deduction guidelines.<br>
><br>
> Any insight would be really appreciated.<br>
><br>
> Thanks,<br>
> Gabor<br>
><br>
</blockquote></div>
</blockquote></div>