[clang] [clang][Interp] Emit dummy values for unknown C variables (PR #66749)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 19 01:27:30 PDT 2023
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/66749
We can't load anything from them, but we can still take their address or return them as lvalues.
>From 9952d03bf25766ada5a41c13c3be45f9bd1e8bf2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 19 Sep 2023 08:47:01 +0200
Subject: [PATCH] [clang][Interp] Emit dummy values for unknown C variables
We can't load anything from them, but we can still take their address or
return them as lvalues.
---
clang/lib/AST/Interp/ByteCodeExprGen.cpp | 3 +++
clang/lib/AST/Interp/Interp.cpp | 2 +-
clang/lib/AST/Interp/Program.cpp | 9 ++++-----
clang/lib/AST/Interp/Program.h | 4 ++--
clang/test/AST/Interp/c.c | 22 ++++++++++++++++------
5 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index c813f9b6d9991c5..24d4991a0308097 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2493,6 +2493,9 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
// Retry.
return this->VisitDeclRefExpr(E);
}
+
+ if (std::optional<unsigned> I = P.getOrCreateDummy(D))
+ return this->emitGetPtrGlobal(*I, E);
}
return this->emitInvalidDeclRef(E, E);
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index e1951574edb6288..4f2d120407e942a 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -139,7 +139,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!Ptr.isExtern())
return true;
- if (!S.checkingPotentialConstantExpression()) {
+ if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
const auto *VD = Ptr.getDeclDesc()->asValueDecl();
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp
index 63901d90703dc46..65e170881e313d7 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -138,17 +138,16 @@ std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
return std::nullopt;
}
-std::optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
-
+std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *PD) {
// Dedup blocks since they are immutable and pointers cannot be compared.
if (auto It = DummyParams.find(PD);
It != DummyParams.end())
return It->second;
- auto &ASTCtx = Ctx.getASTContext();
// Create a pointer to an incomplete array of the specified elements.
- QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
- QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
+ QualType ElemTy = PD->getType();
+ QualType Ty =
+ Ctx.getASTContext().getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
DummyParams[PD] = *Idx;
diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h
index d880a738e733e31..f21b908f5bbd23d 100644
--- a/clang/lib/AST/Interp/Program.h
+++ b/clang/lib/AST/Interp/Program.h
@@ -83,7 +83,7 @@ class Program final {
const Expr *Init = nullptr);
/// Returns or creates a dummy value for parameters.
- std::optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD);
+ std::optional<unsigned> getOrCreateDummy(const ValueDecl *PD);
/// Creates a global and returns its index.
std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *E);
@@ -208,7 +208,7 @@ class Program final {
llvm::DenseMap<const RecordDecl *, Record *> Records;
/// Dummy parameter to generate pointers from.
- llvm::DenseMap<const ParmVarDecl *, unsigned> DummyParams;
+ llvm::DenseMap<const ValueDecl *, unsigned> DummyParams;
/// Creates a new descriptor.
template <typename... Ts>
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index c0ec5f8339dd1d7..24ece8f26399031 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -24,15 +24,25 @@ const int b = 3;
_Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
// pedantic-expected-warning {{not an integer constant expression}}
+/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics.
const int c; // ref-note {{declared here}} \
- // pedantic-ref-note {{declared here}} \
- // expected-note {{declared here}} \
- // pedantic-expected-note {{declared here}}
+ // pedantic-ref-note {{declared here}}
_Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \
// ref-note {{initializer of 'c' is unknown}} \
// pedantic-ref-error {{not an integral constant expression}} \
// pedantic-ref-note {{initializer of 'c' is unknown}} \
// expected-error {{not an integral constant expression}} \
- // expected-note {{initializer of 'c' is unknown}} \
- // pedantic-expected-error {{not an integral constant expression}} \
- // pedantic-expected-note {{initializer of 'c' is unknown}}
+ // pedantic-expected-error {{not an integral constant expression}}
+
+_Static_assert(&c != 0, ""); // ref-warning {{always true}} \
+ // pedantic-ref-warning {{always true}} \
+ // pedantic-ref-warning {{is a GNU extension}} \
+ // expected-warning {{always true}} \
+ // pedantic-expected-warning {{always true}} \
+ // pedantic-expected-warning {{is a GNU extension}}
+_Static_assert(&a != 0, ""); // ref-warning {{always true}} \
+ // pedantic-ref-warning {{always true}} \
+ // pedantic-ref-warning {{is a GNU extension}} \
+ // expected-warning {{always true}} \
+ // pedantic-expected-warning {{always true}} \
+ // pedantic-expected-warning {{is a GNU extension}}
More information about the cfe-commits
mailing list