[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

Ding Fei via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 11 01:08:53 PDT 2023


danix800 created this revision.
danix800 added reviewers: balazske, aaron.ballman.
danix800 added a project: clang.
Herald added subscribers: pengfei, martong, kristof.beyls.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

1. 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.

2. Import single friend node `m` into existing context would crash with an assertion failure:

  ./build/tools/clang/unittests/AST/ASTTests --gtest_filter="*ImportFriendClasses.ImportOfRepeatedFriendFunctionTemplateDecl*" |& sed 's/danis/xxxxx/'
  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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157684

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D157684.549271.patch
Type: text/x-patch
Size: 7616 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230811/cf55a14e/attachment-0001.bin>


More information about the cfe-commits mailing list