[clang] d1d35f0 - [clang] Fix initializer_list matching failures with modules

Alan Zhao via cfe-commits cfe-commits at lists.llvm.org
Tue May 9 10:31:49 PDT 2023


Author: Alan Zhao
Date: 2023-05-09T10:31:43-07:00
New Revision: d1d35f04c6cb2e3d5b0fbc6101d5425a33f8fc63

URL: https://github.com/llvm/llvm-project/commit/d1d35f04c6cb2e3d5b0fbc6101d5425a33f8fc63
DIFF: https://github.com/llvm/llvm-project/commit/d1d35f04c6cb2e3d5b0fbc6101d5425a33f8fc63.diff

LOG: [clang] Fix initializer_list matching failures with modules

Previously, if a class with a defined public virtual destructor is
declared before including <initializer_list> and initializer_list is
provided via a Clang module, then overload resolution would fail for
std::initializer_list. This is because when Clang sees the virtual
destructor, Clang creates an implicit NamespaceDecl for std to
implicitly declare a std::bad_alloc. That NamespaceDecl is not added to
the translation unit's lookup table, so when the module containing
std::initializer_list is imported later, that module's std NamespaceDecl
can't find the previous std NamespaceDecl during redeclaration lookup,
causing overload resolution to fail.

To fix this, implicitly created std NamespaceDecls are now added to the
lookup map. At the same time, their IdentifierNamespace members are
cleared to prevent regular name lookups from finding it.

Fixes 60929

Reviewed By: ChuanqiXu, #clang-language-wg, inclyc

Differential Revision: https://reviews.llvm.org/D150001

Added: 
    clang/test/Modules/match_initializer_list.cpp

Modified: 
    clang/include/clang/AST/DeclBase.h
    clang/lib/Sema/SemaDeclCXX.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index e86eadab0a8a4..be76d1648b9ac 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1172,6 +1172,12 @@ class alignas(8) Decl {
     }
   }
 
+  /// Clears the namespace of this declaration.
+  ///
+  /// This is useful if we want this declaration to be available for
+  /// redeclaration lookup but otherwise hidden for ordinary name lookups.
+  void clearIdentifierNamespace() { IdentifierNamespace = 0; }
+
   enum FriendObjectKind {
     FOK_None,      ///< Not a friend object.
     FOK_Declared,  ///< A friend of a previously-declared entity.

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 4efa1b408607d..e68afaa61ef1c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11567,6 +11567,10 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() {
         &PP.getIdentifierTable().get("std"),
         /*PrevDecl=*/nullptr, /*Nested=*/false);
     getStdNamespace()->setImplicit(true);
+    // We want the created NamespaceDecl to be available for redeclaration
+    // lookups, but not for regular name lookups.
+    Context.getTranslationUnitDecl()->addDecl(getStdNamespace());
+    getStdNamespace()->clearIdentifierNamespace();
   }
 
   return getStdNamespace();

diff  --git a/clang/test/Modules/match_initializer_list.cpp b/clang/test/Modules/match_initializer_list.cpp
new file mode 100644
index 0000000000000..31e2b015a9d05
--- /dev/null
+++ b/clang/test/Modules/match_initializer_list.cpp
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+//
+// RUN: %clang_cc1 -x c++ -fmodules -fmodules-cache-path=%t \
+// RUN:     -I %S/Inputs/initializer_list \
+// RUN:     -fmodule-map-file=%S/Inputs/initializer_list/direct.modulemap \
+// RUN:     %s -verify
+
+// expected-no-diagnostics
+
+class C {
+  public:
+  virtual ~C() {}
+};
+
+#include "Inputs/initializer_list/direct.h"
+
+void takesInitList(std::initializer_list<int>);
+
+void passesInitList() { takesInitList({0}); }


        


More information about the cfe-commits mailing list