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&lt;0&gt;` -&gt; mangle the `enable_if` condition -&gt; mangle the 
lambda's local name -&gt; mangle `get&lt;0&gt;` -&gt; ...

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

Reply via email to