<div dir="ltr">Ok, thanks for the clarification. <br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jul 23, 2019 at 5:17 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="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 23 Jul 2019, 05:37 Gábor Márton via cfe-dev, <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</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"><div>Hi,</div><div><br></div><div>During the improvement of clang::ASTImporter we discovered something strange with redecl chains. </div><div><br></div><div>Consider the following code:</div> 1 template <class T1, class T2><br> 2 struct Base {<br> 3 template <class U1, class U2><br> 4 friend struct Class;<br> 5 };<br> 6 template <class T1, class T2><br> 7 struct Class { }; <div>Here we'd expect that the prototype of `Class` at line 4 is linked to the same redecl chain as the definition at line 7 (see the test case below to be more precise, the test passes on llvm/master).</div><div>I wonder if this is an error in clang::Sema? If this is not an error then what is the explanation?</div></div></blockquote></div></div><div dir="auto"><br></div><div dir="auto">It's intentional. The friend in the template does not constitute a declaration of ::Class until the template Base is instantiated. For example, the template parameters of the friend are at different depths than those of the class.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><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"><div>Thanks,</div><div>Gabor</div><div><br></div><div><br></div>TEST_P(ASTImporterOptionSpecificTestBase,<br> ImportExistingFriendClassTemplateDef) {<br> auto Code =<br> R"(<br> template <class T1, class T2><br> struct Base {<br> template <class U1, class U2><br> friend struct Class;<br> };<br> template <class T1, class T2><br> struct Class { };<br> )";<br><br> TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);<br> TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");<br><br> auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(<br> ToTU, classTemplateDecl(hasName("Class")));<br> auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(<br> ToTU, classTemplateDecl(hasName("Class")));<br> ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());<br> ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());<br> // Previous friend decl is not linked to it!<br> ASSERT_FALSE(ToClassDef->getPreviousDecl());<br> ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);<br> ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);<br>}<br></div>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" rel="noreferrer" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div></div>
</blockquote></div>