llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tidy Author: Thomas Fransham (fsfod) <details> <summary>Changes</summary> Fix missing extern templates for llvm::Registry use in other projects of llvm Windows doesn't implicitly import and merge exported symbols across shared libraries like Linux does so we need to explicitly export/import each instantiation of llvm::Registry. Updated LLVM_INSTANTIATE_REGISTRY to just be a full explicit template instantiation. This is part of the work to enable LLVM_BUILD_LLVM_DYLIB and LLVM plugins on window. --- Full diff: https://github.com/llvm/llvm-project/pull/112640.diff 15 Files Affected: - (modified) clang-tools-extra/clang-doc/Generators.h (+4) - (modified) clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h (+4) - (modified) clang-tools-extra/clangd/URI.h (+4) - (modified) clang-tools-extra/clangd/refactor/Tweak.h (+4) - (modified) clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h (+4) - (modified) clang/include/clang/Basic/ParsedAttrInfo.h (+5) - (modified) clang/include/clang/Frontend/FrontendPluginRegistry.h (+5) - (modified) clang/include/clang/Lex/Preprocessor.h (+5) - (modified) clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h (+6) - (modified) clang/include/clang/Tooling/ToolExecutorPluginRegistry.h (+6) - (modified) flang/include/flang/Frontend/FrontendPluginRegistry.h (+4) - (modified) llvm/include/llvm/CodeGen/GCMetadataPrinter.h (+2) - (modified) llvm/include/llvm/IR/GCStrategy.h (+2) - (modified) llvm/include/llvm/Support/Compiler.h (+11) - (modified) llvm/include/llvm/Support/Registry.h (+34-30) ``````````diff diff --git a/clang-tools-extra/clang-doc/Generators.h b/clang-tools-extra/clang-doc/Generators.h index ba0ef64d3d0f5f..d62d7faa9a69f3 100644 --- a/clang-tools-extra/clang-doc/Generators.h +++ b/clang-tools-extra/clang-doc/Generators.h @@ -55,4 +55,8 @@ std::string getTagType(TagTypeKind AS); } // namespace doc } // namespace clang +namespace llvm { +extern template class Registry<clang::doc::Generator>; +} // namespace llvm + #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H diff --git a/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h b/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h index 78d914bfedbc94..8a07b05c26446c 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h +++ b/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h @@ -18,4 +18,8 @@ using ClangTidyModuleRegistry = llvm::Registry<ClangTidyModule>; } // namespace clang::tidy +namespace llvm { +extern template class Registry<clang::tidy::ClangTidyModule>; +} // namespace llvm + #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H diff --git a/clang-tools-extra/clangd/URI.h b/clang-tools-extra/clangd/URI.h index 7f3bc9d1645a8f..d4629f17551cca 100644 --- a/clang-tools-extra/clangd/URI.h +++ b/clang-tools-extra/clangd/URI.h @@ -133,4 +133,8 @@ typedef llvm::Registry<URIScheme> URISchemeRegistry; } // namespace clangd } // namespace clang +namespace llvm { +extern template class Registry<clang::clangd::URIScheme>; +} // namespace llvm + #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_URI_H diff --git a/clang-tools-extra/clangd/refactor/Tweak.h b/clang-tools-extra/clangd/refactor/Tweak.h index 2769b401d89439..257f44a285f88a 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.h +++ b/clang-tools-extra/clangd/refactor/Tweak.h @@ -147,4 +147,8 @@ prepareTweak(StringRef ID, const Tweak::Selection &S, } // namespace clangd } // namespace clang +namespace llvm { +extern template class Registry<clang::clangd::Tweak>; +} // namespace llvm + #endif diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h index 98aee5f277cf18..b07b9ed1ac25f5 100644 --- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h +++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h @@ -46,4 +46,8 @@ using IncludeSpellingStrategy = llvm::Registry<IncludeSpeller>; std::string spellHeader(const IncludeSpeller::Input &Input); } // namespace clang::include_cleaner +namespace llvm { +extern template class Registry<clang::include_cleaner::IncludeSpeller>; +} // namespace llvm + #endif diff --git a/clang/include/clang/Basic/ParsedAttrInfo.h b/clang/include/clang/Basic/ParsedAttrInfo.h index fab5c6f1377d27..3b5f5d3c3f92ac 100644 --- a/clang/include/clang/Basic/ParsedAttrInfo.h +++ b/clang/include/clang/Basic/ParsedAttrInfo.h @@ -17,6 +17,7 @@ #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/AttributeCommonInfo.h" +#include "clang/Support/Compiler.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Registry.h" #include <climits> @@ -175,4 +176,8 @@ const std::list<std::unique_ptr<ParsedAttrInfo>> &getAttributePluginInstances(); } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI Registry<clang::ParsedAttrInfo>; +} // namespace llvm + #endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H diff --git a/clang/include/clang/Frontend/FrontendPluginRegistry.h b/clang/include/clang/Frontend/FrontendPluginRegistry.h index 810578534acb45..5eea9c2fd89a32 100644 --- a/clang/include/clang/Frontend/FrontendPluginRegistry.h +++ b/clang/include/clang/Frontend/FrontendPluginRegistry.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H #include "clang/Frontend/FrontendAction.h" +#include "clang/Support/Compiler.h" #include "llvm/Support/Registry.h" namespace clang { @@ -23,4 +24,8 @@ using FrontendPluginRegistry = llvm::Registry<PluginASTAction>; } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI Registry<clang::PluginASTAction>; +} // namespace llvm + #endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 4643b0213815f8..92749e4de44b57 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -32,6 +32,7 @@ #include "clang/Lex/PPEmbedParameters.h" #include "clang/Lex/Token.h" #include "clang/Lex/TokenLexer.h" +#include "clang/Support/Compiler.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -3060,4 +3061,8 @@ using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>; } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI Registry<clang::PragmaHandler>; +} // namespace llvm + #endif // LLVM_CLANG_LEX_PREPROCESSOR_H diff --git a/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h index 8c58ad926a402a..e6bcac542b0ecb 100644 --- a/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h +++ b/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H #define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H +#include "clang/Support/Compiler.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/Registry.h" @@ -42,4 +43,9 @@ using CompilationDatabasePluginRegistry = } // namespace tooling } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI + Registry<clang::tooling::CompilationDatabasePlugin>; +} // namespace llvm + #endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H diff --git a/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h b/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h index 5304ff26252def..8d54583234684e 100644 --- a/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h +++ b/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H #define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H +#include "clang/Support/Compiler.h" #include "clang/Tooling/Execution.h" #include "llvm/Support/Registry.h" @@ -20,4 +21,9 @@ using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>; } // namespace tooling } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI + Registry<clang::tooling::ToolExecutorPlugin>; +} // namespace llvm + #endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H diff --git a/flang/include/flang/Frontend/FrontendPluginRegistry.h b/flang/include/flang/Frontend/FrontendPluginRegistry.h index 8b1f576c39e24a..a8079dbfaf8693 100644 --- a/flang/include/flang/Frontend/FrontendPluginRegistry.h +++ b/flang/include/flang/Frontend/FrontendPluginRegistry.h @@ -25,4 +25,8 @@ using FrontendPluginRegistry = llvm::Registry<PluginParseTreeAction>; } // namespace Fortran::frontend +namespace llvm { +extern template class Registry<Fortran::frontend::PluginParseTreeAction>; +} + #endif // FORTRAN_FRONTEND_FRONTENDPLUGINREGISTRY_H diff --git a/llvm/include/llvm/CodeGen/GCMetadataPrinter.h b/llvm/include/llvm/CodeGen/GCMetadataPrinter.h index f9527c9f8752e9..9d421be8313f01 100644 --- a/llvm/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/llvm/include/llvm/CodeGen/GCMetadataPrinter.h @@ -34,6 +34,8 @@ class StackMaps; /// defaults from Registry. using GCMetadataPrinterRegistry = Registry<GCMetadataPrinter>; +extern template class LLVM_TEMPLATE_ABI Registry<GCMetadataPrinter>; + /// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are /// created, managed, and owned by the AsmPrinter. class GCMetadataPrinter { diff --git a/llvm/include/llvm/IR/GCStrategy.h b/llvm/include/llvm/IR/GCStrategy.h index 3186465f001812..cbfbe23aaa0683 100644 --- a/llvm/include/llvm/IR/GCStrategy.h +++ b/llvm/include/llvm/IR/GCStrategy.h @@ -141,6 +141,8 @@ class GCStrategy { /// GCMetadataPrinterRegistery as well. using GCRegistry = Registry<GCStrategy>; +extern template class LLVM_TEMPLATE_ABI Registry<GCStrategy>; + /// Lookup the GCStrategy object associated with the given gc name. std::unique_ptr<GCStrategy> getGCStrategy(const StringRef Name); diff --git a/llvm/include/llvm/Support/Compiler.h b/llvm/include/llvm/Support/Compiler.h index 1d2d751d4dc11a..ab0cbff43d749c 100644 --- a/llvm/include/llvm/Support/Compiler.h +++ b/llvm/include/llvm/Support/Compiler.h @@ -153,6 +153,12 @@ /// exported when llvm is built as a shared library with everything else that is /// unannotated will have internal visibility. /// +/// LLVM_ABI_EXPORT is for the special case for things like plugin symbol +/// declarations or definitions where we don't want the macro to be switching +/// between dllexport and dllimport on windows based on what codebase is being +/// built, it will only be dllexport. For non windows platforms this macro +/// behaves the same as LLVM_ABI. +/// /// LLVM_EXPORT_TEMPLATE is used on explicit template instantiations in source /// files that were declared extern in a header. This macro is only set as a /// compiler export attribute on windows, on other platforms it does nothing. @@ -179,6 +185,7 @@ #define LLVM_ABI #define LLVM_TEMPLATE_ABI #define LLVM_EXPORT_TEMPLATE +#define LLVM_ABI_EXPORT #elif defined(_WIN32) && !defined(__MINGW32__) #if defined(LLVM_EXPORTS) #define LLVM_ABI __declspec(dllexport) @@ -189,19 +196,23 @@ #define LLVM_TEMPLATE_ABI __declspec(dllimport) #define LLVM_EXPORT_TEMPLATE #endif +#define LLVM_ABI_EXPORT __declspec(dllexport) #elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) #define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT #define LLVM_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT #define LLVM_EXPORT_TEMPLATE +#define LLVM_ABI_EXPORT LLVM_ATTRIBUTE_VISIBILITY_DEFAULT #elif defined(__MACH__) || defined(__WASM__) #define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT #define LLVM_TEMPLATE_ABI #define LLVM_EXPORT_TEMPLATE +#define LLVM_ABI_EXPORT LLVM_ATTRIBUTE_VISIBILITY_DEFAULT #endif #else #define LLVM_ABI #define LLVM_TEMPLATE_ABI #define LLVM_EXPORT_TEMPLATE +#define LLVM_ABI_EXPORT #endif #define LLVM_C_ABI LLVM_ABI #endif diff --git a/llvm/include/llvm/Support/Registry.h b/llvm/include/llvm/Support/Registry.h index 5bb6a254a47f4c..ff9226c39359c5 100644 --- a/llvm/include/llvm/Support/Registry.h +++ b/llvm/include/llvm/Support/Registry.h @@ -53,7 +53,13 @@ namespace llvm { Registry() = delete; friend class node; - static node *Head, *Tail; + // These must be must two separate declarations to workaround a 20 year + // old MSVC bug with dllexport and multiple static fields in the same + // declaration causing error C2487 "member of dll interface class may not + // be declared with dll interface". + // https://developercommunity.visualstudio.com/t/c2487-in-dllexport-class-with-static-members/69878 + static node *Head; + static node *Tail; public: /// Node in linked list of entries. @@ -76,7 +82,13 @@ namespace llvm { /// add a node to the executable's registry. Therefore it's not defined here /// to avoid it being instantiated in the plugin and is instead defined in /// the executable (see LLVM_INSTANTIATE_REGISTRY below). - static void add_node(node *N); + static void add_node(node *N) { + if (Tail) + Tail->Next = N; + else + Head = N; + Tail = N; + } /// Iterators for registry entries. /// @@ -95,7 +107,7 @@ namespace llvm { // begin is not defined here in order to avoid usage of an undefined static // data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY. - static iterator begin(); + static iterator begin() { return iterator(Head); } static iterator end() { return iterator(nullptr); } static iterator_range<iterator> entries() { @@ -124,36 +136,28 @@ namespace llvm { } }; }; + } // end namespace llvm +#ifdef _WIN32 /// Instantiate a registry class. -/// -/// This provides template definitions of add_node, begin, and the Head and Tail -/// pointers, then explicitly instantiates them. We could explicitly specialize -/// them, instead of the two-step process of define then instantiate, but -/// strictly speaking that's not allowed by the C++ standard (we would need to -/// have explicit specialization declarations in all translation units where the -/// specialization is used) so we don't. -#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \ - namespace llvm { \ - template<typename T> typename Registry<T>::node *Registry<T>::Head = nullptr;\ - template<typename T> typename Registry<T>::node *Registry<T>::Tail = nullptr;\ - template<typename T> \ - void Registry<T>::add_node(typename Registry<T>::node *N) { \ - if (Tail) \ - Tail->Next = N; \ - else \ - Head = N; \ - Tail = N; \ - } \ - template<typename T> typename Registry<T>::iterator Registry<T>::begin() { \ - return iterator(Head); \ - } \ - template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Head; \ - template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Tail; \ - template \ - void Registry<REGISTRY_CLASS::type>::add_node(REGISTRY_CLASS::node*); \ - template REGISTRY_CLASS::iterator Registry<REGISTRY_CLASS::type>::begin(); \ +#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \ + namespace llvm { \ + template <typename T> \ + typename Registry<T>::node *Registry<T>::Head = nullptr; \ + template <typename T> \ + typename Registry<T>::node *Registry<T>::Tail = nullptr; \ + template class LLVM_ABI_EXPORT Registry<REGISTRY_CLASS::type>; \ + } +#else +#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \ + namespace llvm { \ + template <typename T> \ + typename Registry<T>::node *Registry<T>::Head = nullptr; \ + template <typename T> \ + typename Registry<T>::node *Registry<T>::Tail = nullptr; \ + template class Registry<REGISTRY_CLASS::type>; \ } +#endif #endif // LLVM_SUPPORT_REGISTRY_H `````````` </details> https://github.com/llvm/llvm-project/pull/112640 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits