https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/66749
>From 1d36bdbd1e876adb5c39cf8e06c8387d5de1ab71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@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 | 6 +++--- clang/test/AST/Interp/c.c | 22 ++++++++++++++++------ 5 files changed, 27 insertions(+), 15 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..d843fa06538f514 100644 --- a/clang/lib/AST/Interp/Program.h +++ b/clang/lib/AST/Interp/Program.h @@ -82,8 +82,8 @@ class Program final { std::optional<unsigned> getOrCreateGlobal(const ValueDecl *VD, const Expr *Init = nullptr); - /// Returns or creates a dummy value for parameters. - std::optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD); + /// Returns or creates a dummy value for unknown declarations. + 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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits