[PATCH] D97733: Fix infinite recursion during IR emission if a constant-initialized lifetime-extended temporary object's initializer refers back to the same object.
Richard Smith - zygoloid via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 1 13:59:00 PST 2021
rsmith created this revision.
rsmith added a reviewer: rjmccall.
rsmith requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
`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.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D97733
Files:
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGenCXX/temporaries.cpp
Index: clang/test/CodeGenCXX/temporaries.cpp
===================================================================
--- clang/test/CodeGenCXX/temporaries.cpp
+++ clang/test/CodeGenCXX/temporaries.cpp
@@ -53,6 +53,17 @@
// CHECK: @_ZN9BraceInit1xE ={{.*}} constant i32* @_ZGRN9BraceInit1xE_
}
+namespace RefTempSubobject {
+ struct SelfReferential {
+ int *p = ints;
+ int ints[3] = {1, 2, 3};
+ };
+
+ // CHECK: @_ZGRN16RefTempSubobject2srE_ = internal global { i32*, [3 x i32] } { {{.*}} getelementptr {{.*}} @_ZGRN16RefTempSubobject2srE_ {{.*}}, [3 x i32] [i32 1, i32 2, i32 3] }
+ // CHECK: @_ZN16RefTempSubobject2srE = {{.*}} constant {{.*}} @_ZGRN16RefTempSubobject2srE_
+ constexpr const SelfReferential &sr = SelfReferential();
+}
+
struct A {
A();
~A();
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -5315,8 +5315,21 @@
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
@@ -5395,7 +5408,17 @@
*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);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D97733.327284.patch
Type: text/x-patch
Size: 2753 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210301/6a52c659/attachment.bin>
More information about the cfe-commits
mailing list