From 9e2579dbf434e996b3d35f27b5a1762019cf27bb Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 1 Mar 2021 13:55:17 -0800 Subject: Fix infinite recursion during IR emission if a constant-initialized lifetime-extended temporary object's initializer refers back to the same object. `GetAddrOfGlobalTemporary` previously tried to emit the initializer of a global temporary before updating the global temporary map. Emitting the initializer could recurse back into `GetAddrOfGlobalTemporary` for the same temporary, resulting in an infinite recursion. Reviewed By: rjmccall Differential Revision: https://reviews.llvm.org/D97733 --- clang/lib/CodeGen/CodeGenModule.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 750439dd6844..765138bc798f 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5325,8 +5325,21 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( CharUnits Align = getContext().getTypeAlignInChars(MaterializedType); - if (llvm::Constant *Slot = MaterializedGlobalTemporaryMap[E]) - return ConstantAddress(Slot, Align); + auto InsertResult = MaterializedGlobalTemporaryMap.insert({E, nullptr}); + if (!InsertResult.second) { + // We've seen this before: either we already created it or we're in the + // process of doing so. + if (!InsertResult.first->second) { + // We recursively re-entered this function, probably during emission of + // the initializer. Create a placeholder. We'll clean this up in the + // outer call, at the end of this function. + llvm::Type *Type = getTypes().ConvertTypeForMem(MaterializedType); + InsertResult.first->second = new llvm::GlobalVariable( + getModule(), Type, false, llvm::GlobalVariable::InternalLinkage, + nullptr); + } + return ConstantAddress(InsertResult.first->second, Align); + } // FIXME: If an externally-visible declaration extends multiple temporaries, // we need to give each temporary the same name in every translation unit (and @@ -5405,7 +5418,17 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( *this, GV, AddrSpace, LangAS::Default, Type->getPointerTo( getContext().getTargetAddressSpace(LangAS::Default))); - MaterializedGlobalTemporaryMap[E] = CV; + + // Update the map with the new temporary. If we created a placeholder above, + // replace it with the new global now. + llvm::Constant *&Entry = MaterializedGlobalTemporaryMap[E]; + if (Entry) { + Entry->replaceAllUsesWith( + llvm::ConstantExpr::getBitCast(CV, Entry->getType())); + llvm::cast(Entry)->eraseFromParent(); + } + Entry = CV; + return ConstantAddress(CV, Align); } -- cgit v1.2.3