Skip to content

Commit b945bf2

Browse files
committed
[clang][Interp] Fall back to dummy pointers if createGlobal() fails
createGlobal fails e.g. if the type isn't complete.
1 parent fd7d788 commit b945bf2

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3617,7 +3617,7 @@ VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) {
36173617

36183618
auto R = this->visitVarDecl(VD, /*Toplevel=*/true);
36193619

3620-
if (R.notCreated())
3620+
if (R.notCreated() || R.dummyCreated())
36213621
return R;
36223622

36233623
if (R)
@@ -3709,7 +3709,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve
37093709
// This case is EvalEmitter-only. If we won't create any instructions for the
37103710
// initializer anyway, don't bother creating the variable in the first place.
37113711
if (!this->isActive())
3712-
return VarCreationState::NotCreated();
3712+
return VarCreationState::NotCreated;
37133713

37143714
const Expr *Init = VD->getInit();
37153715
std::optional<PrimType> VarT = classify(VD->getType());
@@ -3759,12 +3759,16 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve
37593759
return Init && checkDecl() && initGlobal(*GlobalIndex);
37603760
}
37613761

3762-
std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);
3762+
if (std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init))
3763+
return !Init || (checkDecl() && initGlobal(*GlobalIndex));
37633764

3764-
if (!GlobalIndex)
3765-
return false;
3765+
if (std::optional<unsigned> I = P.getOrCreateDummy(VD)) {
3766+
if (!this->emitGetPtrGlobal(*I, VD))
3767+
return false;
3768+
return VarCreationState::DummyCreated;
3769+
}
37663770

3767-
return !Init || (checkDecl() && initGlobal(*GlobalIndex));
3771+
return false;
37683772
} else {
37693773
InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));
37703774

@@ -5240,7 +5244,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
52405244
auto revisit = [&](const VarDecl *VD) -> bool {
52415245
auto VarState = this->visitDecl(VD);
52425246

5243-
if (VarState.notCreated())
5247+
if (VarState.notCreated() || VarState.dummyCreated())
52445248
return true;
52455249
if (!VarState)
52465250
return false;

clang/lib/AST/Interp/Compiler.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,14 @@ struct InitLink {
8989
/// State encapsulating if a the variable creation has been successful,
9090
/// unsuccessful, or no variable has been created at all.
9191
struct VarCreationState {
92-
std::optional<bool> S = std::nullopt;
92+
enum SS { Failure = 0, Success = 1, NotCreated, DummyCreated } S;
9393
VarCreationState() = default;
94-
VarCreationState(bool b) : S(b) {}
95-
static VarCreationState NotCreated() { return VarCreationState(); }
94+
VarCreationState(SS b) : S(b) {}
95+
VarCreationState(bool b) : S(b ? Success : Failure) {}
9696

97-
operator bool() const { return S && *S; }
98-
bool notCreated() const { return !S; }
97+
operator bool() const { return S == Success; }
98+
bool notCreated() const { return S == NotCreated; }
99+
bool dummyCreated() const { return S == DummyCreated; }
99100
};
100101

101102
/// Compilation context for expressions.

clang/test/AST/Interp/records.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,3 +1576,13 @@ namespace ctorOverrider {
15761576
constexpr Covariant1 cb;
15771577
}
15781578
#endif
1579+
1580+
namespace IncompleteStaticStructMember {
1581+
struct Foo;
1582+
struct Bar {
1583+
static const Foo x;
1584+
static const Foo y;
1585+
};
1586+
static_assert(&Bar::x != nullptr, ""); // both-warning {{always true}}
1587+
static_assert(&Bar::x != &Bar::y, "");
1588+
}

0 commit comments

Comments
 (0)