diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h index 1bfb26b1b669f9..23f72860367646 100644 --- a/clang/lib/AST/Interp/Boolean.h +++ b/clang/lib/AST/Interp/Boolean.h @@ -56,7 +56,7 @@ class Boolean final { APSInt toAPSInt(unsigned NumBits) const { return APSInt(toAPSInt().zextOrTrunc(NumBits), true); } - APValue toAPValue() const { return APValue(toAPSInt()); } + APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); } Boolean toUnsigned() const { return *this; } diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp index c6c62755930070..867284ecf7f4bd 100644 --- a/clang/lib/AST/Interp/Disasm.cpp +++ b/clang/lib/AST/Interp/Disasm.cpp @@ -366,9 +366,9 @@ LLVM_DUMP_METHOD void EvaluationResult::dump() const { OS << "LValue: "; if (const auto *P = std::get_if(&Value)) - P->toAPValue().printPretty(OS, ASTCtx, SourceType); + P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType); else if (const auto *FP = std::get_if(&Value)) // Nope - FP->toAPValue().printPretty(OS, ASTCtx, SourceType); + FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType); OS << "\n"; break; } diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp index 221bbfdc542ff2..08536536ac3c2e 100644 --- a/clang/lib/AST/Interp/EvalEmitter.cpp +++ b/clang/lib/AST/Interp/EvalEmitter.cpp @@ -145,7 +145,7 @@ template bool EvalEmitter::emitRet(const SourceInfo &Info) { return false; using T = typename PrimConv::T; - EvalResult.setValue(S.Stk.pop().toAPValue()); + EvalResult.setValue(S.Stk.pop().toAPValue(Ctx.getASTContext())); return true; } @@ -181,7 +181,7 @@ template <> bool EvalEmitter::emitRet(const SourceInfo &Info) { return false; } } else { - EvalResult.setValue(Ptr.toAPValue()); + EvalResult.setValue(Ptr.toAPValue(Ctx.getASTContext())); } return true; @@ -285,7 +285,8 @@ void EvalEmitter::updateGlobalTemporaries() { APValue *Cached = Temp->getOrCreateValue(true); if (std::optional T = Ctx.classify(E->getType())) { - TYPE_SWITCH(*T, { *Cached = Ptr.deref().toAPValue(); }); + TYPE_SWITCH( + *T, { *Cached = Ptr.deref().toAPValue(Ctx.getASTContext()); }); } else { if (std::optional APV = Ptr.toRValue(Ctx, Temp->getTemporaryExpr()->getType())) diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index 0bebfd4ad984e1..1b255711c7b362 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -21,9 +21,9 @@ APValue EvaluationResult::toAPValue() const { case LValue: // Either a pointer or a function pointer. if (const auto *P = std::get_if(&Value)) - return P->toAPValue(); + return P->toAPValue(Ctx->getASTContext()); else if (const auto *FP = std::get_if(&Value)) - return FP->toAPValue(); + return FP->toAPValue(Ctx->getASTContext()); else llvm_unreachable("Unhandled LValue type"); break; @@ -46,7 +46,7 @@ std::optional EvaluationResult::toRValue() const { if (const auto *P = std::get_if(&Value)) return P->toRValue(*Ctx, getSourceType()); else if (const auto *FP = std::get_if(&Value)) // Nope - return FP->toAPValue(); + return FP->toAPValue(Ctx->getASTContext()); llvm_unreachable("Unhandled lvalue kind"); } diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h index e4ac76d8509fb8..114487821880fb 100644 --- a/clang/lib/AST/Interp/Floating.h +++ b/clang/lib/AST/Interp/Floating.h @@ -69,7 +69,7 @@ class Floating final { APSInt toAPSInt(unsigned NumBits = 0) const { return APSInt(F.bitcastToAPInt()); } - APValue toAPValue() const { return APValue(F); } + APValue toAPValue(const ASTContext &) const { return APValue(F); } void print(llvm::raw_ostream &OS) const { // Can't use APFloat::print() since it appends a newline. SmallVector Buffer; diff --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/Interp/FunctionPointer.h index fc3d7a4214a72b..0f2c6e571a1d8c 100644 --- a/clang/lib/AST/Interp/FunctionPointer.h +++ b/clang/lib/AST/Interp/FunctionPointer.h @@ -40,7 +40,7 @@ class FunctionPointer final { return Func->getDecl()->isWeak(); } - APValue toAPValue() const { + APValue toAPValue(const ASTContext &) const { if (!Func) return APValue(static_cast(nullptr), CharUnits::Zero(), {}, /*OnePastTheEnd=*/false, /*IsNull=*/true); @@ -69,7 +69,7 @@ class FunctionPointer final { if (!Func) return "nullptr"; - return toAPValue().getAsString(Ctx, Func->getDecl()->getType()); + return toAPValue(Ctx).getAsString(Ctx, Func->getDecl()->getType()); } uint64_t getIntegerRepresentation() const { diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h index db4cc9ae45b491..aafdd02676c966 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -112,7 +112,7 @@ template class Integral final { else return APSInt(toAPSInt().zextOrTrunc(NumBits), !Signed); } - APValue toAPValue() const { return APValue(toAPSInt()); } + APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); } Integral toUnsigned() const { return Integral(*this); diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index 7464f15cdb03b4..b8aa21038256c7 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -133,7 +133,7 @@ template class IntegralAP final { else return APSInt(V.zext(Bits), !Signed); } - APValue toAPValue() const { return APValue(toAPSInt()); } + APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); } bool isZero() const { return V.isZero(); } bool isPositive() const { return V.isNonNegative(); } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index f86b787fb034e7..b2581b5f7b5d01 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -39,8 +39,9 @@ namespace interp { using APSInt = llvm::APSInt; /// Convert a value to an APValue. -template bool ReturnValue(const T &V, APValue &R) { - R = V.toAPValue(); +template +bool ReturnValue(const InterpState &S, const T &V, APValue &R) { + R = V.toAPValue(S.getCtx()); return true; } @@ -286,7 +287,7 @@ bool Ret(InterpState &S, CodePtr &PC, APValue &Result) { } else { delete S.Current; S.Current = nullptr; - if (!ReturnValue(Ret, Result)) + if (!ReturnValue(S, Ret, Result)) return false; } return true; @@ -1318,7 +1319,7 @@ bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I, const Pointer &Ptr = S.P.getGlobal(I); const T Value = S.Stk.peek(); - APValue APV = Value.toAPValue(); + APValue APV = Value.toAPValue(S.getCtx()); APValue *Cached = Temp->getOrCreateValue(true); *Cached = APV; diff --git a/clang/lib/AST/Interp/MemberPointer.cpp b/clang/lib/AST/Interp/MemberPointer.cpp index 96f63643e83c98..0c1b6edc5f7e10 100644 --- a/clang/lib/AST/Interp/MemberPointer.cpp +++ b/clang/lib/AST/Interp/MemberPointer.cpp @@ -60,13 +60,13 @@ FunctionPointer MemberPointer::toFunctionPointer(const Context &Ctx) const { return FunctionPointer(Ctx.getProgram().getFunction(cast(Dcl))); } -APValue MemberPointer::toAPValue() const { +APValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const { if (isZero()) return APValue(static_cast(nullptr), /*IsDerivedMember=*/false, /*Path=*/{}); if (hasBase()) - return Base.toAPValue(); + return Base.toAPValue(ASTCtx); return APValue(cast(getDecl()), /*IsDerivedMember=*/false, /*Path=*/{}); diff --git a/clang/lib/AST/Interp/MemberPointer.h b/clang/lib/AST/Interp/MemberPointer.h index f56dc530431e46..2b3be124db4267 100644 --- a/clang/lib/AST/Interp/MemberPointer.h +++ b/clang/lib/AST/Interp/MemberPointer.h @@ -80,7 +80,7 @@ class MemberPointer final { return MemberPointer(Instance, this->Dcl, this->PtrOffset); } - APValue toAPValue() const; + APValue toAPValue(const ASTContext &) const; bool isZero() const { return Base.isZero() && !Dcl; } bool hasBase() const { return !Base.isZero(); } diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index b22b4b1918ba51..f7bd76b260584e 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -119,7 +119,7 @@ void Pointer::operator=(Pointer &&P) { } } -APValue Pointer::toAPValue() const { +APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { llvm::SmallVector Path; if (isZero()) @@ -220,7 +220,7 @@ std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const { if (isIntegralPointer()) return (Twine("&(") + Twine(asIntPointer().Value + Offset) + ")").str(); - return toAPValue().getAsString(Ctx, getType()); + return toAPValue(Ctx).getAsString(Ctx, getType()); } bool Pointer::isInitialized() const { @@ -344,10 +344,12 @@ bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) { std::optional Pointer::toRValue(const Context &Ctx, QualType ResultType) const { + const ASTContext &ASTCtx = Ctx.getASTContext(); assert(!ResultType.isNull()); // Method to recursively traverse composites. std::function Composite; - Composite = [&Composite, &Ctx](QualType Ty, const Pointer &Ptr, APValue &R) { + Composite = [&Composite, &Ctx, &ASTCtx](QualType Ty, const Pointer &Ptr, + APValue &R) { if (const auto *AT = Ty->getAs()) Ty = AT->getValueType(); @@ -358,7 +360,7 @@ std::optional Pointer::toRValue(const Context &Ctx, // Primitive values. if (std::optional T = Ctx.classify(Ty)) { - TYPE_SWITCH(*T, R = Ptr.deref().toAPValue()); + TYPE_SWITCH(*T, R = Ptr.deref().toAPValue(ASTCtx)); return true; } @@ -375,7 +377,7 @@ std::optional Pointer::toRValue(const Context &Ctx, QualType FieldTy = F.Decl->getType(); if (FP.isActive()) { if (std::optional T = Ctx.classify(FieldTy)) { - TYPE_SWITCH(*T, Value = FP.deref().toAPValue()); + TYPE_SWITCH(*T, Value = FP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(FieldTy, FP, Value); } @@ -398,7 +400,7 @@ std::optional Pointer::toRValue(const Context &Ctx, APValue &Value = R.getStructField(I); if (std::optional T = Ctx.classify(FieldTy)) { - TYPE_SWITCH(*T, Value = FP.deref().toAPValue()); + TYPE_SWITCH(*T, Value = FP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(FieldTy, FP, Value); } @@ -436,7 +438,7 @@ std::optional Pointer::toRValue(const Context &Ctx, APValue &Slot = R.getArrayInitializedElt(I); const Pointer &EP = Ptr.atIndex(I); if (std::optional T = Ctx.classify(ElemTy)) { - TYPE_SWITCH(*T, Slot = EP.deref().toAPValue()); + TYPE_SWITCH(*T, Slot = EP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(ElemTy, EP.narrow(), Slot); } @@ -475,7 +477,7 @@ std::optional Pointer::toRValue(const Context &Ctx, Values.reserve(VT->getNumElements()); for (unsigned I = 0; I != VT->getNumElements(); ++I) { TYPE_SWITCH(ElemT, { - Values.push_back(Ptr.atIndex(I).deref().toAPValue()); + Values.push_back(Ptr.atIndex(I).deref().toAPValue(ASTCtx)); }); } @@ -493,11 +495,11 @@ std::optional Pointer::toRValue(const Context &Ctx, // We can return these as rvalues, but we can't deref() them. if (isZero() || isIntegralPointer()) - return toAPValue(); + return toAPValue(ASTCtx); // Just load primitive types. if (std::optional T = Ctx.classify(ResultType)) { - TYPE_SWITCH(*T, return this->deref().toAPValue()); + TYPE_SWITCH(*T, return this->deref().toAPValue(ASTCtx)); } // Return the composite type. diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index 972f55a553f6e8..7fa6a3230a4f95 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -118,7 +118,7 @@ class Pointer { bool operator!=(const Pointer &P) const { return !(P == *this); } /// Converts the pointer to an APValue. - APValue toAPValue() const; + APValue toAPValue(const ASTContext &ASTCtx) const; /// Converts the pointer to a string usable in diagnostics. std::string toDiagnosticString(const ASTContext &Ctx) const; diff --git a/clang/unittests/AST/Interp/toAPValue.cpp b/clang/unittests/AST/Interp/toAPValue.cpp index d6879d6e0bca36..5ec607a8243492 100644 --- a/clang/unittests/AST/Interp/toAPValue.cpp +++ b/clang/unittests/AST/Interp/toAPValue.cpp @@ -27,6 +27,7 @@ TEST(ToAPValue, Pointers) { auto AST = tooling::buildASTFromCodeWithArgs( Code, {"-fexperimental-new-constant-interpreter"}); + auto &ASTCtx = AST->getASTContext(); auto &Ctx = AST->getASTContext().getInterpContext(); Program &Prog = Ctx.getProgram(); @@ -47,7 +48,7 @@ TEST(ToAPValue, Pointers) { const Pointer &GP = getGlobalPtr("b"); const Pointer &P = GP.deref(); ASSERT_TRUE(P.isLive()); - APValue A = P.toAPValue(); + APValue A = P.toAPValue(ASTCtx); ASSERT_TRUE(A.isLValue()); ASSERT_TRUE(A.hasLValuePath()); const auto &Path = A.getLValuePath(); @@ -62,7 +63,7 @@ TEST(ToAPValue, Pointers) { const Pointer &GP = getGlobalPtr("p"); const Pointer &P = GP.deref(); ASSERT_TRUE(P.isIntegralPointer()); - APValue A = P.toAPValue(); + APValue A = P.toAPValue(ASTCtx); ASSERT_TRUE(A.isLValue()); ASSERT_TRUE(A.getLValueBase().isNull()); APSInt I; @@ -77,7 +78,7 @@ TEST(ToAPValue, Pointers) { const Pointer &GP = getGlobalPtr("nullp"); const Pointer &P = GP.deref(); ASSERT_TRUE(P.isIntegralPointer()); - APValue A = P.toAPValue(); + APValue A = P.toAPValue(ASTCtx); ASSERT_TRUE(A.isLValue()); ASSERT_TRUE(A.getLValueBase().isNull()); ASSERT_TRUE(A.isNullPointer()); @@ -96,6 +97,7 @@ TEST(ToAPValue, FunctionPointers) { auto AST = tooling::buildASTFromCodeWithArgs( Code, {"-fexperimental-new-constant-interpreter"}); + auto &ASTCtx = AST->getASTContext(); auto &Ctx = AST->getASTContext().getInterpContext(); Program &Prog = Ctx.getProgram(); @@ -117,7 +119,7 @@ TEST(ToAPValue, FunctionPointers) { const Pointer &GP = getGlobalPtr("func"); const FunctionPointer &FP = GP.deref(); ASSERT_FALSE(FP.isZero()); - APValue A = FP.toAPValue(); + APValue A = FP.toAPValue(ASTCtx); ASSERT_TRUE(A.hasValue()); ASSERT_TRUE(A.isLValue()); ASSERT_TRUE(A.hasLValuePath()); @@ -132,7 +134,7 @@ TEST(ToAPValue, FunctionPointers) { ASSERT_NE(D, nullptr); const Pointer &GP = getGlobalPtr("nullp"); const auto &P = GP.deref(); - APValue A = P.toAPValue(); + APValue A = P.toAPValue(ASTCtx); ASSERT_TRUE(A.isLValue()); ASSERT_TRUE(A.getLValueBase().isNull()); ASSERT_TRUE(A.isNullPointer()); @@ -151,6 +153,7 @@ TEST(ToAPValue, FunctionPointersC) { auto AST = tooling::buildASTFromCodeWithArgs( Code, {"-x", "c", "-fexperimental-new-constant-interpreter"}); + auto &ASTCtx = AST->getASTContext(); auto &Ctx = AST->getASTContext().getInterpContext(); Program &Prog = Ctx.getProgram(); @@ -174,7 +177,7 @@ TEST(ToAPValue, FunctionPointersC) { ASSERT_TRUE(GP.isLive()); const FunctionPointer &FP = GP.deref(); ASSERT_FALSE(FP.isZero()); - APValue A = FP.toAPValue(); + APValue A = FP.toAPValue(ASTCtx); ASSERT_TRUE(A.hasValue()); ASSERT_TRUE(A.isLValue()); const auto &Path = A.getLValuePath(); @@ -197,6 +200,7 @@ TEST(ToAPValue, MemberPointers) { auto AST = tooling::buildASTFromCodeWithArgs( Code, {"-fexperimental-new-constant-interpreter"}); + auto &ASTCtx = AST->getASTContext(); auto &Ctx = AST->getASTContext().getInterpContext(); Program &Prog = Ctx.getProgram(); @@ -218,7 +222,7 @@ TEST(ToAPValue, MemberPointers) { const Pointer &GP = getGlobalPtr("pm"); ASSERT_TRUE(GP.isLive()); const MemberPointer &FP = GP.deref(); - APValue A = FP.toAPValue(); + APValue A = FP.toAPValue(ASTCtx); ASSERT_EQ(A.getMemberPointerDecl(), getDecl("m")); ASSERT_EQ(A.getKind(), APValue::MemberPointer); } @@ -228,7 +232,7 @@ TEST(ToAPValue, MemberPointers) { ASSERT_TRUE(GP.isLive()); const MemberPointer &NP = GP.deref(); ASSERT_TRUE(NP.isZero()); - APValue A = NP.toAPValue(); + APValue A = NP.toAPValue(ASTCtx); ASSERT_EQ(A.getKind(), APValue::MemberPointer); } }