From 36b07077673b6c639804160c6b31ce57718e13db Mon Sep 17 00:00:00 2001 From: Timm Baeder Date: Fri, 11 Oct 2024 05:58:25 +0200 Subject: [PATCH] [clang][bytecode] Return an lvalue path for dummy pointers (#111862) Not doing this is wrong in general and we need to reject expressions where it would matter differently. --- clang/lib/AST/ByteCode/Compiler.cpp | 16 ++++++++++------ clang/lib/AST/ByteCode/Pointer.cpp | 5 ----- clang/test/AST/ByteCode/cxx1z.cpp | 3 +++ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index ba4c5600d613b..0a3b38b0dc6e5 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -6006,6 +6006,9 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { return this->emitGetPtrParam(It->second.Offset, E); } + + if (D->getType()->isReferenceType()) + return false; // FIXME: Do we need to emit InvalidDeclRef? } // In case we need to re-visit a declaration. @@ -6042,9 +6045,7 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { const auto typeShouldBeVisited = [&](QualType T) -> bool { if (T.isConstant(Ctx.getASTContext())) return true; - if (const auto *RT = T->getAs()) - return RT->getPointeeType().isConstQualified(); - return false; + return T->isReferenceType(); }; // DecompositionDecls are just proxies for us. @@ -6060,9 +6061,12 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { // other words, we're evaluating the initializer, just to know if we can // evaluate the initializer. if (VD->isLocalVarDecl() && typeShouldBeVisited(VD->getType()) && - VD->getInit() && !VD->getInit()->isValueDependent() && - VD->evaluateValue()) - return revisit(VD); + VD->getInit() && !VD->getInit()->isValueDependent()) { + + if (VD->evaluateValue()) + return revisit(VD); + return this->emitInvalidDeclRef(cast(E), E); + } } } else { if (const auto *VD = dyn_cast(D); diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index a52f0e336ef29..75b00dcb2ab24 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -253,11 +253,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { } } - // FIXME(perf): We compute the lvalue path above, but we can't supply it - // for dummy pointers (that causes crashes later in CheckConstantExpression). - if (isDummy()) - Path.clear(); - // We assemble the LValuePath starting from the innermost pointer to the // outermost one. SO in a.b.c, the first element in Path will refer to // the field 'c', while later code expects it to refer to 'a'. diff --git a/clang/test/AST/ByteCode/cxx1z.cpp b/clang/test/AST/ByteCode/cxx1z.cpp index 2b5d215f01654..1a06597fa348f 100644 --- a/clang/test/AST/ByteCode/cxx1z.cpp +++ b/clang/test/AST/ByteCode/cxx1z.cpp @@ -10,3 +10,6 @@ namespace Temp { A c; // both-error {{reference to subobject of temporary object}} A d; // both-error {{pointer to subobject of temporary object}} } + +char arr[3]; +A d; // both-error {{refers to subobject '&arr[1]'}}