<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">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;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:0 0 0 .8ex;border-left:1px #ccc solid;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" target="_blank" rel="noreferrer">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>