Skip to content

Commit 2bed2a7

Browse files
authored
[clang][Interp] Emit dummy values for unknown C variables (#66749)
We can't load anything from them, but we can still take their address or return them as lvalues.
1 parent 116a1ae commit 2bed2a7

File tree

5 files changed

+27
-15
lines changed

5 files changed

+27
-15
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,9 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
25472547
// Retry.
25482548
return this->VisitDeclRefExpr(E);
25492549
}
2550+
2551+
if (std::optional<unsigned> I = P.getOrCreateDummy(D))
2552+
return this->emitGetPtrGlobal(*I, E);
25502553
}
25512554

25522555
return this->emitInvalidDeclRef(E, E);

clang/lib/AST/Interp/Interp.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
139139
if (!Ptr.isExtern())
140140
return true;
141141

142-
if (!S.checkingPotentialConstantExpression()) {
142+
if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
143143
const auto *VD = Ptr.getDeclDesc()->asValueDecl();
144144
const SourceInfo &Loc = S.Current->getSource(OpPC);
145145
S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;

clang/lib/AST/Interp/Program.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,16 @@ std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
138138
return std::nullopt;
139139
}
140140

141-
std::optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
142-
141+
std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *PD) {
143142
// Dedup blocks since they are immutable and pointers cannot be compared.
144143
if (auto It = DummyParams.find(PD);
145144
It != DummyParams.end())
146145
return It->second;
147146

148-
auto &ASTCtx = Ctx.getASTContext();
149147
// Create a pointer to an incomplete array of the specified elements.
150-
QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
151-
QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
148+
QualType ElemTy = PD->getType();
149+
QualType Ty =
150+
Ctx.getASTContext().getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
152151

153152
if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
154153
DummyParams[PD] = *Idx;

clang/lib/AST/Interp/Program.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ class Program final {
8282
std::optional<unsigned> getOrCreateGlobal(const ValueDecl *VD,
8383
const Expr *Init = nullptr);
8484

85-
/// Returns or creates a dummy value for parameters.
86-
std::optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD);
85+
/// Returns or creates a dummy value for unknown declarations.
86+
std::optional<unsigned> getOrCreateDummy(const ValueDecl *PD);
8787

8888
/// Creates a global and returns its index.
8989
std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *E);
@@ -208,7 +208,7 @@ class Program final {
208208
llvm::DenseMap<const RecordDecl *, Record *> Records;
209209

210210
/// Dummy parameter to generate pointers from.
211-
llvm::DenseMap<const ParmVarDecl *, unsigned> DummyParams;
211+
llvm::DenseMap<const ValueDecl *, unsigned> DummyParams;
212212

213213
/// Creates a new descriptor.
214214
template <typename... Ts>

clang/test/AST/Interp/c.c

+16-6
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,25 @@ const int b = 3;
2828
_Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
2929
// pedantic-expected-warning {{not an integer constant expression}}
3030

31+
/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics.
3132
const int c; // ref-note {{declared here}} \
32-
// pedantic-ref-note {{declared here}} \
33-
// expected-note {{declared here}} \
34-
// pedantic-expected-note {{declared here}}
33+
// pedantic-ref-note {{declared here}}
3534
_Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \
3635
// ref-note {{initializer of 'c' is unknown}} \
3736
// pedantic-ref-error {{not an integral constant expression}} \
3837
// pedantic-ref-note {{initializer of 'c' is unknown}} \
3938
// expected-error {{not an integral constant expression}} \
40-
// expected-note {{initializer of 'c' is unknown}} \
41-
// pedantic-expected-error {{not an integral constant expression}} \
42-
// pedantic-expected-note {{initializer of 'c' is unknown}}
39+
// pedantic-expected-error {{not an integral constant expression}}
40+
41+
_Static_assert(&c != 0, ""); // ref-warning {{always true}} \
42+
// pedantic-ref-warning {{always true}} \
43+
// pedantic-ref-warning {{is a GNU extension}} \
44+
// expected-warning {{always true}} \
45+
// pedantic-expected-warning {{always true}} \
46+
// pedantic-expected-warning {{is a GNU extension}}
47+
_Static_assert(&a != 0, ""); // ref-warning {{always true}} \
48+
// pedantic-ref-warning {{always true}} \
49+
// pedantic-ref-warning {{is a GNU extension}} \
50+
// expected-warning {{always true}} \
51+
// pedantic-expected-warning {{always true}} \
52+
// pedantic-expected-warning {{is a GNU extension}}

0 commit comments

Comments
 (0)