[llvm] [llvm] get cl::opt instantiations working with MSVC DLL build (PR #147810)
Andrew Rogers via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 14 08:32:09 PDT 2025
https://github.com/andrurogerz updated https://github.com/llvm/llvm-project/pull/147810
>From 5b42e4a789cf05e366c52f409d80a8302e24469f Mon Sep 17 00:00:00 2001
From: Andrew Rogers <andrurogerz at gmail.com>
Date: Wed, 9 Jul 2025 12:03:59 -0700
Subject: [PATCH] [llvm] get cl::opt instantiations working with MSVC DLL build
---
llvm/include/llvm/Support/CommandLine.h | 19 +++++++++++-----
llvm/lib/Support/CommandLine.cpp | 29 ++++++++++++++++++++-----
2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index adaa75cc6c348..ab3ab9b52ac12 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -1518,11 +1518,20 @@ class opt
[](const typename ParserClass::parser_data_type &) {};
};
-extern template class opt<unsigned>;
-extern template class opt<int>;
-extern template class opt<std::string>;
-extern template class opt<char>;
-extern template class opt<bool>;
+#if !defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS) || \
+ !(defined(_MSC_VER) && !defined(__clang__))
+// Only instantiate opt<std::string> when not building a Windows DLL with MSVC.
+// When exporting opt<std::string>, MSVC cl implicitly exports symbols for
+// std::basic_string through transitive inheritance via std::string. These
+// symbols may appear in other TUs with different linkage, leading to duplicate
+// symbol conflicts.
+extern template class LLVM_TEMPLATE_ABI opt<std::string>;
+#endif
+
+extern template class LLVM_TEMPLATE_ABI opt<unsigned>;
+extern template class LLVM_TEMPLATE_ABI opt<int>;
+extern template class LLVM_TEMPLATE_ABI opt<char>;
+extern template class LLVM_TEMPLATE_ABI opt<bool>;
//===----------------------------------------------------------------------===//
// Default storage class definition: external storage. This implementation
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index d5c3cba13e030..c9541289aa3bd 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -68,11 +68,21 @@ template class LLVM_EXPORT_TEMPLATE basic_parser<float>;
template class LLVM_EXPORT_TEMPLATE basic_parser<std::string>;
template class LLVM_EXPORT_TEMPLATE basic_parser<char>;
-template class opt<unsigned>;
-template class opt<int>;
-template class opt<std::string>;
-template class opt<char>;
-template class opt<bool>;
+#if !defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS) || \
+ !(defined(_MSC_VER) && !defined(__clang__))
+// Only instantiate opt<std::string> when not building a Windows DLL with MSVC.
+// When exporting opt<std::string>, MSVC cl implicitly exports symbols for
+// std::basic_string through transitive inheritance via std::string. These
+// symbols may appear in other TUs with different linkage, leading to duplicate
+// symbol conflicts.
+template class LLVM_EXPORT_TEMPLATE opt<std::string>;
+#endif
+
+template class LLVM_EXPORT_TEMPLATE opt<bool>;
+template class LLVM_EXPORT_TEMPLATE opt<char>;
+template class LLVM_EXPORT_TEMPLATE opt<int>;
+template class LLVM_EXPORT_TEMPLATE opt<unsigned>;
+
} // namespace cl
} // namespace llvm
@@ -95,6 +105,15 @@ void parser<float>::anchor() {}
void parser<std::string>::anchor() {}
void parser<char>::anchor() {}
+// These anchor functions instantiate opt<T> 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<bool> anchor{""}; }
+void opt_char_anchor() { opt<char> anchor{""}; }
+void opt_int_anchor() { opt<int> anchor{""}; }
+void opt_unsigned_anchor() { opt<unsigned> anchor{""}; }
+
//===----------------------------------------------------------------------===//
const static size_t DefaultPad = 2;
More information about the llvm-commits
mailing list