diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h index c22060852ac..881fbc81e50 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/DerivedTypes.h @@ -496,6 +496,7 @@ public: /// OpaqueType - Class to represent abstract types /// class OpaqueType : public DerivedType { + friend class LLVMContextImpl; OpaqueType(const OpaqueType &); // DO NOT IMPLEMENT const OpaqueType &operator=(const OpaqueType &); // DO NOT IMPLEMENT OpaqueType(LLVMContext &C); diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index bed2f138ddb..fd56b16639c 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -132,7 +132,7 @@ class SMDiagnostic { unsigned ShowLine : 1; public: - SMDiagnostic() : LineNo(0), ColumnNo(0) {} + SMDiagnostic() : LineNo(0), ColumnNo(0), ShowLine(0) {} SMDiagnostic(const std::string &FN, int Line, int Col, const std::string &Msg, const std::string &LineStr, bool showline = true) diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index ccca7892095..f7f4860614a 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -164,7 +164,10 @@ public: // Opaque types are not structurally uniqued, so don't use TypeMap. typedef SmallPtrSet OpaqueTypesTy; OpaqueTypesTy OpaqueTypes; - + + /// Used as an abstract type that will never be resolved. + OpaqueType *const AlwaysOpaqueTy; + /// ValueHandles - This map keeps track of all of the value handles that are /// watching a Value*. The Value::HasValueHandle bit is used to know @@ -196,7 +199,12 @@ public: Int8Ty(C, 8), Int16Ty(C, 16), Int32Ty(C, 32), - Int64Ty(C, 64) { } + Int64Ty(C, 64), + AlwaysOpaqueTy(new OpaqueType(C)) { + // Make sure the AlwaysOpaqueTy stays alive as long as the Context. + AlwaysOpaqueTy->addRef(); + OpaqueTypes.insert(AlwaysOpaqueTy); + } ~LLVMContextImpl() { ExprConstants.freeConstants(); @@ -217,6 +225,7 @@ public: delete I->second; } MDNodeSet.clear(); + AlwaysOpaqueTy->dropRef(); for (OpaqueTypesTy::iterator I = OpaqueTypes.begin(), E = OpaqueTypes.end(); I != E; ++I) { (*I)->AbstractTypeUsers.clear(); diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 044de4fb393..cf851987df8 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -507,30 +507,7 @@ void DerivedType::dropAllTypeUses() { if (NumContainedTys != 0) { // The type must stay abstract. To do this, we insert a pointer to a type // that will never get resolved, thus will always be abstract. - static Type *AlwaysOpaqueTy = 0; - static PATypeHolder* Holder = 0; - Type *tmp = AlwaysOpaqueTy; - if (llvm_is_multithreaded()) { - sys::MemoryFence(); - if (!tmp) { - llvm_acquire_global_lock(); - tmp = AlwaysOpaqueTy; - if (!tmp) { - tmp = OpaqueType::get(getContext()); - PATypeHolder* tmp2 = new PATypeHolder(tmp); - sys::MemoryFence(); - AlwaysOpaqueTy = tmp; - Holder = tmp2; - } - - llvm_release_global_lock(); - } - } else if (!AlwaysOpaqueTy) { - AlwaysOpaqueTy = OpaqueType::get(getContext()); - Holder = new PATypeHolder(AlwaysOpaqueTy); - } - - ContainedTys[0] = AlwaysOpaqueTy; + ContainedTys[0] = getContext().pImpl->AlwaysOpaqueTy; // Change the rest of the types to be Int32Ty's. It doesn't matter what we // pick so long as it doesn't point back to this type. We choose something diff --git a/unittests/VMCore/DerivedTypesTest.cpp b/unittests/VMCore/DerivedTypesTest.cpp index 11b4dffb5f4..2e0450d6e5c 100644 --- a/unittests/VMCore/DerivedTypesTest.cpp +++ b/unittests/VMCore/DerivedTypesTest.cpp @@ -18,14 +18,16 @@ namespace { TEST(OpaqueTypeTest, RegisterWithContext) { LLVMContext C; - LLVMContextImpl *pImpl = C.pImpl; + LLVMContextImpl *pImpl = C.pImpl; - EXPECT_EQ(0u, pImpl->OpaqueTypes.size()); + // 1 refers to the AlwaysOpaqueTy allocated in the Context's constructor and + // destroyed in the destructor. + EXPECT_EQ(1u, pImpl->OpaqueTypes.size()); { PATypeHolder Type = OpaqueType::get(C); - EXPECT_EQ(1u, pImpl->OpaqueTypes.size()); + EXPECT_EQ(2u, pImpl->OpaqueTypes.size()); } - EXPECT_EQ(0u, pImpl->OpaqueTypes.size()); + EXPECT_EQ(1u, pImpl->OpaqueTypes.size()); } } // namespace