llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Usef Ahmed (usefahmed07) <details> <summary>Changes</summary> Fixes #<!-- -->233807 When a function template with an `enable_if` (or `diagnose_if`) attribute whose condition contains a lambda is instantiated, the lambda closure type is created with the instantiated function as its `DeclContext` (the condition is substituted under `ContextRAII(S, New)`, which is needed so that parameters and `this` resolve). The lambda has no `LambdaContextDecl`. When mangling, this causes infinite recursion: mangle `get<0>` -> mangle the `enable_if` condition -> mangle the lambda's local name -> mangle `get<0>` -> ... The dependent pattern's lambda lives in the function's parent context, so this patch makes `getEffectiveDeclContext` do the same for a lambda that sits inside an `EnableIfAttr`/`DiagnoseIfAttr` condition of its own `DeclContext` function (detected by source location). This breaks the cycle. I first tried changing the context used for substitution in `instantiateDependentFunctionAttrCondition`, but that breaks lookup of parameters and `this` (it regressed `SemaCXX/enable_if.cpp`, `SemaCXX/diagnose_if.cpp` and `CodeGenCXX/enable_if.cpp`), so the fix is in the mangler instead. Test: added `clang/test/CodeGenCXX/mangle-lambda-enable-if.cpp`. It crashes without the patch and passes with it. Also ran `SemaCXX/enable_if.cpp`, `SemaCXX/diagnose_if.cpp`, `CodeGenCXX/enable_if.cpp`, `CodeGenCXX/mangle-lambdas*.cpp` and `SemaTemplate/`; no regressions. --- Full diff: https://github.com/llvm/llvm-project/pull/234686.diff 2 Files Affected: - (modified) clang/lib/AST/ItaniumMangle.cpp (+21) - (added) clang/test/CodeGenCXX/mangle-lambda-enable-if.cpp (+10) ``````````diff diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 02f27cec53f69..48da61996d0f1 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -30,6 +30,7 @@ #include "clang/Basic/ABI.h" #include "clang/Basic/DiagnosticAST.h" #include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Thunk.h" #include "llvm/ADT/StringExtras.h" @@ -664,6 +665,26 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { if (ParmVarDecl *ContextParam = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) return ContextParam->getDeclContext(); + + // A lambda in the condition of an enable_if/diagnose_if attribute is + // instantiated with the function as its DeclContext, but the ABI treats it + // like the dependent pattern: it lives in the function's parent context. + // Mangling it relative to the function would recurse forever, since the + // function's encoding includes the attribute condition. + if (RD->isLambda() && !RD->getLambdaContextDecl()) + if (const auto *FD = dyn_cast<FunctionDecl>(RD->getDeclContext())) { + const SourceManager &SM = getASTContext().getSourceManager(); + SourceLocation Loc = RD->getLocation(); + for (const Attr *A : FD->attrs()) { + if (!isa<EnableIfAttr, DiagnoseIfAttr>(A)) + continue; + SourceRange R = A->getRange(); + if (R.isValid() && Loc.isValid() && + !SM.isBeforeInTranslationUnit(Loc, R.getBegin()) && + !SM.isBeforeInTranslationUnit(R.getEnd(), Loc)) + return FD->getDeclContext(); + } + } } // Perform the same check for block literals. diff --git a/clang/test/CodeGenCXX/mangle-lambda-enable-if.cpp b/clang/test/CodeGenCXX/mangle-lambda-enable-if.cpp new file mode 100644 index 0000000000000..fd92cd1aa65d3 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-lambda-enable-if.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++20 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s + +// Mangling a lambda in an enable_if condition must not recurse infinitely. +// https://github.com/llvm/llvm-project/issues/233807 +template <int = 0> +int get() __attribute__((enable_if([]() { return true; }(), ""))) { return 0; } + +// CHECK-LABEL: define {{.*}} @__cxx_global_var_init +// CHECK: call {{.*}} @_Z3getILi0EEUa9enable_ifIXclLUlvE_EEEiv() +int y = get(); `````````` </details> https://github.com/llvm/llvm-project/pull/234686 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
