[clang][bytecode] Create global variables for temporaries... (#195037)
... that are extended by other global variables.
If the temporary we create is extended by a variable that we index as a
global, create a global for the temporary, even if it's not an
`SD_Static` temporary.
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 626068c..9b18155 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3231,23 +3231,32 @@
// FIXME: Find a test case where Adjustments matters.
- // When we're initializing a global variable *or* the storage duration of
+ // When we're extending a global variable *or* the storage duration of
// the temporary is explicitly static, create a global variable.
OptPrimType InnerT = classify(Inner);
- if (E->getStorageDuration() == SD_Static) {
+ const ValueDecl *ExtendingDecl = E->getExtendingDecl();
+ bool IsStatic = E->getStorageDuration() == SD_Static;
+ if (IsStatic ||
+ (ExtendingDecl && Context::shouldBeGloballyIndexed(ExtendingDecl))) {
UnsignedOrNone GlobalIndex = P.createGlobal(E, Inner->getType());
if (!GlobalIndex)
return false;
const LifetimeExtendedTemporaryDecl *TempDecl =
E->getLifetimeExtendedTemporaryDecl();
- assert(TempDecl);
if (InnerT) {
if (!this->visit(Inner))
return false;
- if (!this->emitInitGlobalTemp(*InnerT, *GlobalIndex, TempDecl, E))
- return false;
+
+ if (IsStatic) {
+ assert(TempDecl);
+ if (!this->emitInitGlobalTemp(*InnerT, *GlobalIndex, TempDecl, E))
+ return false;
+ } else {
+ if (!this->emitInitGlobal(*InnerT, *GlobalIndex, E))
+ return false;
+ }
return this->emitGetPtrGlobal(*GlobalIndex, E);
}
@@ -3258,7 +3267,11 @@
return false;
if (!this->visitInitializer(Inner))
return false;
- return this->emitInitGlobalTempComp(TempDecl, E);
+ if (IsStatic) {
+ assert(TempDecl);
+ return this->emitInitGlobalTempComp(TempDecl, E);
+ }
+ return true;
}
ScopeKind VarScope = E->getStorageDuration() == SD_FullExpression
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index f0a41c1..97fa176 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1949,6 +1949,16 @@
static_assert(test_dynamic(false));
static_assert(test_dynamic(true)); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}
+
+
+ void LocalGlobal() {
+ constexpr const int &temp = 0; // both-error {{must be initialized by a constant expression}} \
+ // both-note {{reference to temporary is not a constant expression}} \
+ // both-note {{temporary created here}} \
+ // ref-note {{declared here}}
+ static_assert(__builtin_is_within_lifetime(&temp)); // ref-error {{not an integral constant expression}} \
+ // ref-note {{initializer of 'temp' is not a constant expression}}
+ }
}
#ifdef __SIZEOF_INT128__
diff --git a/clang/test/AST/ByteCode/references.cpp b/clang/test/AST/ByteCode/references.cpp
index 3da3996a..a4a8100 100644
--- a/clang/test/AST/ByteCode/references.cpp
+++ b/clang/test/AST/ByteCode/references.cpp
@@ -188,9 +188,10 @@
constexpr S s = {&x}; // both-error {{must be initialized by a constant expression}} \
// both-note {{reference to temporary}} \
// both-note {{created here}} \
- // ref-note {{declared here}}
+ // ref-note {{declared here}} \
+ // expected-note {{created here}}
static_assert(s.t == &x, ""); // both-error {{not an integral constant expression}} \
- // expected-note {{read of dereferenced null pointer}} \
+ // expected-note {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}} \
// ref-note {{initializer of 's' is not a constant expression}}
}
}