diff options
| author | Richard Smith <richard@metafoo.co.uk> | 2021-03-01 13:55:17 -0800 |
|---|---|---|
| committer | Richard Smith <richard@metafoo.co.uk> | 2021-03-01 22:19:21 -0800 |
| commit | 9e2579dbf434e996b3d35f27b5a1762019cf27bb (patch) | |
| tree | bd2f5a5d4ee95b846451292514eecf0a7ead7dcf /clang/lib/CodeGen/CodeGenModule.cpp | |
| parent | 6d2fd3d9cdd6ed24784ec47741e7e70c236a140e (diff) | |
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
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 29 |
1 files changed, 26 insertions, 3 deletions
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<llvm::GlobalVariable>(Entry)->eraseFromParent(); + } + Entry = CV; + return ConstantAddress(CV, Align); } |
