jcsxky created this revision. jcsxky added reviewers: a.sidorin, shafik, balazske, steakhal, aaron.ballman, Michael137. jcsxky added projects: clang, clang-c. Herald added a project: All. jcsxky requested review of this revision. Herald added a subscriber: cfe-commits.
Don't increase template parameter's depth when it's a friend declaration in template class. The reason is that this member(template class) should match the previous class definition and when import from external ast file, type of them should be equivalence. See import issue <https://reviews.llvm.org/D156693> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D157170 Files: clang/lib/Parse/ParseTemplate.cpp clang/unittests/AST/ASTImporterTest.cpp Index: clang/unittests/AST/ASTImporterTest.cpp =================================================================== --- clang/unittests/AST/ASTImporterTest.cpp +++ clang/unittests/AST/ASTImporterTest.cpp @@ -4212,6 +4212,56 @@ EXPECT_TRUE(Imported->getPreviousDecl()); } +TEST_P(ImportFriendClasses, SkipFriendTemplateDeclaration) { + Decl *ToTU = getToTuDecl( + R"( + template <class T, T U> + class A; + + template <class T, T U> + class A { + public: + template <class P, P Q> + friend class A; + + A(T x):x(x) {} + + private: + T x; + }; + )", + Lang_CXX11); + + auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match( + ToTU, classTemplateDecl(hasName("A"))); + Decl *FromTU = getTuDecl( + R"( + template <class T, T U> + class A; + + template <class T, T U> + class A { + public: + template <class P, P Q> + friend class A; + + A(T x):x(x) {} + + private: + T x; + }; + + A<int, 3> a1(0); + )", + Lang_CXX11, "input1.cc"); + auto *FromA = FirstDeclMatcher<ClassTemplateDecl>().match( + FromTU, classTemplateDecl(hasName("A"))); + auto *ToA = Import(FromA, Lang_CXX11); + EXPECT_TRUE(ToA); + EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(), + ToA->getTemplatedDecl()->getTypeForDecl()); +} + TEST_P(ImportFriendClasses, ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) { Decl *ToTU = getToTuDecl( Index: clang/lib/Parse/ParseTemplate.cpp =================================================================== --- clang/lib/Parse/ParseTemplate.cpp +++ clang/lib/Parse/ParseTemplate.cpp @@ -127,8 +127,30 @@ // Parse the '<' template-parameter-list '>' SourceLocation LAngleLoc, RAngleLoc; SmallVector<NamedDecl*, 4> TemplateParams; + + bool SeeFriendKeyWord = false; + { + SmallVector<NamedDecl *, 4> TemplateParams; + SourceLocation LAngleLoc, RAngleLoc; + RevertingTentativeParsingAction TPA(*this); + MultiParseScope TemplateParamScopesTmp(*this); + if (ParseTemplateParameters(TemplateParamScopesTmp, + CurTemplateDepthTracker.getDepth(), + TemplateParams, LAngleLoc, RAngleLoc)) { + // returns true don't need process + // returns false, blowe 'ParseTemplateParameters' will do it after + // revert + } + // skip outmost declaration + if (Tok.is(tok::kw_friend) && CurTemplateDepthTracker.getDepth() > 0) { + SeeFriendKeyWord = true; + } + } + if (ParseTemplateParameters(TemplateParamScopes, - CurTemplateDepthTracker.getDepth(), + SeeFriendKeyWord + ? CurTemplateDepthTracker.getDepth() - 1 + : CurTemplateDepthTracker.getDepth(), TemplateParams, LAngleLoc, RAngleLoc)) { // Skip until the semi-colon or a '}'. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
Index: clang/unittests/AST/ASTImporterTest.cpp =================================================================== --- clang/unittests/AST/ASTImporterTest.cpp +++ clang/unittests/AST/ASTImporterTest.cpp @@ -4212,6 +4212,56 @@ EXPECT_TRUE(Imported->getPreviousDecl()); } +TEST_P(ImportFriendClasses, SkipFriendTemplateDeclaration) { + Decl *ToTU = getToTuDecl( + R"( + template <class T, T U> + class A; + + template <class T, T U> + class A { + public: + template <class P, P Q> + friend class A; + + A(T x):x(x) {} + + private: + T x; + }; + )", + Lang_CXX11); + + auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match( + ToTU, classTemplateDecl(hasName("A"))); + Decl *FromTU = getTuDecl( + R"( + template <class T, T U> + class A; + + template <class T, T U> + class A { + public: + template <class P, P Q> + friend class A; + + A(T x):x(x) {} + + private: + T x; + }; + + A<int, 3> a1(0); + )", + Lang_CXX11, "input1.cc"); + auto *FromA = FirstDeclMatcher<ClassTemplateDecl>().match( + FromTU, classTemplateDecl(hasName("A"))); + auto *ToA = Import(FromA, Lang_CXX11); + EXPECT_TRUE(ToA); + EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(), + ToA->getTemplatedDecl()->getTypeForDecl()); +} + TEST_P(ImportFriendClasses, ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) { Decl *ToTU = getToTuDecl( Index: clang/lib/Parse/ParseTemplate.cpp =================================================================== --- clang/lib/Parse/ParseTemplate.cpp +++ clang/lib/Parse/ParseTemplate.cpp @@ -127,8 +127,30 @@ // Parse the '<' template-parameter-list '>' SourceLocation LAngleLoc, RAngleLoc; SmallVector<NamedDecl*, 4> TemplateParams; + + bool SeeFriendKeyWord = false; + { + SmallVector<NamedDecl *, 4> TemplateParams; + SourceLocation LAngleLoc, RAngleLoc; + RevertingTentativeParsingAction TPA(*this); + MultiParseScope TemplateParamScopesTmp(*this); + if (ParseTemplateParameters(TemplateParamScopesTmp, + CurTemplateDepthTracker.getDepth(), + TemplateParams, LAngleLoc, RAngleLoc)) { + // returns true don't need process + // returns false, blowe 'ParseTemplateParameters' will do it after + // revert + } + // skip outmost declaration + if (Tok.is(tok::kw_friend) && CurTemplateDepthTracker.getDepth() > 0) { + SeeFriendKeyWord = true; + } + } + if (ParseTemplateParameters(TemplateParamScopes, - CurTemplateDepthTracker.getDepth(), + SeeFriendKeyWord + ? CurTemplateDepthTracker.getDepth() - 1 + : CurTemplateDepthTracker.getDepth(), TemplateParams, LAngleLoc, RAngleLoc)) { // Skip until the semi-colon or a '}'. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits