Index: lldb/include/lldb/Symbol/CompilerType.h =================================================================== --- lldb/include/lldb/Symbol/CompilerType.h +++ lldb/include/lldb/Symbol/CompilerType.h @@ -66,10 +66,10 @@ /// Tests. /// \{ explicit operator bool() const { - return m_type != nullptr && m_type_system != nullptr; + return IsValid(); } - bool IsValid() const { return m_type != nullptr && m_type_system != nullptr; } + bool IsValid() const; bool IsArrayType(CompilerType *element_type = nullptr, uint64_t *size = nullptr, Index: lldb/include/lldb/Symbol/TypeSystem.h =================================================================== --- lldb/include/lldb/Symbol/TypeSystem.h +++ lldb/include/lldb/Symbol/TypeSystem.h @@ -21,6 +21,7 @@ #include "llvm/Support/Error.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Expression/Expression.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" @@ -74,7 +75,8 @@ class TypeSystem : public PluginInterface { public: // Constructors and Destructors - ~TypeSystem() override; + TypeSystem(); + ~TypeSystem() = default; // LLVM RTTI support virtual bool isA(const void *ClassID) const = 0; @@ -87,7 +89,7 @@ // Free up any resources associated with this TypeSystem. Done before // removing all the TypeSystems from the TypeSystemMap. - virtual void Finalize() {} + virtual void Finalize(); virtual DWARFASTParser *GetDWARFParser() { return nullptr; } virtual PDBASTParser *GetPDBParser() { return nullptr; } @@ -558,6 +560,12 @@ llvm::Optional create_callback = llvm::None); }; +using TypeSystemSet = + ThreadSafeDenseMap; +/// A set of type systems that have been deleted and can no longer be accessed. +/// The bool value is unused. +TypeSystemSet &GetTypeSystemGraveyard(); + } // namespace lldb_private #endif // LLDB_SYMBOL_TYPESYSTEM_H Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -552,7 +552,8 @@ } TypeSystemClang::TypeSystemClang(llvm::StringRef name, - llvm::Triple target_triple) { + llvm::Triple target_triple) + : TypeSystem() { m_display_name = name.str(); if (!target_triple.str().empty()) SetTargetTriple(target_triple.str()); @@ -562,7 +563,8 @@ } TypeSystemClang::TypeSystemClang(llvm::StringRef name, - ASTContext &existing_ctxt) { + ASTContext &existing_ctxt) + : TypeSystem() { m_display_name = name.str(); SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str()); @@ -661,6 +663,7 @@ m_diagnostics_engine_up.reset(); m_source_manager_up.reset(); m_language_options_up.reset(); + TypeSystem::Finalize(); } void TypeSystemClang::setSema(Sema *s) { Index: lldb/source/Symbol/CompilerType.cpp =================================================================== --- lldb/source/Symbol/CompilerType.cpp +++ lldb/source/Symbol/CompilerType.cpp @@ -11,11 +11,13 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" #include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Scalar.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" @@ -26,6 +28,17 @@ using namespace lldb; using namespace lldb_private; +bool CompilerType::IsValid() const { + if (!m_type || !m_type_system) + return false; + bool unused; + if (GetTypeSystemGraveyard().Lookup(m_type_system, unused)) { + lldbassert(false && "CompilerType belongs to deleted Typesystem"); + return false; + } + return true; +} + // Tests bool CompilerType::IsAggregateType() const { Index: lldb/source/Symbol/TypeSystem.cpp =================================================================== --- lldb/source/Symbol/TypeSystem.cpp +++ lldb/source/Symbol/TypeSystem.cpp @@ -17,6 +17,12 @@ using namespace lldb_private; using namespace lldb; +TypeSystemSet &lldb_private::GetTypeSystemGraveyard() { + // Intentionally leaked to avoid C++ destructor ordering issue. + static TypeSystemSet *g_typesystem_graveyard = new TypeSystemSet(); + return *g_typesystem_graveyard; +} + /// A 64-bit SmallBitVector is only small up to 64-7 bits, and the /// setBitsInMask interface wants to write full bytes. static const size_t g_num_small_bitvector_bits = 64 - 8; @@ -35,7 +41,11 @@ bool LanguageSet::Empty() const { return bitvector.none(); } bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; } -TypeSystem::~TypeSystem() = default; +TypeSystem::TypeSystem() { + // Remove this pointer from the graveyard in case it got reused. + GetTypeSystemGraveyard().Erase(this); +} +void TypeSystem::Finalize() { GetTypeSystemGraveyard().Insert(this, false); } static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language, Module *module, Target *target) { Index: lldb/unittests/Symbol/TestTypeSystemClang.cpp =================================================================== --- lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -29,6 +29,7 @@ void SetUp() override { m_ast.reset( new TypeSystemClang("test ASTContext", HostInfo::GetTargetTriple())); + GetTypeSystemGraveyard().Erase(m_ast.get()); } void TearDown() override { m_ast.reset(); }