- Repeated friends of template class/function in template class are partially imported:
template <class T> class Container { template <class U> friend void m(); template <class U> friend void m(); };
Only one m can be imported,
FromTu:
ClassTemplateDecl 0x5590cff47ae0 <input.cc:2:9, line:6:9> line:3:15 Container |-TemplateTypeParmDecl 0x5590cff47990 <line:2:19, col:25> col:25 class depth 0 index 0 T `-CXXRecordDecl 0x5590cff47a50 <line:3:9, line:6:9> line:3:15 class Container definition |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveConstructor exists simple trivial needs_implicit | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveAssignment exists simple trivial needs_implicit | `-Destructor simple irrelevant trivial needs_implicit |-CXXRecordDecl 0x5590cff47d30 <col:9, col:15> col:15 implicit class Container |-FriendDecl 0x5590cff48048 <line:4:11, col:44> col:42 | `-FunctionTemplateDecl 0x5590cff47f80 parent 0x5590cfefeda8 <col:11, col:44> col:42 m | |-TemplateTypeParmDecl 0x5590cff47dc0 <col:21, col:27> col:27 class depth 1 index 0 U | `-FunctionDecl 0x5590cff47ec8 parent 0x5590cfefeda8 <col:30, col:44> col:42 m 'void ()' `-FriendDecl 0x5590cff48260 <line:5:11, col:44> col:42 `-FunctionTemplateDecl 0x5590cff481f8 parent 0x5590cfefeda8 <col:11, col:44> col:42 m |-TemplateTypeParmDecl 0x5590cff48088 <col:21, col:27> col:27 class depth 1 index 0 U `-FunctionDecl 0x5590cff48140 parent 0x5590cfefeda8 <col:30, col:44> col:42 m 'void ()'
ToTu:
ClassTemplateDecl 0x5590cffe3ad8 <input.cc:2:9, line:6:9> line:3:15 Container |-TemplateTypeParmDecl 0x5590cffe3950 <line:2:19, col:25> col:25 class depth 0 index 0 T `-CXXRecordDecl 0x5590cffe3a10 <line:3:9, line:6:9> line:3:15 class Container definition |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveConstructor exists simple trivial needs_implicit | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param | |-MoveAssignment exists simple trivial needs_implicit | `-Destructor simple irrelevant trivial needs_implicit |-FunctionTemplateDecl 0x5590cffe3ef8 parent 0x5590cff9b128 <line:4:11, col:44> col:42 m // extranous node | |-TemplateTypeParmDecl 0x5590cffe3d20 <col:21, col:27> col:27 class depth 1 index 0 U | `-FunctionDecl 0x5590cffe3e28 parent 0x5590cff9b128 <col:30, col:44> col:42 m 'void ()' |-FriendDecl 0x5590cffe3f60 <col:11, col:44> col:42 | `-FunctionTemplateDecl 0x5590cffe3ef8 parent 0x5590cff9b128 <col:11, col:44> col:42 m | |-TemplateTypeParmDecl 0x5590cffe3d20 <col:21, col:27> col:27 class depth 1 index 0 U | `-FunctionDecl 0x5590cffe3e28 parent 0x5590cff9b128 <col:30, col:44> col:42 m 'void ()' `-CXXRecordDecl 0x5590cffe3fa0 <line:3:9, col:15> col:15 implicit class Container
Also note that an extranous FunctionTemplateDecl 0x5590cffe3ef8 is added into this ClassTemplateDecl 0x5590cffe3ad8 lexical context, which
renders it NOT identical to the original DeclContext, even after the second friend is successfully imported, this extra node would crash clang-import-test.
Plan to fix it in another revision (D157691).
- Import single friend node m into existing context would crash with an assertion failure:
./build/tools/clang/unittests/AST/ASTTests --gtest_filter="*ImportFriendClasses.ImportOfRepeatedFriendFunctionTemplateDecl*" Note: Google Test filter = *ImportFriendClasses.ImportOfRepeatedFriendFunctionTemplateDecl* [==========] Running 4 tests from 1 test suite. [----------] Global test environment set-up. [----------] 4 tests from ParameterizedTests/ImportFriendClasses [ RUN ] ParameterizedTests/ImportFriendClasses.ImportOfRepeatedFriendFunctionTemplateDecl/0 ASTTests: /home/xxxxx/Sources/llvm-project-main/clang/lib/AST/ASTImporter.cpp:4139: clang::ExpectedDecl clang::ASTNodeImporter::VisitFriendDecl(clang::FriendDecl *): Assertion `ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount && "Class with non-matching friends is imported, ODR check wrong?"' failed. #0 0x00007f1f53bf812a llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/xxxxx/Sources/llvm-project-main/llvm/lib/Support/Unix/Signals.inc:602:11 #1 0x00007f1f53bf82db PrintStackTraceSignalHandler(void*) /home/xxxxx/Sources/llvm-project-main/llvm/lib/Support/Unix/Signals.inc:675:1 #2 0x00007f1f53bf6846 llvm::sys::RunSignalHandlers() /home/xxxxx/Sources/llvm-project-main/llvm/lib/Support/Signals.cpp:104:5 #3 0x00007f1f53bf8af5 SignalHandler(int) /home/xxxxx/Sources/llvm-project-main/llvm/lib/Support/Unix/Signals.inc:413:1 #4 0x00007f1f5365afd0 (/lib/x86_64-linux-gnu/libc.so.6+0x3bfd0) #5 0x00007f1f536a9d3c __pthread_kill_implementation ./nptl/./nptl/pthread_kill.c:44:76 #6 0x00007f1f5365af32 raise ./signal/../sysdeps/posix/raise.c:27:6 #7 0x00007f1f53645472 abort ./stdlib/./stdlib/abort.c:81:7 #8 0x00007f1f53645395 _nl_load_domain ./intl/./intl/loadmsgcat.c:1177:9 #9 0x00007f1f53653e32 (/lib/x86_64-linux-gnu/libc.so.6+0x34e32) #10 0x00007f1f555c7179 clang::ASTNodeImporter::VisitFriendDecl(clang::FriendDecl*) /home/xxxxx/Sources/llvm-project-main/clang/lib/AST/ASTImporter.cpp:4140:7 #11 0x00007f1f5561f564 clang::declvisitor::Base<std::add_pointer, clang::ASTNodeImporter, llvm::Expected<clang::Decl*> >::Visit(clang::Decl*) /home/xxxxx/Sources/llvm-project-main/build/tools/clang/include/clang/AST/DeclNodes.inc:71:1 #12 0x00007f1f555eaf3d clang::ASTImporter::ImportImpl(clang::Decl*) /home/xxxxx/Sources/llvm-project-main/clang/lib/AST/ASTImporter.cpp:8768:19 #13 0x00007f1f555ce605 clang::ASTImporter::Import(clang::Decl*) /home/xxxxx/Sources/llvm-project-main/clang/lib/AST/ASTImporter.cpp:9167:8 #14 0x0000562aa520bd4a clang::ast_matchers::ASTImporterTestBase::TU::import(std::shared_ptr<clang::ASTImporterSharedState> const&, clang::ASTUnit*, clang::Decl*) /home/xxxxx/Sources/llvm-project-main/clang/unittests/AST/ASTImporterFixtures.cpp:83:12 #15 0x0000562aa520c9c9 clang::ast_matchers::ASTImporterTestBase::Import(clang::Decl*, clang::TestLanguage) /home/xxxxx/Sources/llvm-project-main/clang/unittests/AST/ASTImporterFixtures.cpp:199:9 #16 0x0000562aa531f023 clang::FriendDecl* clang::ast_matchers::ASTImporterTestBase::Import<clang::FriendDecl>(clang::FriendDecl*, clang::TestLanguage) /home/xxxxx/Sources/llvm-project-main/clang/unittests/AST/ASTImporterFixtures.h:185:32 #17 0x0000562aa52af6a2 clang::ast_matchers::ImportFriendClasses::testRepeatedFriendImport(char const*) /home/xxxxx/Sources/llvm-project-main/clang/unittests/AST/ASTImporterTest.cpp:4068:37 #18 0x0000562aa5255524 clang::ast_matchers::ImportFriendClasses_ImportOfRepeatedFriendFunctionTemplateDecl_Test::TestBody() /home/xxxxx/Sources/llvm-project-main/clang/unittests/AST/ASTImporterTest.cpp:4388:1 #19 0x00007f1f56ddb76b void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:2433:3 #20 0x00007f1f56dc0e07 void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:2488:5 #21 0x00007f1f56da9963 testing::Test::Run() /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:2515:3 #22 0x00007f1f56daa1ba testing::TestInfo::Run() /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:2687:12 #23 0x00007f1f56daa71b testing::TestSuite::Run() /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:2815:44 #24 0x00007f1f56db2ef9 testing::internal::UnitTestImpl::RunAllTests() /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:5337:24 #25 0x00007f1f56ddea3b bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:2433:3 #26 0x00007f1f56dc3247 bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:2488:5 #27 0x00007f1f56db2adf testing::UnitTest::Run() /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/src/gtest.cc:4925:10 #28 0x00007f1f578add71 RUN_ALL_TESTS() /home/xxxxx/Sources/llvm-project-main/third-party/unittest/googletest/include/gtest/gtest.h:2472:3 #29 0x00007f1f578adcb4 main /home/xxxxx/Sources/llvm-project-main/third-party/unittest/UnitTestMain/TestMain.cpp:55:3 #30 0x00007f1f536461ca __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:74:3 #31 0x00007f1f53646285 call_init ./csu/../csu/libc-start.c:128:20 #32 0x00007f1f53646285 __libc_start_main ./csu/../csu/libc-start.c:347:5 #33 0x0000562aa51aed31 _start (./build/tools/clang/unittests/AST/ASTTests+0x490d31)
FriendCountAndPosition computation for FromContext by pointer comparison is not reliable in this case.
As ToContext counts what's already imported, we could use ASTStructuralEquivalence which is more reliable.
According to the coding rules auto should not be used here.