Author: Timm Bäder Date: 2024-06-07T08:16:39+02:00 New Revision: 0b8acc06c42df9d444f669fff312fffffcacdfb9
URL: https://github.com/llvm/llvm-project/commit/0b8acc06c42df9d444f669fff312fffffcacdfb9 DIFF: https://github.com/llvm/llvm-project/commit/0b8acc06c42df9d444f669fff312fffffcacdfb9.diff LOG: [clang][Interp] Improve APValue machinery Handle lvalues pointing to declarations, unions and member pointers. Added: Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/test/AST/Interp/cxx20.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index d124248a3605f..9073175263645 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3218,9 +3218,18 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val, return this->emitConst(Val.getInt(), ValType, E); if (Val.isLValue()) { + if (Val.isNullPointer()) + return this->emitNull(ValType, nullptr, E); APValue::LValueBase Base = Val.getLValueBase(); if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>()) return this->visit(BaseExpr); + else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) { + return this->visitDeclRef(VD, E); + } + } else if (Val.isMemberPointer()) { + if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl()) + return this->emitGetMemberPtr(MemberDecl, E); + return this->emitNullMemberPtr(nullptr, E); } return false; @@ -3229,15 +3238,15 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val, template <class Emitter> bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val, const Expr *E) { + if (Val.isStruct()) { const Record *R = this->getRecord(E->getType()); assert(R); - for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) { const APValue &F = Val.getStructField(I); const Record::Field *RF = R->getField(I); - if (F.isInt() || F.isLValue()) { + if (F.isInt() || F.isLValue() || F.isMemberPointer()) { PrimType T = classifyPrim(RF->Decl->getType()); if (!this->visitAPValue(F, T, E)) return false; @@ -3263,11 +3272,30 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val, if (!this->emitPopPtr(E)) return false; + } else if (F.isStruct() || F.isUnion()) { + if (!this->emitDupPtr(E)) + return false; + if (!this->emitGetPtrField(RF->Offset, E)) + return false; + if (!this->visitAPValueInitializer(F, E)) + return false; + if (!this->emitPopPtr(E)) + return false; } else { assert(false && "I don't think this should be possible"); } } return true; + } else if (Val.isUnion()) { + const FieldDecl *UnionField = Val.getUnionField(); + const Record *R = this->getRecord(UnionField->getParent()); + assert(R); + const APValue &F = Val.getUnionValue(); + const Record::Field *RF = R->getField(UnionField); + PrimType T = classifyPrim(RF->Decl->getType()); + if (!this->visitAPValue(F, T, E)) + return false; + return this->emitInitElem(T, 0, E); } // TODO: Other types. @@ -3827,12 +3855,10 @@ bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator( } template <class Emitter> -bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { +bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { if (DiscardResult) return true; - const auto *D = E->getDecl(); - if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { return this->emitConst(ECD->getInitVal(), E); } else if (const auto *BD = dyn_cast<BindingDecl>(D)) { @@ -3900,7 +3926,7 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { if (!this->visitVarDecl(VD)) return false; // Retry. - return this->VisitDeclRefExpr(E); + return this->visitDeclRef(VD, E); } } } else { @@ -3910,7 +3936,7 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { if (!this->visitVarDecl(VD)) return false; // Retry. - return this->VisitDeclRefExpr(E); + return this->visitDeclRef(VD, E); } } @@ -3927,7 +3953,15 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { return true; } - return this->emitInvalidDeclRef(E, E); + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + return this->emitInvalidDeclRef(DRE, E); + return false; +} + +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { + const auto *D = E->getDecl(); + return this->visitDeclRef(D, E); } template <class Emitter> diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 44c495240289f..7ab14b6ab383e 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -189,6 +189,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, /// Visit an APValue. bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E); bool visitAPValueInitializer(const APValue &Val, const Expr *E); + /// Visit the given decl as if we have a reference to it. + bool visitDeclRef(const ValueDecl *D, const Expr *E); /// Visits an expression and converts it to a boolean. bool visitBool(const Expr *E); diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp index 000ffe39eb94a..49ee040be392e 100644 --- a/clang/test/AST/Interp/cxx20.cpp +++ b/clang/test/AST/Interp/cxx20.cpp @@ -774,3 +774,11 @@ void overflowInSwitchCase(int n) { break; } } + +namespace APValues { + int g; + struct A { union { int n, m; }; int *p; int A::*q; char buffer[32]; }; + template<A a> constexpr const A &get = a; + constexpr const A &v = get<A{}>; + constexpr const A &w = get<A{1, &g, &A::n, "hello"}>; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits