llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> We just called `getInit()`, which isn't always correct and used the wrong initializer in the module test case. --- Full diff: https://github.com/llvm/llvm-project/pull/158056.diff 9 Files Affected: - (modified) clang/lib/AST/ByteCode/ByteCodeEmitter.h (+2-1) - (modified) clang/lib/AST/ByteCode/Compiler.cpp (+10-11) - (modified) clang/lib/AST/ByteCode/Compiler.h (+4-2) - (modified) clang/lib/AST/ByteCode/Context.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/Context.h (+2-1) - (modified) clang/lib/AST/ByteCode/EvalEmitter.cpp (+4-3) - (modified) clang/lib/AST/ByteCode/EvalEmitter.h (+4-2) - (modified) clang/lib/AST/ExprConstant.cpp (+1-1) - (modified) clang/test/Modules/added-visible-decls.cppm (+1) ``````````diff diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.h b/clang/lib/AST/ByteCode/ByteCodeEmitter.h index d29db66325412..c050b299d8f61 100644 --- a/clang/lib/AST/ByteCode/ByteCodeEmitter.h +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h @@ -46,7 +46,8 @@ class ByteCodeEmitter { /// Methods implemented by the compiler. virtual bool visitFunc(const FunctionDecl *E) = 0; virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0; - virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0; + virtual bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init, + bool ConstantContext) = 0; virtual bool visit(const Expr *E) = 0; virtual bool emitBool(bool V, const Expr *E) = 0; diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 3f7db39281358..78b74acc3789d 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -4714,7 +4714,8 @@ template <class Emitter> VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD, bool IsConstexprUnknown) { - auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown); + auto R = this->visitVarDecl(VD, VD->getInit(), /*Toplevel=*/true, + IsConstexprUnknown); if (R.notCreated()) return R; @@ -4740,14 +4741,12 @@ VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD, /// We get here from evaluateAsInitializer(). /// We need to evaluate the initializer and return its value. template <class Emitter> -bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, +bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, const Expr *Init, bool ConstantContext) { - // We only create variables if we're evaluating in a constant context. // Otherwise, just evaluate the initializer and return it. if (!ConstantContext) { DeclScope<Emitter> LS(this, VD); - const Expr *Init = VD->getInit(); if (!this->visit(Init)) return false; return this->emitRet(classify(Init).value_or(PT_Ptr), VD) && @@ -4755,7 +4754,7 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, } LocalScope<Emitter> VDScope(this, VD); - if (!this->visitVarDecl(VD, /*Toplevel=*/true)) + if (!this->visitVarDecl(VD, Init, /*Toplevel=*/true)) return false; OptPrimType VarT = classify(VD->getType()); @@ -4802,9 +4801,9 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, } template <class Emitter> -VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, - bool Toplevel, - bool IsConstexprUnknown) { +VarCreationState +Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init, + bool Toplevel, bool IsConstexprUnknown) { // We don't know what to do with these, so just return false. if (VD->getType().isNull()) return false; @@ -4814,7 +4813,6 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, if (!this->isActive()) return VarCreationState::NotCreated(); - const Expr *Init = VD->getInit(); OptPrimType VarT = classify(VD->getType()); if (Init && Init->isValueDependent()) @@ -5488,7 +5486,8 @@ template <class Emitter> bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) { if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) { for (auto *BD : DD->flat_bindings()) - if (auto *KD = BD->getHoldingVar(); KD && !this->visitVarDecl(KD)) + if (auto *KD = BD->getHoldingVar(); + KD && !this->visitVarDecl(KD, KD->getInit())) return false; } return true; @@ -5552,7 +5551,7 @@ bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS, const auto *VD = dyn_cast<VarDecl>(D); if (!VD) return false; - if (!this->visitVarDecl(VD)) + if (!this->visitVarDecl(VD, VD->getInit())) return false; // Register decomposition decl holding vars. diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index c97dc18656ce4..5f392964c076a 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -251,7 +251,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>, bool visitExpr(const Expr *E, bool DestroyToplevelScope) override; bool visitFunc(const FunctionDecl *F) override; - bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override; + bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init, + bool ConstantContext) override; protected: /// Emits scope cleanup instructions. @@ -303,7 +304,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>, /// intact. bool delegate(const Expr *E); /// Creates and initializes a variable from the given decl. - VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false, + VarCreationState visitVarDecl(const VarDecl *VD, const Expr *Init, + bool Toplevel = false, bool IsConstexprUnknown = false); VarCreationState visitDecl(const VarDecl *VD, bool IsConstexprUnknown = false); diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index 8598996681466..de3191bfcff55 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -135,7 +135,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, bool CheckGlobalInitialized = shouldBeGloballyIndexed(VD) && (VD->getType()->isRecordType() || VD->getType()->isArrayType()); - auto Res = C.interpretDecl(VD, CheckGlobalInitialized); + auto Res = C.interpretDecl(VD, Init, CheckGlobalInitialized); if (Res.isInvalid()) { C.cleanup(); Stk.clearTo(StackSizeBefore); diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h index fa98498dbe8fa..280a31725555f 100644 --- a/clang/lib/AST/ByteCode/Context.h +++ b/clang/lib/AST/ByteCode/Context.h @@ -59,7 +59,8 @@ class Context final { ConstantExprKind Kind); /// Evaluates a toplevel initializer. - bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result); + bool evaluateAsInitializer(State &Parent, const VarDecl *VD, const Expr *Init, + APValue &Result); bool evaluateCharRange(State &Parent, const Expr *SizeExpr, const Expr *PtrExpr, APValue &Result); diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp index e349397078aa3..1d73f0e247aa2 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.cpp +++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp @@ -49,14 +49,15 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E, return std::move(this->EvalResult); } -EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, +EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, const Expr *Init, bool CheckFullyInitialized) { this->CheckFullyInitialized = CheckFullyInitialized; S.EvaluatingDecl = VD; S.setEvalLocation(VD->getLocation()); EvalResult.setSource(VD); - if (const Expr *Init = VD->getAnyInitializer()) { + // FIXME: I think Init is never null. + if (Init) { QualType T = VD->getType(); this->ConvertResultToRValue = !Init->isGLValue() && !T->isPointerType() && !T->isObjCObjectPointerType(); @@ -65,7 +66,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, EvalResult.setSource(VD); - if (!this->visitDeclAndReturn(VD, S.inConstantContext())) + if (!this->visitDeclAndReturn(VD, Init, S.inConstantContext())) EvalResult.setInvalid(); S.EvaluatingDecl = nullptr; diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h b/clang/lib/AST/ByteCode/EvalEmitter.h index 85a0a99fbb4b0..e81ea67adf97a 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.h +++ b/clang/lib/AST/ByteCode/EvalEmitter.h @@ -37,7 +37,8 @@ class EvalEmitter : public SourceMapper { EvaluationResult interpretExpr(const Expr *E, bool ConvertResultToRValue = false, bool DestroyToplevelScope = false); - EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized); + EvaluationResult interpretDecl(const VarDecl *VD, const Expr *Init, + bool CheckFullyInitialized); /// Interpret the given Expr to a Pointer. EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB); /// Interpret the given expression as if it was in the body of the given @@ -59,7 +60,8 @@ class EvalEmitter : public SourceMapper { /// Methods implemented by the compiler. virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0; - virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) = 0; + virtual bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init, + bool ConstantContext) = 0; virtual bool visitFunc(const FunctionDecl *F) = 0; virtual bool visit(const Expr *E) = 0; virtual bool emitBool(bool V, const Expr *E) = 0; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5145896930153..820b053057067 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -17755,7 +17755,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, if (Info.EnableNewConstInterp) { auto &InterpCtx = const_cast<ASTContext &>(Ctx).getInterpContext(); - if (!InterpCtx.evaluateAsInitializer(Info, VD, Value)) + if (!InterpCtx.evaluateAsInitializer(Info, VD, this, Value)) return false; return CheckConstantExpression(Info, DeclLoc, DeclTy, Value, diff --git a/clang/test/Modules/added-visible-decls.cppm b/clang/test/Modules/added-visible-decls.cppm index 2f387db452905..28df3bf6f8543 100644 --- a/clang/test/Modules/added-visible-decls.cppm +++ b/clang/test/Modules/added-visible-decls.cppm @@ -5,6 +5,7 @@ // RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o %t/c.pcm -fprebuilt-module-path=%t // RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -fsyntax-only -verify +// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -fsyntax-only -verify -fexperimental-new-constant-interpreter //--- a.h template <typename T> `````````` </details> https://github.com/llvm/llvm-project/pull/158056 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits