Redecl chain of friend class template is broken ?

Hi,

During the improvement of clang::ASTImporter we discovered something strange with redecl chains.

Consider the following code:
1 template <class T1, class T2>
2 struct Base {
3 template <class U1, class U2>
4 friend struct Class;
5 };
6 template <class T1, class T2>
7 struct Class { };
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).
I wonder if this is an error in clang::Sema? If this is not an error then what is the explanation?

Thanks,
Gabor

TEST_P(ASTImporterOptionSpecificTestBase,
ImportExistingFriendClassTemplateDef) {
auto Code =
R"(
template <class T1, class T2>
struct Base {
template <class U1, class U2>
friend struct Class;
};
template <class T1, class T2>
struct Class { };
)";

TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, “input.cc”);

auto *ToClassProto = FirstDeclMatcher().match(
ToTU, classTemplateDecl(hasName(“Class”)));
auto *ToClassDef = LastDeclMatcher().match(
ToTU, classTemplateDecl(hasName(“Class”)));
ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
// Previous friend decl is not linked to it!
ASSERT_FALSE(ToClassDef->getPreviousDecl());
ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
}

Hi,

During the improvement of clang::ASTImporter we discovered something strange with redecl chains.

Consider the following code:
1 template <class T1, class T2>
2 struct Base {
3 template <class U1, class U2>
4 friend struct Class;
5 };
6 template <class T1, class T2>
7 struct Class { };
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).
I wonder if this is an error in clang::Sema? If this is not an error then what is the explanation?

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.

Ok, thanks for the clarification.