diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h index adaa75cc6c348..ca725b8ac8712 100644 --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -1518,11 +1518,18 @@ class opt [](const typename ParserClass::parser_data_type &) {}; }; -extern template class opt; -extern template class opt; -extern template class opt; -extern template class opt; -extern template class opt; +#if !(defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS) && defined(_MSC_VER)) +// Only instantiate opt when not building a Windows DLL. When +// exporting opt, MSVC implicitly exports symbols for +// std::basic_string through transitive inheritance via std::string. These +// symbols may appear in clients, leading to duplicate symbol conflicts. +extern template class LLVM_TEMPLATE_ABI opt; +#endif + +extern template class LLVM_TEMPLATE_ABI opt; +extern template class LLVM_TEMPLATE_ABI opt; +extern template class LLVM_TEMPLATE_ABI opt; +extern template class LLVM_TEMPLATE_ABI opt; //===----------------------------------------------------------------------===// // Default storage class definition: external storage. This implementation diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp index d5c3cba13e030..8491633df97e8 100644 --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -68,11 +68,19 @@ template class LLVM_EXPORT_TEMPLATE basic_parser; template class LLVM_EXPORT_TEMPLATE basic_parser; template class LLVM_EXPORT_TEMPLATE basic_parser; -template class opt; -template class opt; -template class opt; -template class opt; -template class opt; +#if !(defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS) && defined(_MSC_VER)) +// Only instantiate opt when not building a Windows DLL. When +// exporting opt, MSVC implicitly exports symbols for +// std::basic_string through transitive inheritance via std::string. These +// symbols may appear in clients, leading to duplicate symbol conflicts. +template class LLVM_EXPORT_TEMPLATE opt; +#endif + +template class LLVM_EXPORT_TEMPLATE opt; +template class LLVM_EXPORT_TEMPLATE opt; +template class LLVM_EXPORT_TEMPLATE opt; +template class LLVM_EXPORT_TEMPLATE opt; + } // namespace cl } // namespace llvm @@ -95,6 +103,15 @@ void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} +// These anchor functions instantiate opt and reference its virtual +// destructor to ensure MSVC exports the corresponding vtable and typeinfo when +// building a Windows DLL. Without an explicit reference, MSVC may omit the +// instantiation at link time even if it is marked DLL-export. +void opt_bool_anchor() { opt anchor{""}; } +void opt_char_anchor() { opt anchor{""}; } +void opt_int_anchor() { opt anchor{""}; } +void opt_unsigned_anchor() { opt anchor{""}; } + //===----------------------------------------------------------------------===// const static size_t DefaultPad = 2;