Author: Timm Baeder Date: 2025-07-11T10:51:59+02:00 New Revision: c0422733e3b78ae29cc41b729a2a4adafc0c63bc
URL: https://github.com/llvm/llvm-project/commit/c0422733e3b78ae29cc41b729a2a4adafc0c63bc DIFF: https://github.com/llvm/llvm-project/commit/c0422733e3b78ae29cc41b729a2a4adafc0c63bc.diff LOG: [clang][bytecode] Check lambda captures before binding decls (#148130) If the given decls is a lambda capture (but also a BindingDecl), handle it as a lambda capture instead of a BindingDecl. Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index e7c085750b7ad..afa3b7ea7de7e 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -6532,14 +6532,13 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { if (DiscardResult) return true; - if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { + if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) return this->emitConst(ECD->getInitVal(), E); - } else if (const auto *BD = dyn_cast<BindingDecl>(D)) { - return this->visit(BD->getBinding()); - } else if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) { + if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) { const Function *F = getFunction(FuncDecl); return F && this->emitGetFnPtr(F, E); - } else if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) { + } + if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) { if (std::optional<unsigned> Index = P.getOrCreateGlobal(D)) { if (!this->emitGetPtrGlobal(*Index, E)) return false; @@ -6560,13 +6559,15 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { // value. bool IsReference = D->getType()->isReferenceType(); - // Check for local/global variables and parameters. + // Local variables. if (auto It = Locals.find(D); It != Locals.end()) { const unsigned Offset = It->second.Offset; if (IsReference) return this->emitGetLocal(classifyPrim(E), Offset, E); return this->emitGetPtrLocal(Offset, E); - } else if (auto GlobalIndex = P.getGlobal(D)) { + } + // Global variables. + if (auto GlobalIndex = P.getGlobal(D)) { if (IsReference) { if (!Ctx.getLangOpts().CPlusPlus11) return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E); @@ -6574,7 +6575,9 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { } return this->emitGetPtrGlobal(*GlobalIndex, E); - } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { + } + // Function parameters. + if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { if (auto It = this->Params.find(PVD); It != this->Params.end()) { if (IsReference || !It->second.IsPtr) return this->emitGetParam(classifyPrim(E), It->second.Offset, E); @@ -6600,7 +6603,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { return this->visitDeclRef(D, E); }; - // Handle lambda captures. + // Lambda captures. if (auto It = this->LambdaCaptures.find(D); It != this->LambdaCaptures.end()) { auto [Offset, IsPtr] = It->second; @@ -6608,12 +6611,17 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { if (IsPtr) return this->emitGetThisFieldPtr(Offset, E); return this->emitGetPtrThisField(Offset, E); - } else if (const auto *DRE = dyn_cast<DeclRefExpr>(E); - DRE && DRE->refersToEnclosingVariableOrCapture()) { + } + + if (const auto *DRE = dyn_cast<DeclRefExpr>(E); + DRE && DRE->refersToEnclosingVariableOrCapture()) { if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture()) return revisit(VD); } + if (const auto *BD = dyn_cast<BindingDecl>(D)) + return this->visit(BD->getBinding()); + // Avoid infinite recursion. if (D == InitializingDecl) return this->emitDummyPtr(D, E); @@ -6666,7 +6674,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { if (VD->evaluateValue()) return revisit(VD); - if (!D->getType()->isReferenceType()) + if (!IsReference) return this->emitDummyPtr(D, E); return this->emitInvalidDeclRef(cast<DeclRefExpr>(E), diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp index 33a6039459484..aa8d055e44971 100644 --- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -3,6 +3,10 @@ // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -fcxx-exceptions // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER -fcxx-exceptions +// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks %s -fcxx-exceptions -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -fblocks %s -fcxx-exceptions -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -fcxx-exceptions -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER -fcxx-exceptions -fexperimental-new-constant-interpreter namespace test_lambda_is_literal { #ifdef CPP14_AND_EARLIER _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits