summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard@metafoo.co.uk>2021-03-01 13:55:17 -0800
committerRichard Smith <richard@metafoo.co.uk>2021-03-01 22:19:21 -0800
commit9e2579dbf434e996b3d35f27b5a1762019cf27bb (patch)
treebd2f5a5d4ee95b846451292514eecf0a7ead7dcf /clang/lib/CodeGen/CodeGenModule.cpp
parent6d2fd3d9cdd6ed24784ec47741e7e70c236a140e (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.cpp29
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);
}