ayzhao created this revision. Herald added a project: All. ayzhao requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D150001 Files: clang/include/clang/AST/DeclBase.h clang/lib/Sema/SemaDeclCXX.cpp clang/test/Modules/match_initializer_list.cpp Index: clang/test/Modules/match_initializer_list.cpp =================================================================== --- /dev/null +++ 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}); } Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -11567,6 +11567,8 @@ &PP.getIdentifierTable().get("std"), /*PrevDecl=*/nullptr, /*Nested=*/false); getStdNamespace()->setImplicit(true); + Context.getTranslationUnitDecl()->addDecl(getStdNamespace()); + getStdNamespace()->clearIdentifierNamespace(); } return getStdNamespace(); Index: clang/include/clang/AST/DeclBase.h =================================================================== --- clang/include/clang/AST/DeclBase.h +++ clang/include/clang/AST/DeclBase.h @@ -1172,6 +1172,12 @@ } } + /// 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.
Index: clang/test/Modules/match_initializer_list.cpp =================================================================== --- /dev/null +++ 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}); } Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -11567,6 +11567,8 @@ &PP.getIdentifierTable().get("std"), /*PrevDecl=*/nullptr, /*Nested=*/false); getStdNamespace()->setImplicit(true); + Context.getTranslationUnitDecl()->addDecl(getStdNamespace()); + getStdNamespace()->clearIdentifierNamespace(); } return getStdNamespace(); Index: clang/include/clang/AST/DeclBase.h =================================================================== --- clang/include/clang/AST/DeclBase.h +++ clang/include/clang/AST/DeclBase.h @@ -1172,6 +1172,12 @@ } } + /// 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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits