https://github.com/hokein updated 
https://github.com/llvm/llvm-project/pull/139253

>From b8ba1ae30227fd7c946c5f5e57fb83e47f3bbe69 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein...@gmail.com>
Date: Fri, 9 May 2025 10:24:01 +0200
Subject: [PATCH 1/6] Reland "Reland [Modules] Remove unnecessary check when
 generating name lookup table in ASTWriter"

This relands the patch 
https://github.com/llvm/llvm-project/commit/67b298f6d82e0b4bb648ac0dabe895e816a77ef1
---
 clang/include/clang/Serialization/ASTWriter.h |   2 -
 clang/lib/Serialization/ASTWriter.cpp         | 117 ++++++------------
 clang/test/Modules/pr61065.cppm               |   6 +-
 3 files changed, 44 insertions(+), 81 deletions(-)

diff --git a/clang/include/clang/Serialization/ASTWriter.h 
b/clang/include/clang/Serialization/ASTWriter.h
index 9f0570eddc34e..cf4ae610ea51f 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -592,8 +592,6 @@ class ASTWriter : public ASTDeserializationListener,
   void WriteTypeAbbrevs();
   void WriteType(ASTContext &Context, QualType T);
 
-  bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
-
   void GenerateSpecializationInfoLookupTable(
       const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
       llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial);
diff --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index 8c5adc3959398..4211a4a7275e5 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4504,12 +4504,6 @@ uint64_t ASTWriter::WriteSpecializationInfoLookupTable(
   return Offset;
 }
 
-bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
-                                       DeclContext *DC) {
-  return Result.hasExternalDecls() &&
-         DC->hasNeedToReconcileExternalVisibleStorage();
-}
-
 /// Returns ture if all of the lookup result are either external, not emitted 
or
 /// predefined. In such cases, the lookup result is not interesting and we 
don't
 /// need to record the result in the current being written module. Return false
@@ -4561,14 +4555,12 @@ void ASTWriter::GenerateNameLookupTable(
   // order.
   SmallVector<DeclarationName, 16> Names;
 
-  // We also build up small sets of the constructor and conversion function
-  // names which are visible.
-  llvm::SmallPtrSet<DeclarationName, 8> ConstructorNameSet, ConversionNameSet;
-
-  for (auto &Lookup : *DC->buildLookup()) {
-    auto &Name = Lookup.first;
-    auto &Result = Lookup.second;
+  // We also track whether we're writing out the DeclarationNameKey for
+  // constructors or conversion functions.
+  bool IncludeConstructorNames = false;
+  bool IncludeConversionNames = false;
 
+  for (auto &[Name, Result] : *DC->buildLookup()) {
     // If there are no local declarations in our lookup result, we
     // don't need to write an entry for the name at all. If we can't
     // write out a lookup set without performing more deserialization,
@@ -4577,15 +4569,8 @@ void ASTWriter::GenerateNameLookupTable(
     // Also in reduced BMI, we'd like to avoid writing unreachable
     // declarations in GMF, so we need to avoid writing declarations
     // that entirely external or unreachable.
-    //
-    // FIMXE: It looks sufficient to test
-    // isLookupResultNotInteresting here. But due to bug we have
-    // to test isLookupResultExternal here. See
-    // https://github.com/llvm/llvm-project/issues/61065 for details.
-    if ((GeneratingReducedBMI || isLookupResultExternal(Result, DC)) &&
-        isLookupResultNotInteresting(*this, Result))
+    if (GeneratingReducedBMI && isLookupResultNotInteresting(*this, Result))
       continue;
-
     // We also skip empty results. If any of the results could be external and
     // the currently available results are empty, then all of the results are
     // external and we skip it above. So the only way we get here with an empty
@@ -4600,24 +4585,26 @@ void ASTWriter::GenerateNameLookupTable(
     // results for them. This in almost certainly a bug in Clang's name lookup,
     // but that is likely to be hard or impossible to fix and so we tolerate it
     // here by omitting lookups with empty results.
-    if (Lookup.second.getLookupResult().empty())
+    if (Result.getLookupResult().empty())
       continue;
 
-    switch (Lookup.first.getNameKind()) {
+    switch (Name.getNameKind()) {
     default:
-      Names.push_back(Lookup.first);
+      Names.push_back(Name);
       break;
 
     case DeclarationName::CXXConstructorName:
-      assert(isa<CXXRecordDecl>(DC) &&
-             "Cannot have a constructor name outside of a class!");
-      ConstructorNameSet.insert(Name);
+      // assert(isa<CXXRecordDecl>(DC) &&
+      //        "Cannot have a constructor name outside of a class!");
+      // ConstructorNameSet.insert(Name);
+      IncludeConstructorNames = true;
       break;
 
     case DeclarationName::CXXConversionFunctionName:
-      assert(isa<CXXRecordDecl>(DC) &&
-             "Cannot have a conversion function name outside of a class!");
-      ConversionNameSet.insert(Name);
+      // assert(isa<CXXRecordDecl>(DC) &&
+      //        "Cannot have a conversion function name outside of a class!");
+      // ConversionNameSet.insert(Name);
+      IncludeConversionNames = true;
       break;
     }
   }
@@ -4625,57 +4612,35 @@ void ASTWriter::GenerateNameLookupTable(
   // Sort the names into a stable order.
   llvm::sort(Names);
 
-  if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {
+  // if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {
+  if (IncludeConstructorNames || IncludeConversionNames) {
     // We need to establish an ordering of constructor and conversion function
-    // names, and they don't have an intrinsic ordering.
-
-    // First we try the easy case by forming the current context's constructor
-    // name and adding that name first. This is a very useful optimization to
-    // avoid walking the lexical declarations in many cases, and it also
-    // handles the only case where a constructor name can come from some other
-    // lexical context -- when that name is an implicit constructor merged from
-    // another declaration in the redecl chain. Any non-implicit constructor or
-    // conversion function which doesn't occur in all the lexical contexts
-    // would be an ODR violation.
-    auto ImplicitCtorName = Context.DeclarationNames.getCXXConstructorName(
-        Context.getCanonicalType(Context.getRecordType(D)));
-    if (ConstructorNameSet.erase(ImplicitCtorName))
-      Names.push_back(ImplicitCtorName);
-
-    // If we still have constructors or conversion functions, we walk all the
-    // names in the decl and add the constructors and conversion functions
-    // which are visible in the order they lexically occur within the context.
-    if (!ConstructorNameSet.empty() || !ConversionNameSet.empty())
-      for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls())
-        if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {
-          auto Name = ChildND->getDeclName();
-          switch (Name.getNameKind()) {
-          default:
-            continue;
-
-          case DeclarationName::CXXConstructorName:
-            if (ConstructorNameSet.erase(Name))
-              Names.push_back(Name);
-            break;
+    // names, and they don't have an intrinsic ordering. We also need to write
+    // out all constructor and conversion function results if we write out any
+    // of them, because they're all tracked under the same lookup key.
+    llvm::SmallPtrSet<DeclarationName, 8> AddedNames;
+    for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls()) {
+      if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {
+        auto Name = ChildND->getDeclName();
+        switch (Name.getNameKind()) {
+        default:
+          continue;
 
-          case DeclarationName::CXXConversionFunctionName:
-            if (ConversionNameSet.erase(Name))
-              Names.push_back(Name);
-            break;
-          }
+        case DeclarationName::CXXConstructorName:
+          if (!IncludeConstructorNames)
+            continue;
+          break;
 
-          if (ConstructorNameSet.empty() && ConversionNameSet.empty())
-            break;
+        case DeclarationName::CXXConversionFunctionName:
+          if (!IncludeConversionNames)
+            continue;
+          break;
         }
-
-    assert(ConstructorNameSet.empty() && "Failed to find all of the visible "
-                                         "constructors by walking all the "
-                                         "lexical members of the context.");
-    assert(ConversionNameSet.empty() && "Failed to find all of the visible "
-                                        "conversion functions by walking all "
-                                        "the lexical members of the context.");
+        if (AddedNames.insert(Name).second)
+          Names.push_back(Name);
+      }
+    }
   }
-
   // Next we need to do a lookup with each name into this decl context to fully
   // populate any results from external sources. We don't actually use the
   // results of these lookups because we only want to use the results after all
diff --git a/clang/test/Modules/pr61065.cppm b/clang/test/Modules/pr61065.cppm
index c79d7ac4457a1..f6a0d149c93f8 100644
--- a/clang/test/Modules/pr61065.cppm
+++ b/clang/test/Modules/pr61065.cppm
@@ -18,9 +18,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o 
%t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o 
%t/b.pcm \
 // RUN:     -fprebuilt-module-path=%t
-// DISABLED: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o 
%t/c.pcm \
-// DISABLED:     -fprebuilt-module-path=%t
-// DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify 
-fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o 
%t/c.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify 
-fprebuilt-module-path=%t
 
 
 //--- a.cppm

>From 7ca897c038a8869ac3c46c37c228096d0853667d Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakal...@google.com>
Date: Mon, 12 May 2025 15:18:05 +0200
Subject: [PATCH 2/6] Add test cases.

---
 clang/test/Modules/GH61065-2.cppm | 34 +++++++++++++++++++++++++
 clang/test/Modules/GH61065-3.cppm | 42 +++++++++++++++++++++++++++++++
 clang/test/Modules/GH61065.cppm   | 15 +++++++++++
 3 files changed, 91 insertions(+)
 create mode 100644 clang/test/Modules/GH61065-2.cppm
 create mode 100644 clang/test/Modules/GH61065-3.cppm
 create mode 100644 clang/test/Modules/GH61065.cppm

diff --git a/clang/test/Modules/GH61065-2.cppm 
b/clang/test/Modules/GH61065-2.cppm
new file mode 100644
index 0000000000000..57a1f1102ff63
--- /dev/null
+++ b/clang/test/Modules/GH61065-2.cppm
@@ -0,0 +1,34 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang -std=c++20 -Wno-experimental-header-units -fmodule-header 
%t/RelaxedAtomic.h -o %t/RelaxedAtomic.pcm
+// RUN: %clang -std=c++20 -Wno-experimental-header-units -fmodule-header 
-fmodule-file=%t/RelaxedAtomic.pcm %t/SharedMutex.h -o %t/SharedMutex.pcm
+// RUN: %clang -std=c++20 -Wno-experimental-header-units -fmodule-header 
-fmodule-file=%t/SharedMutex.pcm -fmodule-file=%t/RelaxedAtomic.pcm 
%t/ThreadLocalDetail.h -o %t/ThreadLocalDetail.pcm
+//--- RelaxedAtomic.h
+struct relaxed_atomic_base {
+  relaxed_atomic_base(int) {}
+};
+
+struct relaxed_atomic : relaxed_atomic_base {
+  using relaxed_atomic_base::relaxed_atomic_base; // constructor
+};
+
+//--- SharedMutex.h
+import "RelaxedAtomic.h";
+
+inline void getMaxDeferredReaders() {
+  static relaxed_atomic cache{0};
+}
+
+//--- ThreadLocalDetail.h
+import "RelaxedAtomic.h";
+
+struct noncopyable {
+  noncopyable(const noncopyable&) = delete;
+};
+
+struct StaticMetaBase {
+  relaxed_atomic nextId_{0};
+  noncopyable ncp;
+};
diff --git a/clang/test/Modules/GH61065-3.cppm 
b/clang/test/Modules/GH61065-3.cppm
new file mode 100644
index 0000000000000..e19a7a9616d71
--- /dev/null
+++ b/clang/test/Modules/GH61065-3.cppm
@@ -0,0 +1,42 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang -std=c++20 -x c++-module --precompile -c %t/a.cpp -o %t/a.pcm
+// RUN: %clang -std=c++20 -fmodule-file=a=%t/a.pcm --precompile -x c++-module 
-c %t/b.cpp -o %t/b.pcm
+// RUN: %clang -std=c++20 -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -x 
c++-module --precompile -c %t/c.cpp -o /dev/null
+
+//--- a.cpp
+export module a;
+
+struct base {
+       base(int) {}
+};
+
+export struct a : base {
+       using base::base;
+};
+
+//--- b.cpp
+export module b;
+
+import a;
+
+a b() {
+       return a(1);
+}
+
+//--- c.cpp
+export module c;
+
+import a;
+import b;
+
+struct noncopyable {
+       noncopyable(noncopyable const &) = delete;
+};
+
+struct c {
+       noncopyable c0;
+       a c1;
+};
\ No newline at end of file
diff --git a/clang/test/Modules/GH61065.cppm b/clang/test/Modules/GH61065.cppm
new file mode 100644
index 0000000000000..8370ad93b55ed
--- /dev/null
+++ b/clang/test/Modules/GH61065.cppm
@@ -0,0 +1,15 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -fallow-pcm-with-compiler-errors -fmodule-name=c  -xc++ 
-emit-module -fmodules -std=gnu++20 %t/a.cppmap -o %t/c.pcm
+//--- a.cppmap
+module "c" {
+ header "a.h"
+}
+
+//--- a.h
+template <class>
+class C {};
+template <class T>
+C<T>::operator C() {}
\ No newline at end of file

>From 47468e0b50270a2778b73d72352d4c6cec00dcbc Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakal...@google.com>
Date: Mon, 12 May 2025 15:21:53 +0200
Subject: [PATCH 3/6] Minor adjustments.

---
 clang/test/Modules/GH61065-3.cppm             | 42 -------------------
 .../Modules/{GH61065.cppm => pr61065-2.cppm}  |  0
 .../{GH61065-2.cppm => pr61065-3.cppm}        |  0
 clang/test/Modules/pr61065.cppm               |  6 +--
 4 files changed, 3 insertions(+), 45 deletions(-)
 delete mode 100644 clang/test/Modules/GH61065-3.cppm
 rename clang/test/Modules/{GH61065.cppm => pr61065-2.cppm} (100%)
 rename clang/test/Modules/{GH61065-2.cppm => pr61065-3.cppm} (100%)

diff --git a/clang/test/Modules/GH61065-3.cppm 
b/clang/test/Modules/GH61065-3.cppm
deleted file mode 100644
index e19a7a9616d71..0000000000000
--- a/clang/test/Modules/GH61065-3.cppm
+++ /dev/null
@@ -1,42 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir %t
-// RUN: split-file %s %t
-//
-// RUN: %clang -std=c++20 -x c++-module --precompile -c %t/a.cpp -o %t/a.pcm
-// RUN: %clang -std=c++20 -fmodule-file=a=%t/a.pcm --precompile -x c++-module 
-c %t/b.cpp -o %t/b.pcm
-// RUN: %clang -std=c++20 -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -x 
c++-module --precompile -c %t/c.cpp -o /dev/null
-
-//--- a.cpp
-export module a;
-
-struct base {
-       base(int) {}
-};
-
-export struct a : base {
-       using base::base;
-};
-
-//--- b.cpp
-export module b;
-
-import a;
-
-a b() {
-       return a(1);
-}
-
-//--- c.cpp
-export module c;
-
-import a;
-import b;
-
-struct noncopyable {
-       noncopyable(noncopyable const &) = delete;
-};
-
-struct c {
-       noncopyable c0;
-       a c1;
-};
\ No newline at end of file
diff --git a/clang/test/Modules/GH61065.cppm b/clang/test/Modules/pr61065-2.cppm
similarity index 100%
rename from clang/test/Modules/GH61065.cppm
rename to clang/test/Modules/pr61065-2.cppm
diff --git a/clang/test/Modules/GH61065-2.cppm 
b/clang/test/Modules/pr61065-3.cppm
similarity index 100%
rename from clang/test/Modules/GH61065-2.cppm
rename to clang/test/Modules/pr61065-3.cppm
diff --git a/clang/test/Modules/pr61065.cppm b/clang/test/Modules/pr61065.cppm
index f6a0d149c93f8..98e4988cd7174 100644
--- a/clang/test/Modules/pr61065.cppm
+++ b/clang/test/Modules/pr61065.cppm
@@ -6,9 +6,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm \
 // RUN:     -fprebuilt-module-path=%t
-// DISABLED: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface -o 
%t/c.pcm \
-// DISABLED:     -fprebuilt-module-path=%t
-// DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify 
-fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface -o %t/c.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify 
-fprebuilt-module-path=%t
 
 // Test again with reduced BMI
 // RUN: rm -rf %t

>From 49c38568161a245a251e4c7fa7ebb259f8d4e08f Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakal...@google.com>
Date: Mon, 12 May 2025 15:22:35 +0200
Subject: [PATCH 4/6] Minor adjustments.

---
 clang/test/Modules/pr61065-2.cppm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/Modules/pr61065-2.cppm 
b/clang/test/Modules/pr61065-2.cppm
index 8370ad93b55ed..f46a0f73aa203 100644
--- a/clang/test/Modules/pr61065-2.cppm
+++ b/clang/test/Modules/pr61065-2.cppm
@@ -12,4 +12,4 @@ module "c" {
 template <class>
 class C {};
 template <class T>
-C<T>::operator C() {}
\ No newline at end of file
+C<T>::operator C() {}

>From a55894b454acdb93638ae7393f7010da440342e3 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein...@gmail.com>
Date: Mon, 12 May 2025 15:56:10 +0200
Subject: [PATCH 5/6] Cleanup on ASTWriter.cpp

---
 clang/lib/Serialization/ASTWriter.cpp | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index 4211a4a7275e5..c5ad05b525bf9 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4594,16 +4594,10 @@ void ASTWriter::GenerateNameLookupTable(
       break;
 
     case DeclarationName::CXXConstructorName:
-      // assert(isa<CXXRecordDecl>(DC) &&
-      //        "Cannot have a constructor name outside of a class!");
-      // ConstructorNameSet.insert(Name);
       IncludeConstructorNames = true;
       break;
 
     case DeclarationName::CXXConversionFunctionName:
-      // assert(isa<CXXRecordDecl>(DC) &&
-      //        "Cannot have a conversion function name outside of a class!");
-      // ConversionNameSet.insert(Name);
       IncludeConversionNames = true;
       break;
     }
@@ -4612,7 +4606,6 @@ void ASTWriter::GenerateNameLookupTable(
   // Sort the names into a stable order.
   llvm::sort(Names);
 
-  // if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {
   if (IncludeConstructorNames || IncludeConversionNames) {
     // We need to establish an ordering of constructor and conversion function
     // names, and they don't have an intrinsic ordering. We also need to write

>From 6369313a057ce3b8833ddd44509dd5819b3ba834 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein...@gmail.com>
Date: Mon, 12 May 2025 16:01:00 +0200
Subject: [PATCH 6/6] Add release notes

---
 clang/docs/ReleaseNotes.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 918ff952bb2c3..80c2b37a869db 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -551,6 +551,7 @@ Bug Fixes in This Version
 - Fixed a bug where an attribute before a ``pragma clang attribute`` or
   ``pragma clang __debug`` would cause an assertion. Instead, this now 
diagnoses
   the invalid attribute location appropriately.  (#GH137861)
+- Fixed assertion failures when generating name lookup table in modules. 
(#GH61065, #GH134739)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to