https://github.com/alcxpr updated 
https://github.com/llvm/llvm-project/pull/165524

>From f303f139966b6753718aa3e12a2b3e2dc4ef5a4c Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Wed, 29 Oct 2025 14:59:42 +0700
Subject: [PATCH 01/12] [Clang][CodeGen]  Fix crash when compiling naked
 lambdas

Skip instance and lambda prologue emission when a lambda is marked `naked`,
preventing invalid access to `this` during code generation.
---
 clang/lib/CodeGen/CodeGenFunction.cpp  | 82 +++++++++++++++-----------
 clang/test/CodeGenCXX/naked-lambda.cpp | 20 +++++++
 2 files changed, 66 insertions(+), 36 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/naked-lambda.cpp

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index 88628530cf66b..11e9e708f9b73 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -46,6 +46,7 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/Support/CRC.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/xxhash.h"
 #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
 #include "llvm/Transforms/Utils/PromoteMemToReg.h"
@@ -1271,50 +1272,59 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     }
   }
 
-  EmitFunctionProlog(*CurFnInfo, CurFn, Args);
+    EmitFunctionProlog(*CurFnInfo, CurFn, Args);
 
   if (const CXXMethodDecl *MD = dyn_cast_if_present<CXXMethodDecl>(D);
       MD && !MD->isStatic()) {
     bool IsInLambda =
         MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call;
-    if (MD->isImplicitObjectMemberFunction())
-      CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
-    if (IsInLambda) {
-      // We're in a lambda; figure out the captures.
-      MD->getParent()->getCaptureFields(LambdaCaptureFields,
-                                        LambdaThisCaptureField);
-      if (LambdaThisCaptureField) {
-        // If the lambda captures the object referred to by '*this' - either by
-        // value or by reference, make sure CXXThisValue points to the correct
-        // object.
-
-        // Get the lvalue for the field (which is a copy of the enclosing 
object
-        // or contains the address of the enclosing object).
-        LValue ThisFieldLValue = 
EmitLValueForLambdaField(LambdaThisCaptureField);
-        if (!LambdaThisCaptureField->getType()->isPointerType()) {
-          // If the enclosing object was captured by value, just use its
-          // address. Sign this pointer.
-          CXXThisValue = ThisFieldLValue.getPointer(*this);
-        } else {
-          // Load the lvalue pointed to by the field, since '*this' was 
captured
-          // by reference.
-          CXXThisValue =
-              EmitLoadOfLValue(ThisFieldLValue, 
SourceLocation()).getScalarVal();
+
+    const FunctionDecl *FD = dyn_cast_if_present<FunctionDecl>(D);
+    bool IsNaked = FD && FD->hasAttr<NakedAttr>();
+
+    if (!IsNaked) {
+      if (MD->isImplicitObjectMemberFunction())
+        CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+
+      if (IsInLambda) {
+        // We're in a lambda; figure out the captures.
+        MD->getParent()->getCaptureFields(LambdaCaptureFields,
+                                          LambdaThisCaptureField);
+        if (LambdaThisCaptureField) {
+          // If the lambda captures the object referred to by '*this' - either 
by
+          // value or by reference, make sure CXXThisValue points to the 
correct
+          // object.
+
+          // Get the lvalue for the field (which is a copy of the enclosing 
object
+          // or contains the address of the enclosing object).
+          LValue ThisFieldLValue =
+              EmitLValueForLambdaField(LambdaThisCaptureField);
+          if (!LambdaThisCaptureField->getType()->isPointerType()) {
+            // If the enclosing object was captured by value, just use its
+            // address. Sign this pointer.
+            CXXThisValue = ThisFieldLValue.getPointer(*this);
+          } else {
+            // Load the lvalue pointed to by the field, since '*this' was 
captured
+            // by reference.
+            CXXThisValue =
+                EmitLoadOfLValue(ThisFieldLValue, 
SourceLocation()).getScalarVal();
+          }
         }
-      }
-      for (auto *FD : MD->getParent()->fields()) {
-        if (FD->hasCapturedVLAType()) {
-          auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD),
-                                           SourceLocation()).getScalarVal();
-          auto VAT = FD->getCapturedVLAType();
-          VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+
+        for (auto *FD : MD->getParent()->fields()) {
+          if (FD->hasCapturedVLAType()) {
+            auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD),
+                                             SourceLocation()).getScalarVal();
+            auto VAT = FD->getCapturedVLAType();
+            VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+          }
         }
+      } else if (MD->isImplicitObjectMemberFunction()) {
+        // Not in a lambda; just use 'this' from the method.
+        // FIXME: Should we generate a new load for each use of 'this'?  The
+        // fast register allocator would be happier...
+        CXXThisValue = CXXABIThisValue;
       }
-    } else if (MD->isImplicitObjectMemberFunction()) {
-      // Not in a lambda; just use 'this' from the method.
-      // FIXME: Should we generate a new load for each use of 'this'?  The
-      // fast register allocator would be happier...
-      CXXThisValue = CXXABIThisValue;
     }
 
     // Check the 'this' pointer once per function, if it's available.
diff --git a/clang/test/CodeGenCXX/naked-lambda.cpp 
b/clang/test/CodeGenCXX/naked-lambda.cpp
new file mode 100644
index 0000000000000..27ea1af09da01
--- /dev/null
+++ b/clang/test/CodeGenCXX/naked-lambda.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S %s -o - | FileCheck %s 
--check-prefix=ASM
+
+void test_naked_lambda() {
+  auto l = []() __attribute__((naked)) {
+    asm volatile("retq");
+  };
+  l();
+}
+
+// CHECK: define internal void @"_ZZ17test_naked_lambdavENK3$_0clEv"
+// CHECK-NOT: alloca
+// CHECK-NOT: store
+// CHECK-NOT: call void @_ZN
+// ASM-LABEL: _ZZ17test_naked_lambdavENK3$_0clEv:
+// ASM-NOT: push
+// ASM-NOT: pop
+// ASM: retq
+
+

>From 666aed6e0078e158e8539d842f3c8b88de74891f Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Wed, 29 Oct 2025 15:38:22 +0700
Subject: [PATCH 02/12] [Clang][CodeGen] Apply clang-format

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 180 ++++++++++++++------------
 1 file changed, 94 insertions(+), 86 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index 11e9e708f9b73..a4affa30f491a 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -115,9 +115,12 @@ llvm::fp::ExceptionBehavior
 clang::ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind) {
 
   switch (Kind) {
-  case LangOptions::FPE_Ignore:  return llvm::fp::ebIgnore;
-  case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
-  case LangOptions::FPE_Strict:  return llvm::fp::ebStrict;
+  case LangOptions::FPE_Ignore:
+    return llvm::fp::ebIgnore;
+  case LangOptions::FPE_MayTrap:
+    return llvm::fp::ebMayTrap;
+  case LangOptions::FPE_Strict:
+    return llvm::fp::ebStrict;
   default:
     llvm_unreachable("Unsupported FP Exception Behavior");
   }
@@ -175,8 +178,7 @@ void 
CodeGenFunction::CGFPOptionsRAII::ConstructorHelper(FPOptions FPFeatures) {
          "FPConstrained should be enabled on entire function");
 
   auto mergeFnAttrValue = [&](StringRef Name, bool Value) {
-    auto OldValue =
-        CGF.CurFn->getFnAttribute(Name).getValueAsBool();
+    auto OldValue = CGF.CurFn->getFnAttribute(Name).getValueAsBool();
     auto NewValue = OldValue & Value;
     if (OldValue != NewValue)
       CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
@@ -216,8 +218,8 @@ CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, 
QualType T,
                                       IsKnownNonNull);
 }
 
-LValue
-CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) 
{
+LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V,
+                                                          QualType T) {
   return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true,
                                       /*MightBeSigned*/ true, *this);
 }
@@ -330,7 +332,7 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
   // cleans up functions which started with a unified return block.
   if (ReturnBlock.getBlock()->hasOneUse()) {
     llvm::BranchInst *BI =
-      dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin());
+        dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin());
     if (BI && BI->isUnconditional() &&
         BI->getSuccessor(0) == ReturnBlock.getBlock()) {
       // Record/return the DebugLoc of the simple 'return' expression to be 
used
@@ -353,7 +355,8 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
 }
 
 static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) {
-  if (!BB) return;
+  if (!BB)
+    return;
   if (!BB->use_empty()) {
     CGF.CurFn->insert(CGF.CurFn->end(), BB);
     return;
@@ -375,9 +378,9 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) 
{
            "mismatched push/pop in convergence stack!");
   }
 
-  bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0
-    && NumSimpleReturnExprs == NumReturnExprs
-    && ReturnBlock.getBlock()->use_empty();
+  bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0 &&
+                               NumSimpleReturnExprs == NumReturnExprs &&
+                               ReturnBlock.getBlock()->use_empty();
   // Usually the return expression is evaluated before the cleanup
   // code.  If the function contains only a simple return statement,
   // such as a constant, the location before the cleanup code becomes
@@ -445,8 +448,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) 
{
                      RetKeyInstructionsAtomGroup);
   EmitEndEHSpec(CurCodeDecl);
 
-  assert(EHStack.empty() &&
-         "did not remove all scopes from cleanup stack!");
+  assert(EHStack.empty() && "did not remove all scopes from cleanup stack!");
 
   // If someone did an indirect goto, emit the indirect goto block at the end 
of
   // the function.
@@ -656,7 +658,8 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl 
*FD,
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getXDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getYDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getZDim())))};
-    Fn->setMetadata("work_group_size_hint", llvm::MDNode::get(Context, 
AttrMDArgs));
+    Fn->setMetadata("work_group_size_hint",
+                    llvm::MDNode::get(Context, AttrMDArgs));
   }
 
   if (const ReqdWorkGroupSizeAttr *A = FD->getAttr<ReqdWorkGroupSizeAttr>()) {
@@ -667,7 +670,8 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl 
*FD,
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getXDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getYDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getZDim())))};
-    Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, 
AttrMDArgs));
+    Fn->setMetadata("reqd_work_group_size",
+                    llvm::MDNode::get(Context, AttrMDArgs));
   }
 
   if (const OpenCLIntelReqdSubGroupSizeAttr *A =
@@ -680,7 +684,7 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl 
*FD,
 }
 
 /// Determine whether the function F ends with a return stmt.
-static bool endsWithReturn(const Decl* F) {
+static bool endsWithReturn(const Decl *F) {
   const Stmt *Body = nullptr;
   if (auto *FD = dyn_cast_or_null<FunctionDecl>(F))
     Body = FD->getBody();
@@ -870,7 +874,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType 
RetTy,
       const IdentifierInfo *II = 
OMD->getSelector().getIdentifierInfoForSlot(0);
       if (OMD->getMethodFamily() == OMF_dealloc ||
           OMD->getMethodFamily() == OMF_initialize ||
-          (OMD->getSelector().isUnarySelector() && 
II->isStr(".cxx_destruct"))) {
+          (OMD->getSelector().isUnarySelector() &&
+           II->isStr(".cxx_destruct"))) {
         markAsIgnoreThreadCheckingAtRuntime(Fn);
       }
     }
@@ -1183,14 +1188,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
       if (CGM.getCodeGenOpts().MNopMCount) {
         if (!CGM.getCodeGenOpts().CallFEntry)
           CGM.getDiags().Report(diag::err_opt_not_valid_without_opt)
-            << "-mnop-mcount" << "-mfentry";
+              << "-mnop-mcount" << "-mfentry";
         Fn->addFnAttr("mnop-mcount");
       }
 
       if (CGM.getCodeGenOpts().RecordMCount) {
         if (!CGM.getCodeGenOpts().CallFEntry)
           CGM.getDiags().Report(diag::err_opt_not_valid_without_opt)
-            << "-mrecord-mcount" << "-mfentry";
+              << "-mrecord-mcount" << "-mfentry";
         Fn->addFnAttr("mrecord-mcount");
       }
     }
@@ -1200,7 +1205,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     if (getContext().getTargetInfo().getTriple().getArch() !=
         llvm::Triple::systemz)
       CGM.getDiags().Report(diag::err_opt_not_valid_on_target)
-        << "-mpacked-stack";
+          << "-mpacked-stack";
     Fn->addFnAttr("packed-stack");
   }
 
@@ -1237,8 +1242,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
     llvm::Function::arg_iterator EI = CurFn->arg_end();
     --EI;
-    llvm::Value *Addr = Builder.CreateStructGEP(
-        CurFnInfo->getArgStruct(), &*EI, Idx);
+    llvm::Value *Addr =
+        Builder.CreateStructGEP(CurFnInfo->getArgStruct(), &*EI, Idx);
     llvm::Type *Ty =
         cast<llvm::GetElementPtrInst>(Addr)->getResultElementType();
     ReturnValuePointer = Address(Addr, Ty, getPointerAlign());
@@ -1251,8 +1256,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     // Tell the epilog emitter to autorelease the result.  We do this
     // now so that various specialized functions can suppress it
     // during their IR-generation.
-    if (getLangOpts().ObjCAutoRefCount &&
-        !CurFnInfo->isReturnsRetained() &&
+    if (getLangOpts().ObjCAutoRefCount && !CurFnInfo->isReturnsRetained() &&
         RetTy->isObjCRetainableType())
       AutoreleaseResult = true;
   }
@@ -1272,7 +1276,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     }
   }
 
-    EmitFunctionProlog(*CurFnInfo, CurFn, Args);
+  EmitFunctionProlog(*CurFnInfo, CurFn, Args);
 
   if (const CXXMethodDecl *MD = dyn_cast_if_present<CXXMethodDecl>(D);
       MD && !MD->isStatic()) {
@@ -1291,12 +1295,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
         MD->getParent()->getCaptureFields(LambdaCaptureFields,
                                           LambdaThisCaptureField);
         if (LambdaThisCaptureField) {
-          // If the lambda captures the object referred to by '*this' - either 
by
-          // value or by reference, make sure CXXThisValue points to the 
correct
-          // object.
+          // If the lambda captures the object referred to by '*this' - either
+          // by value or by reference, make sure CXXThisValue points to the
+          // correct object.
 
-          // Get the lvalue for the field (which is a copy of the enclosing 
object
-          // or contains the address of the enclosing object).
+          // Get the lvalue for the field (which is a copy of the enclosing
+          // object or contains the address of the enclosing object).
           LValue ThisFieldLValue =
               EmitLValueForLambdaField(LambdaThisCaptureField);
           if (!LambdaThisCaptureField->getType()->isPointerType()) {
@@ -1304,17 +1308,18 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
             // address. Sign this pointer.
             CXXThisValue = ThisFieldLValue.getPointer(*this);
           } else {
-            // Load the lvalue pointed to by the field, since '*this' was 
captured
-            // by reference.
-            CXXThisValue =
-                EmitLoadOfLValue(ThisFieldLValue, 
SourceLocation()).getScalarVal();
+            // Load the lvalue pointed to by the field, since '*this' was
+            // captured by reference.
+            CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
+                               .getScalarVal();
           }
         }
 
         for (auto *FD : MD->getParent()->fields()) {
           if (FD->hasCapturedVLAType()) {
-            auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD),
-                                             SourceLocation()).getScalarVal();
+            auto *ExprArg =
+                EmitLoadOfLValue(EmitLValueForLambdaField(FD), 
SourceLocation())
+                    .getScalarVal();
             auto VAT = FD->getCapturedVLAType();
             VLASizeMap[VAT->getSizeExpr()] = ExprArg;
           }
@@ -1416,7 +1421,8 @@ void 
CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
 static void TryMarkNoThrow(llvm::Function *F) {
   // LLVM treats 'nounwind' on a function as part of the type, so we
   // can't do this on functions that can be overwritten.
-  if (F->isInterposable()) return;
+  if (F->isInterposable())
+    return;
 
   for (llvm::BasicBlock &BB : *F)
     for (llvm::Instruction &I : BB)
@@ -1584,8 +1590,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, 
llvm::Function *Fn,
     EmitDestructorBody(Args);
   else if (isa<CXXConstructorDecl>(FD))
     EmitConstructorBody(Args);
-  else if (getLangOpts().CUDA &&
-           !getLangOpts().CUDAIsDevice &&
+  else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&
            FD->hasAttr<CUDAGlobalAttr>())
     CGM.getCUDARuntime().emitDeviceStub(*this, Args);
   else if (isa<CXXMethodDecl>(FD) &&
@@ -1680,7 +1685,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, 
llvm::Function *Fn,
 /// that we can just remove the code.
 bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) {
   // Null statement, not a label!
-  if (!S) return false;
+  if (!S)
+    return false;
 
   // If this is a label, we have to emit the code, consider something like:
   // if (0) {  ...  foo:  bar(); }  goto foo;
@@ -1712,7 +1718,8 @@ bool CodeGenFunction::ContainsLabel(const Stmt *S, bool 
IgnoreCaseStmts) {
 /// inside of it, this is fine.
 bool CodeGenFunction::containsBreak(const Stmt *S) {
   // Null statement, not a label!
-  if (!S) return false;
+  if (!S)
+    return false;
 
   // If this is a switch or loop that defines its own break scope, then we can
   // include it and anything inside of it.
@@ -1732,7 +1739,8 @@ bool CodeGenFunction::containsBreak(const Stmt *S) {
 }
 
 bool CodeGenFunction::mightAddDeclToScope(const Stmt *S) {
-  if (!S) return false;
+  if (!S)
+    return false;
 
   // Some statement kinds add a scope and thus never add a decl to the current
   // scope. Note, this list is longer than the list of statements that might
@@ -1785,11 +1793,11 @@ bool 
CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
   // to bool.
   Expr::EvalResult Result;
   if (!Cond->EvaluateAsInt(Result, getContext()))
-    return false;  // Not foldable, not integer or not fully evaluatable.
+    return false; // Not foldable, not integer or not fully evaluatable.
 
   llvm::APSInt Int = Result.Val.getInt();
   if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
-    return false;  // Contains a label.
+    return false; // Contains a label.
 
   PGO->markStmtMaybeUsed(Cond);
   ResultInt = Int;
@@ -2086,7 +2094,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
     //   br(c ? throw x : y, t, f) -> br(c, br(throw x, t, f), br(y, t, f)
     // Fold this to:
     //   br(c, throw x, br(y, t, f))
-    EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/false);
+    EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/ false);
     return;
   }
 
@@ -2187,8 +2195,8 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
   CGBuilderTy &Builder = CGF.Builder;
 
   CharUnits baseSize = CGF.getContext().getTypeSizeInChars(baseType);
-  llvm::Value *baseSizeInChars
-    = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity());
+  llvm::Value *baseSizeInChars =
+      llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity());
 
   Address begin = dest.withElementType(CGF.Int8Ty);
   llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(),
@@ -2206,8 +2214,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
   llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur");
   cur->addIncoming(begin.emitRawPointer(CGF), originBB);
 
-  CharUnits curAlign =
-    dest.getAlignment().alignmentOfArrayElement(baseSize);
+  CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize);
 
   // memcpy the individual element bit-pattern.
   Builder.CreateMemCpy(Address(cur, CGF.Int8Ty, curAlign), src, 
baseSizeInChars,
@@ -2215,7 +2222,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
 
   // Go to the next element.
   llvm::Value *next =
-    Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next");
+      Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next");
 
   // Leave if that's the end of the VLA.
   llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
@@ -2225,8 +2232,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
   CGF.EmitBlock(contBB);
 }
 
-void
-CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
+void CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
   // Ignore empty classes in C++.
   if (getLangOpts().CPlusPlus)
     if (const auto *RD = Ty->getAsCXXRecordDecl(); RD && RD->isEmpty())
@@ -2244,9 +2250,8 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, 
QualType Ty) {
   // Don't bother emitting a zero-byte memset.
   if (size.isZero()) {
     // But note that getTypeInfo returns 0 for a VLA.
-    if (const VariableArrayType *vlaType =
-          dyn_cast_or_null<VariableArrayType>(
-                                          getContext().getAsArrayType(Ty))) {
+    if (const VariableArrayType *vlaType = dyn_cast_or_null<VariableArrayType>(
+            getContext().getAsArrayType(Ty))) {
       auto VlaSize = getVLASize(vlaType);
       SizeVal = VlaSize.NumElts;
       CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type);
@@ -2267,20 +2272,21 @@ CodeGenFunction::EmitNullInitialization(Address 
DestPtr, QualType Ty) {
   // like -1, which happens to be the pattern used by member-pointers.
   if (!CGM.getTypes().isZeroInitializable(Ty)) {
     // For a VLA, emit a single element, then splat that over the VLA.
-    if (vla) Ty = getContext().getBaseElementType(vla);
+    if (vla)
+      Ty = getContext().getBaseElementType(vla);
 
     llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
 
-    llvm::GlobalVariable *NullVariable =
-      new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
-                               /*isConstant=*/true,
-                               llvm::GlobalVariable::PrivateLinkage,
-                               NullConstant, Twine());
+    llvm::GlobalVariable *NullVariable = new llvm::GlobalVariable(
+        CGM.getModule(), NullConstant->getType(),
+        /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, 
NullConstant,
+        Twine());
     CharUnits NullAlign = DestPtr.getAlignment();
     NullVariable->setAlignment(NullAlign.getAsAlign());
     Address SrcPtr(NullVariable, Builder.getInt8Ty(), NullAlign);
 
-    if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);
+    if (vla)
+      return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);
 
     // Get and call the appropriate llvm.memcpy overload.
     Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, false);
@@ -2307,13 +2313,14 @@ llvm::BlockAddress 
*CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
 
 llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
   // If we already made the indirect branch for indirect goto, return its 
block.
-  if (IndirectBranch) return IndirectBranch->getParent();
+  if (IndirectBranch)
+    return IndirectBranch->getParent();
 
   CGBuilderTy TmpBuilder(*this, createBasicBlock("indirectgoto"));
 
   // Create the PHI node that indirect gotos will add entries to.
-  llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, 0,
-                                              "indirect.goto.dest");
+  llvm::Value *DestVal =
+      TmpBuilder.CreatePHI(Int8PtrTy, 0, "indirect.goto.dest");
 
   // Create the indirect branch instruction.
   IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
@@ -2353,7 +2360,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
   // We have some number of constant-length arrays, so addr should
   // have LLVM type [M x [N x [...]]]*.  Build a GEP that walks
   // down to the first element of addr.
-  SmallVector<llvm::Value*, 8> gepIndices;
+  SmallVector<llvm::Value *, 8> gepIndices;
 
   // GEP down to the array type.
   llvm::ConstantInt *zero = Builder.getInt32(0);
@@ -2363,7 +2370,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
   QualType eltType;
 
   llvm::ArrayType *llvmArrayType =
-    dyn_cast<llvm::ArrayType>(addr.getElementType());
+      dyn_cast<llvm::ArrayType>(addr.getElementType());
   while (llvmArrayType) {
     assert(isa<ConstantArrayType>(arrayType));
     assert(cast<ConstantArrayType>(arrayType)->getZExtSize() ==
@@ -2373,8 +2380,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
     countFromCLAs *= llvmArrayType->getNumElements();
     eltType = arrayType->getElementType();
 
-    llvmArrayType =
-      dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType());
+    llvmArrayType = dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType());
     arrayType = getContext().getAsArrayType(arrayType->getElementType());
     assert((!llvmArrayType || arrayType) &&
            "LLVM and Clang types are out-of-synch");
@@ -2402,8 +2408,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
 
   baseType = eltType;
 
-  llvm::Value *numElements
-    = llvm::ConstantInt::get(SizeTy, countFromCLAs);
+  llvm::Value *numElements = llvm::ConstantInt::get(SizeTy, countFromCLAs);
 
   // If we had any VLA dimensions, factor them in.
   if (numVLAElements)
@@ -2439,11 +2444,10 @@ CodeGenFunction::getVLASize(const VariableArrayType 
*type) {
     }
   } while ((type = getContext().getAsVariableArrayType(elementType)));
 
-  return { numElements, elementType };
+  return {numElements, elementType};
 }
 
-CodeGenFunction::VlaSizePair
-CodeGenFunction::getVLAElements1D(QualType type) {
+CodeGenFunction::VlaSizePair CodeGenFunction::getVLAElements1D(QualType type) {
   const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
   assert(vla && "type was not a variable array type!");
   return getVLAElements1D(vla);
@@ -2454,7 +2458,7 @@ CodeGenFunction::getVLAElements1D(const VariableArrayType 
*Vla) {
   llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()];
   assert(VlaSize && "no size for VLA!");
   assert(VlaSize->getType() == SizeTy);
-  return { VlaSize, Vla->getElementType() };
+  return {VlaSize, Vla->getElementType()};
 }
 
 void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
@@ -2616,7 +2620,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType 
type) {
   } while (type->isVariablyModifiedType());
 }
 
-Address CodeGenFunction::EmitVAListRef(const Expr* E) {
+Address CodeGenFunction::EmitVAListRef(const Expr *E) {
   if (getContext().getBuiltinVaListType()->isArrayType())
     return EmitPointerWithAlignment(E);
   return EmitLValue(E).getAddress();
@@ -2640,9 +2644,11 @@ CodeGenFunction::protectFromPeepholes(RValue rvalue) {
   // is trunc(zext) folding, but if we add more, we can easily
   // extend this protection.
 
-  if (!rvalue.isScalar()) return PeepholeProtection();
+  if (!rvalue.isScalar())
+    return PeepholeProtection();
   llvm::Value *value = rvalue.getScalarVal();
-  if (!isa<llvm::ZExtInst>(value)) return PeepholeProtection();
+  if (!isa<llvm::ZExtInst>(value))
+    return PeepholeProtection();
 
   // Just make an extra bitcast.
   assert(HaveInsertPoint());
@@ -2655,7 +2661,8 @@ CodeGenFunction::protectFromPeepholes(RValue rvalue) {
 }
 
 void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
-  if (!protection.Inst) return;
+  if (!protection.Inst)
+    return;
 
   // In theory, we could try to duplicate the peepholes now, but whatever.
   protection.Inst->eraseFromParent();
@@ -2762,7 +2769,7 @@ Address CodeGenFunction::EmitFieldAnnotations(const 
FieldDecl *D,
   return Address(V, Addr.getElementType(), Addr.getAlignment());
 }
 
-CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
+CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() {}
 
 CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF)
     : CGF(CGF) {
@@ -2845,12 +2852,13 @@ void 
CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
   // referenced by an accelerator executable function, we emit an error.
   bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
   if (BuiltinID) {
-    StringRef 
FeatureList(CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
-    if (!Builtin::evaluateRequiredTargetFeatures(
-        FeatureList, CallerFeatureMap) && !IsHipStdPar) {
+    StringRef FeatureList(
+        CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
+    if (!Builtin::evaluateRequiredTargetFeatures(FeatureList,
+                                                 CallerFeatureMap) &&
+        !IsHipStdPar) {
       CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature)
-          << TargetDecl->getDeclName()
-          << FeatureList;
+          << TargetDecl->getDeclName() << FeatureList;
     }
   } else if (!TargetDecl->isMultiVersion() &&
              TargetDecl->hasAttr<TargetAttr>()) {

>From b986c7407983672eef4e1c2d80af8ae16921d92d Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Wed, 29 Oct 2025 20:28:02 +0700
Subject: [PATCH 03/12] [Clang][CodeGen] Make naked lambda captures analyzed

Naked lambdas now have their captures analyzed and metadata populated even 
though they cannot be accessed via generated code as naked functions have no 
prologue

This matches GCC's acceptance of naked lambdas with captures.
---
 clang/lib/CodeGen/CodeGenFunction.cpp         |  7 +++++
 .../CodeGenCXX/naked-lambda-capture-multi.cpp | 18 ++++++++++++
 .../CodeGenCXX/naked-lambda-capture-this.cpp  | 28 +++++++++++++++++++
 .../CodeGenCXX/naked-lambda-capture-var.cpp   | 21 ++++++++++++++
 clang/test/CodeGenCXX/naked-lambda.cpp        |  2 --
 5 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp
 create mode 100644 clang/test/CodeGenCXX/naked-lambda-capture-this.cpp
 create mode 100644 clang/test/CodeGenCXX/naked-lambda-capture-var.cpp

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index a4affa30f491a..fafcdbeeddbc7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1330,6 +1330,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
         // fast register allocator would be happier...
         CXXThisValue = CXXABIThisValue;
       }
+    } else if (IsInLambda && MD->isImplicitObjectMemberFunction()) {
+      // Populate capture fields metadata for analysis. We skip
+      // EmitInstanceProlog to avoid emitting prologue code.
+      // FIXME: Naked functions cannot access captures via LLVM IR; any access
+      // must be done manually in inline assembly.
+      MD->getParent()->getCaptureFields(LambdaCaptureFields,
+                                        LambdaThisCaptureField);
     }
 
     // Check the 'this' pointer once per function, if it's available.
diff --git a/clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp 
b/clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp
new file mode 100644
index 0000000000000..de52d6dec77e9
--- /dev/null
+++ b/clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
+
+void test_naked_lambda_capture_multi() {
+  int x = 42;
+  int y = 100;
+  auto l = [&x, y]() __attribute__((naked)) {
+    asm volatile("retq");
+  };
+  l();
+}
+
+// CHECK-LABEL: define {{.*}} 
@"_ZZ31test_naked_lambda_capture_multivENK3$_0clEv"
+// CHECK-NOT: load i32
+// CHECK-NOT: load ptr
+// CHECK-NOT: getelementptr
+// CHECK-NOT: alloca
+// CHECK: call void asm sideeffect "retq"
+// CHECK-NEXT: unreachable
diff --git a/clang/test/CodeGenCXX/naked-lambda-capture-this.cpp 
b/clang/test/CodeGenCXX/naked-lambda-capture-this.cpp
new file mode 100644
index 0000000000000..c6bcd2f83b8eb
--- /dev/null
+++ b/clang/test/CodeGenCXX/naked-lambda-capture-this.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S %s -o - | FileCheck %s 
--check-prefix=ASM
+
+struct S {
+  int member;
+  void test_naked_lambda_capture_this() {
+    auto l = [this]() __attribute__((naked)) {
+      asm volatile("retq");
+    };
+    l();
+  }
+};
+
+void test() {
+  S s;
+  s.test_naked_lambda_capture_this();
+}
+
+// CHECK-LABEL: define {{.*}} 
@_ZZN1S30test_naked_lambda_capture_thisEvENKUlvE_clEv
+// CHECK-NOT: load ptr
+// CHECK-NOT: getelementptr
+// CHECK-NOT: alloca
+// CHECK: call void asm sideeffect "retq"
+
+// ASM-LABEL: _ZZN1S30test_naked_lambda_capture_thisEvENKUlvE_clEv:
+// ASM-NOT: push
+// ASM-NOT: mov
+// ASM: retq
diff --git a/clang/test/CodeGenCXX/naked-lambda-capture-var.cpp 
b/clang/test/CodeGenCXX/naked-lambda-capture-var.cpp
new file mode 100644
index 0000000000000..543c38bd5ab45
--- /dev/null
+++ b/clang/test/CodeGenCXX/naked-lambda-capture-var.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S %s -o - | FileCheck %s 
--check-prefix=ASM
+
+void test_naked_lambda_capture_var() {
+  int x = 42;
+  auto l = [x]() __attribute__((naked)) {
+    asm volatile("retq");
+  };
+  l();
+}
+
+// CHECK-LABEL: define {{.*}} @"_ZZ29test_naked_lambda_capture_varvENK3$_0clEv"
+// CHECK-NOT: load i32
+// CHECK-NOT: alloca
+// CHECK-NOT: getelementptr
+// CHECK: call void asm sideeffect "retq"
+
+// ASM-LABEL: _ZZ29test_naked_lambda_capture_varvENK3$_0clEv:
+// ASM-NOT: push
+// ASM-NOT: mov
+// ASM: retq
diff --git a/clang/test/CodeGenCXX/naked-lambda.cpp 
b/clang/test/CodeGenCXX/naked-lambda.cpp
index 27ea1af09da01..c24699495c0cf 100644
--- a/clang/test/CodeGenCXX/naked-lambda.cpp
+++ b/clang/test/CodeGenCXX/naked-lambda.cpp
@@ -16,5 +16,3 @@ void test_naked_lambda() {
 // ASM-NOT: push
 // ASM-NOT: pop
 // ASM: retq
-
-

>From 6e341cbcce044ae14582310b9e23bcbdc74d4138 Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Wed, 29 Oct 2025 20:42:01 +0700
Subject: [PATCH 04/12] Revert file back

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 243 ++++++++++++--------------
 1 file changed, 109 insertions(+), 134 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index fafcdbeeddbc7..88628530cf66b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -46,7 +46,6 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/Support/CRC.h"
-#include "llvm/Support/Casting.h"
 #include "llvm/Support/xxhash.h"
 #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
 #include "llvm/Transforms/Utils/PromoteMemToReg.h"
@@ -115,12 +114,9 @@ llvm::fp::ExceptionBehavior
 clang::ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind) {
 
   switch (Kind) {
-  case LangOptions::FPE_Ignore:
-    return llvm::fp::ebIgnore;
-  case LangOptions::FPE_MayTrap:
-    return llvm::fp::ebMayTrap;
-  case LangOptions::FPE_Strict:
-    return llvm::fp::ebStrict;
+  case LangOptions::FPE_Ignore:  return llvm::fp::ebIgnore;
+  case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
+  case LangOptions::FPE_Strict:  return llvm::fp::ebStrict;
   default:
     llvm_unreachable("Unsupported FP Exception Behavior");
   }
@@ -178,7 +174,8 @@ void 
CodeGenFunction::CGFPOptionsRAII::ConstructorHelper(FPOptions FPFeatures) {
          "FPConstrained should be enabled on entire function");
 
   auto mergeFnAttrValue = [&](StringRef Name, bool Value) {
-    auto OldValue = CGF.CurFn->getFnAttribute(Name).getValueAsBool();
+    auto OldValue =
+        CGF.CurFn->getFnAttribute(Name).getValueAsBool();
     auto NewValue = OldValue & Value;
     if (OldValue != NewValue)
       CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
@@ -218,8 +215,8 @@ CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, 
QualType T,
                                       IsKnownNonNull);
 }
 
-LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V,
-                                                          QualType T) {
+LValue
+CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) 
{
   return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true,
                                       /*MightBeSigned*/ true, *this);
 }
@@ -332,7 +329,7 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
   // cleans up functions which started with a unified return block.
   if (ReturnBlock.getBlock()->hasOneUse()) {
     llvm::BranchInst *BI =
-        dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin());
+      dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->user_begin());
     if (BI && BI->isUnconditional() &&
         BI->getSuccessor(0) == ReturnBlock.getBlock()) {
       // Record/return the DebugLoc of the simple 'return' expression to be 
used
@@ -355,8 +352,7 @@ llvm::DebugLoc CodeGenFunction::EmitReturnBlock() {
 }
 
 static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) {
-  if (!BB)
-    return;
+  if (!BB) return;
   if (!BB->use_empty()) {
     CGF.CurFn->insert(CGF.CurFn->end(), BB);
     return;
@@ -378,9 +374,9 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) 
{
            "mismatched push/pop in convergence stack!");
   }
 
-  bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0 &&
-                               NumSimpleReturnExprs == NumReturnExprs &&
-                               ReturnBlock.getBlock()->use_empty();
+  bool OnlySimpleReturnStmts = NumSimpleReturnExprs > 0
+    && NumSimpleReturnExprs == NumReturnExprs
+    && ReturnBlock.getBlock()->use_empty();
   // Usually the return expression is evaluated before the cleanup
   // code.  If the function contains only a simple return statement,
   // such as a constant, the location before the cleanup code becomes
@@ -448,7 +444,8 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) 
{
                      RetKeyInstructionsAtomGroup);
   EmitEndEHSpec(CurCodeDecl);
 
-  assert(EHStack.empty() && "did not remove all scopes from cleanup stack!");
+  assert(EHStack.empty() &&
+         "did not remove all scopes from cleanup stack!");
 
   // If someone did an indirect goto, emit the indirect goto block at the end 
of
   // the function.
@@ -658,8 +655,7 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl 
*FD,
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getXDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getYDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getZDim())))};
-    Fn->setMetadata("work_group_size_hint",
-                    llvm::MDNode::get(Context, AttrMDArgs));
+    Fn->setMetadata("work_group_size_hint", llvm::MDNode::get(Context, 
AttrMDArgs));
   }
 
   if (const ReqdWorkGroupSizeAttr *A = FD->getAttr<ReqdWorkGroupSizeAttr>()) {
@@ -670,8 +666,7 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl 
*FD,
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getXDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getYDim()))),
         llvm::ConstantAsMetadata::get(Builder.getInt32(Eval(A->getZDim())))};
-    Fn->setMetadata("reqd_work_group_size",
-                    llvm::MDNode::get(Context, AttrMDArgs));
+    Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, 
AttrMDArgs));
   }
 
   if (const OpenCLIntelReqdSubGroupSizeAttr *A =
@@ -684,7 +679,7 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl 
*FD,
 }
 
 /// Determine whether the function F ends with a return stmt.
-static bool endsWithReturn(const Decl *F) {
+static bool endsWithReturn(const Decl* F) {
   const Stmt *Body = nullptr;
   if (auto *FD = dyn_cast_or_null<FunctionDecl>(F))
     Body = FD->getBody();
@@ -874,8 +869,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType 
RetTy,
       const IdentifierInfo *II = 
OMD->getSelector().getIdentifierInfoForSlot(0);
       if (OMD->getMethodFamily() == OMF_dealloc ||
           OMD->getMethodFamily() == OMF_initialize ||
-          (OMD->getSelector().isUnarySelector() &&
-           II->isStr(".cxx_destruct"))) {
+          (OMD->getSelector().isUnarySelector() && 
II->isStr(".cxx_destruct"))) {
         markAsIgnoreThreadCheckingAtRuntime(Fn);
       }
     }
@@ -1188,14 +1182,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
       if (CGM.getCodeGenOpts().MNopMCount) {
         if (!CGM.getCodeGenOpts().CallFEntry)
           CGM.getDiags().Report(diag::err_opt_not_valid_without_opt)
-              << "-mnop-mcount" << "-mfentry";
+            << "-mnop-mcount" << "-mfentry";
         Fn->addFnAttr("mnop-mcount");
       }
 
       if (CGM.getCodeGenOpts().RecordMCount) {
         if (!CGM.getCodeGenOpts().CallFEntry)
           CGM.getDiags().Report(diag::err_opt_not_valid_without_opt)
-              << "-mrecord-mcount" << "-mfentry";
+            << "-mrecord-mcount" << "-mfentry";
         Fn->addFnAttr("mrecord-mcount");
       }
     }
@@ -1205,7 +1199,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     if (getContext().getTargetInfo().getTriple().getArch() !=
         llvm::Triple::systemz)
       CGM.getDiags().Report(diag::err_opt_not_valid_on_target)
-          << "-mpacked-stack";
+        << "-mpacked-stack";
     Fn->addFnAttr("packed-stack");
   }
 
@@ -1242,8 +1236,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
     llvm::Function::arg_iterator EI = CurFn->arg_end();
     --EI;
-    llvm::Value *Addr =
-        Builder.CreateStructGEP(CurFnInfo->getArgStruct(), &*EI, Idx);
+    llvm::Value *Addr = Builder.CreateStructGEP(
+        CurFnInfo->getArgStruct(), &*EI, Idx);
     llvm::Type *Ty =
         cast<llvm::GetElementPtrInst>(Addr)->getResultElementType();
     ReturnValuePointer = Address(Addr, Ty, getPointerAlign());
@@ -1256,7 +1250,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     // Tell the epilog emitter to autorelease the result.  We do this
     // now so that various specialized functions can suppress it
     // during their IR-generation.
-    if (getLangOpts().ObjCAutoRefCount && !CurFnInfo->isReturnsRetained() &&
+    if (getLangOpts().ObjCAutoRefCount &&
+        !CurFnInfo->isReturnsRetained() &&
         RetTy->isObjCRetainableType())
       AutoreleaseResult = true;
   }
@@ -1282,61 +1277,44 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
       MD && !MD->isStatic()) {
     bool IsInLambda =
         MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call;
-
-    const FunctionDecl *FD = dyn_cast_if_present<FunctionDecl>(D);
-    bool IsNaked = FD && FD->hasAttr<NakedAttr>();
-
-    if (!IsNaked) {
-      if (MD->isImplicitObjectMemberFunction())
-        CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
-
-      if (IsInLambda) {
-        // We're in a lambda; figure out the captures.
-        MD->getParent()->getCaptureFields(LambdaCaptureFields,
-                                          LambdaThisCaptureField);
-        if (LambdaThisCaptureField) {
-          // If the lambda captures the object referred to by '*this' - either
-          // by value or by reference, make sure CXXThisValue points to the
-          // correct object.
-
-          // Get the lvalue for the field (which is a copy of the enclosing
-          // object or contains the address of the enclosing object).
-          LValue ThisFieldLValue =
-              EmitLValueForLambdaField(LambdaThisCaptureField);
-          if (!LambdaThisCaptureField->getType()->isPointerType()) {
-            // If the enclosing object was captured by value, just use its
-            // address. Sign this pointer.
-            CXXThisValue = ThisFieldLValue.getPointer(*this);
-          } else {
-            // Load the lvalue pointed to by the field, since '*this' was
-            // captured by reference.
-            CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
-                               .getScalarVal();
-          }
+    if (MD->isImplicitObjectMemberFunction())
+      CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+    if (IsInLambda) {
+      // We're in a lambda; figure out the captures.
+      MD->getParent()->getCaptureFields(LambdaCaptureFields,
+                                        LambdaThisCaptureField);
+      if (LambdaThisCaptureField) {
+        // If the lambda captures the object referred to by '*this' - either by
+        // value or by reference, make sure CXXThisValue points to the correct
+        // object.
+
+        // Get the lvalue for the field (which is a copy of the enclosing 
object
+        // or contains the address of the enclosing object).
+        LValue ThisFieldLValue = 
EmitLValueForLambdaField(LambdaThisCaptureField);
+        if (!LambdaThisCaptureField->getType()->isPointerType()) {
+          // If the enclosing object was captured by value, just use its
+          // address. Sign this pointer.
+          CXXThisValue = ThisFieldLValue.getPointer(*this);
+        } else {
+          // Load the lvalue pointed to by the field, since '*this' was 
captured
+          // by reference.
+          CXXThisValue =
+              EmitLoadOfLValue(ThisFieldLValue, 
SourceLocation()).getScalarVal();
         }
-
-        for (auto *FD : MD->getParent()->fields()) {
-          if (FD->hasCapturedVLAType()) {
-            auto *ExprArg =
-                EmitLoadOfLValue(EmitLValueForLambdaField(FD), 
SourceLocation())
-                    .getScalarVal();
-            auto VAT = FD->getCapturedVLAType();
-            VLASizeMap[VAT->getSizeExpr()] = ExprArg;
-          }
+      }
+      for (auto *FD : MD->getParent()->fields()) {
+        if (FD->hasCapturedVLAType()) {
+          auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD),
+                                           SourceLocation()).getScalarVal();
+          auto VAT = FD->getCapturedVLAType();
+          VLASizeMap[VAT->getSizeExpr()] = ExprArg;
         }
-      } else if (MD->isImplicitObjectMemberFunction()) {
-        // Not in a lambda; just use 'this' from the method.
-        // FIXME: Should we generate a new load for each use of 'this'?  The
-        // fast register allocator would be happier...
-        CXXThisValue = CXXABIThisValue;
       }
-    } else if (IsInLambda && MD->isImplicitObjectMemberFunction()) {
-      // Populate capture fields metadata for analysis. We skip
-      // EmitInstanceProlog to avoid emitting prologue code.
-      // FIXME: Naked functions cannot access captures via LLVM IR; any access
-      // must be done manually in inline assembly.
-      MD->getParent()->getCaptureFields(LambdaCaptureFields,
-                                        LambdaThisCaptureField);
+    } else if (MD->isImplicitObjectMemberFunction()) {
+      // Not in a lambda; just use 'this' from the method.
+      // FIXME: Should we generate a new load for each use of 'this'?  The
+      // fast register allocator would be happier...
+      CXXThisValue = CXXABIThisValue;
     }
 
     // Check the 'this' pointer once per function, if it's available.
@@ -1428,8 +1406,7 @@ void 
CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
 static void TryMarkNoThrow(llvm::Function *F) {
   // LLVM treats 'nounwind' on a function as part of the type, so we
   // can't do this on functions that can be overwritten.
-  if (F->isInterposable())
-    return;
+  if (F->isInterposable()) return;
 
   for (llvm::BasicBlock &BB : *F)
     for (llvm::Instruction &I : BB)
@@ -1597,7 +1574,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, 
llvm::Function *Fn,
     EmitDestructorBody(Args);
   else if (isa<CXXConstructorDecl>(FD))
     EmitConstructorBody(Args);
-  else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&
+  else if (getLangOpts().CUDA &&
+           !getLangOpts().CUDAIsDevice &&
            FD->hasAttr<CUDAGlobalAttr>())
     CGM.getCUDARuntime().emitDeviceStub(*this, Args);
   else if (isa<CXXMethodDecl>(FD) &&
@@ -1692,8 +1670,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, 
llvm::Function *Fn,
 /// that we can just remove the code.
 bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) {
   // Null statement, not a label!
-  if (!S)
-    return false;
+  if (!S) return false;
 
   // If this is a label, we have to emit the code, consider something like:
   // if (0) {  ...  foo:  bar(); }  goto foo;
@@ -1725,8 +1702,7 @@ bool CodeGenFunction::ContainsLabel(const Stmt *S, bool 
IgnoreCaseStmts) {
 /// inside of it, this is fine.
 bool CodeGenFunction::containsBreak(const Stmt *S) {
   // Null statement, not a label!
-  if (!S)
-    return false;
+  if (!S) return false;
 
   // If this is a switch or loop that defines its own break scope, then we can
   // include it and anything inside of it.
@@ -1746,8 +1722,7 @@ bool CodeGenFunction::containsBreak(const Stmt *S) {
 }
 
 bool CodeGenFunction::mightAddDeclToScope(const Stmt *S) {
-  if (!S)
-    return false;
+  if (!S) return false;
 
   // Some statement kinds add a scope and thus never add a decl to the current
   // scope. Note, this list is longer than the list of statements that might
@@ -1800,11 +1775,11 @@ bool 
CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
   // to bool.
   Expr::EvalResult Result;
   if (!Cond->EvaluateAsInt(Result, getContext()))
-    return false; // Not foldable, not integer or not fully evaluatable.
+    return false;  // Not foldable, not integer or not fully evaluatable.
 
   llvm::APSInt Int = Result.Val.getInt();
   if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
-    return false; // Contains a label.
+    return false;  // Contains a label.
 
   PGO->markStmtMaybeUsed(Cond);
   ResultInt = Int;
@@ -2101,7 +2076,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
     //   br(c ? throw x : y, t, f) -> br(c, br(throw x, t, f), br(y, t, f)
     // Fold this to:
     //   br(c, throw x, br(y, t, f))
-    EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/ false);
+    EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/false);
     return;
   }
 
@@ -2202,8 +2177,8 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
   CGBuilderTy &Builder = CGF.Builder;
 
   CharUnits baseSize = CGF.getContext().getTypeSizeInChars(baseType);
-  llvm::Value *baseSizeInChars =
-      llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity());
+  llvm::Value *baseSizeInChars
+    = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity());
 
   Address begin = dest.withElementType(CGF.Int8Ty);
   llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(),
@@ -2221,7 +2196,8 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
   llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur");
   cur->addIncoming(begin.emitRawPointer(CGF), originBB);
 
-  CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize);
+  CharUnits curAlign =
+    dest.getAlignment().alignmentOfArrayElement(baseSize);
 
   // memcpy the individual element bit-pattern.
   Builder.CreateMemCpy(Address(cur, CGF.Int8Ty, curAlign), src, 
baseSizeInChars,
@@ -2229,7 +2205,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
 
   // Go to the next element.
   llvm::Value *next =
-      Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next");
+    Builder.CreateInBoundsGEP(CGF.Int8Ty, cur, baseSizeInChars, "vla.next");
 
   // Leave if that's the end of the VLA.
   llvm::Value *done = Builder.CreateICmpEQ(next, end, "vla-init.isdone");
@@ -2239,7 +2215,8 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, 
QualType baseType,
   CGF.EmitBlock(contBB);
 }
 
-void CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
+void
+CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) {
   // Ignore empty classes in C++.
   if (getLangOpts().CPlusPlus)
     if (const auto *RD = Ty->getAsCXXRecordDecl(); RD && RD->isEmpty())
@@ -2257,8 +2234,9 @@ void CodeGenFunction::EmitNullInitialization(Address 
DestPtr, QualType Ty) {
   // Don't bother emitting a zero-byte memset.
   if (size.isZero()) {
     // But note that getTypeInfo returns 0 for a VLA.
-    if (const VariableArrayType *vlaType = dyn_cast_or_null<VariableArrayType>(
-            getContext().getAsArrayType(Ty))) {
+    if (const VariableArrayType *vlaType =
+          dyn_cast_or_null<VariableArrayType>(
+                                          getContext().getAsArrayType(Ty))) {
       auto VlaSize = getVLASize(vlaType);
       SizeVal = VlaSize.NumElts;
       CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type);
@@ -2279,21 +2257,20 @@ void CodeGenFunction::EmitNullInitialization(Address 
DestPtr, QualType Ty) {
   // like -1, which happens to be the pattern used by member-pointers.
   if (!CGM.getTypes().isZeroInitializable(Ty)) {
     // For a VLA, emit a single element, then splat that over the VLA.
-    if (vla)
-      Ty = getContext().getBaseElementType(vla);
+    if (vla) Ty = getContext().getBaseElementType(vla);
 
     llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
 
-    llvm::GlobalVariable *NullVariable = new llvm::GlobalVariable(
-        CGM.getModule(), NullConstant->getType(),
-        /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, 
NullConstant,
-        Twine());
+    llvm::GlobalVariable *NullVariable =
+      new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
+                               /*isConstant=*/true,
+                               llvm::GlobalVariable::PrivateLinkage,
+                               NullConstant, Twine());
     CharUnits NullAlign = DestPtr.getAlignment();
     NullVariable->setAlignment(NullAlign.getAsAlign());
     Address SrcPtr(NullVariable, Builder.getInt8Ty(), NullAlign);
 
-    if (vla)
-      return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);
+    if (vla) return emitNonZeroVLAInit(*this, Ty, DestPtr, SrcPtr, SizeVal);
 
     // Get and call the appropriate llvm.memcpy overload.
     Builder.CreateMemCpy(DestPtr, SrcPtr, SizeVal, false);
@@ -2320,14 +2297,13 @@ llvm::BlockAddress 
*CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
 
 llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
   // If we already made the indirect branch for indirect goto, return its 
block.
-  if (IndirectBranch)
-    return IndirectBranch->getParent();
+  if (IndirectBranch) return IndirectBranch->getParent();
 
   CGBuilderTy TmpBuilder(*this, createBasicBlock("indirectgoto"));
 
   // Create the PHI node that indirect gotos will add entries to.
-  llvm::Value *DestVal =
-      TmpBuilder.CreatePHI(Int8PtrTy, 0, "indirect.goto.dest");
+  llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, 0,
+                                              "indirect.goto.dest");
 
   // Create the indirect branch instruction.
   IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
@@ -2367,7 +2343,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
   // We have some number of constant-length arrays, so addr should
   // have LLVM type [M x [N x [...]]]*.  Build a GEP that walks
   // down to the first element of addr.
-  SmallVector<llvm::Value *, 8> gepIndices;
+  SmallVector<llvm::Value*, 8> gepIndices;
 
   // GEP down to the array type.
   llvm::ConstantInt *zero = Builder.getInt32(0);
@@ -2377,7 +2353,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
   QualType eltType;
 
   llvm::ArrayType *llvmArrayType =
-      dyn_cast<llvm::ArrayType>(addr.getElementType());
+    dyn_cast<llvm::ArrayType>(addr.getElementType());
   while (llvmArrayType) {
     assert(isa<ConstantArrayType>(arrayType));
     assert(cast<ConstantArrayType>(arrayType)->getZExtSize() ==
@@ -2387,7 +2363,8 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
     countFromCLAs *= llvmArrayType->getNumElements();
     eltType = arrayType->getElementType();
 
-    llvmArrayType = dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType());
+    llvmArrayType =
+      dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType());
     arrayType = getContext().getAsArrayType(arrayType->getElementType());
     assert((!llvmArrayType || arrayType) &&
            "LLVM and Clang types are out-of-synch");
@@ -2415,7 +2392,8 @@ llvm::Value *CodeGenFunction::emitArrayLength(const 
ArrayType *origArrayType,
 
   baseType = eltType;
 
-  llvm::Value *numElements = llvm::ConstantInt::get(SizeTy, countFromCLAs);
+  llvm::Value *numElements
+    = llvm::ConstantInt::get(SizeTy, countFromCLAs);
 
   // If we had any VLA dimensions, factor them in.
   if (numVLAElements)
@@ -2451,10 +2429,11 @@ CodeGenFunction::getVLASize(const VariableArrayType 
*type) {
     }
   } while ((type = getContext().getAsVariableArrayType(elementType)));
 
-  return {numElements, elementType};
+  return { numElements, elementType };
 }
 
-CodeGenFunction::VlaSizePair CodeGenFunction::getVLAElements1D(QualType type) {
+CodeGenFunction::VlaSizePair
+CodeGenFunction::getVLAElements1D(QualType type) {
   const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
   assert(vla && "type was not a variable array type!");
   return getVLAElements1D(vla);
@@ -2465,7 +2444,7 @@ CodeGenFunction::getVLAElements1D(const VariableArrayType 
*Vla) {
   llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()];
   assert(VlaSize && "no size for VLA!");
   assert(VlaSize->getType() == SizeTy);
-  return {VlaSize, Vla->getElementType()};
+  return { VlaSize, Vla->getElementType() };
 }
 
 void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
@@ -2627,7 +2606,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType 
type) {
   } while (type->isVariablyModifiedType());
 }
 
-Address CodeGenFunction::EmitVAListRef(const Expr *E) {
+Address CodeGenFunction::EmitVAListRef(const Expr* E) {
   if (getContext().getBuiltinVaListType()->isArrayType())
     return EmitPointerWithAlignment(E);
   return EmitLValue(E).getAddress();
@@ -2651,11 +2630,9 @@ CodeGenFunction::protectFromPeepholes(RValue rvalue) {
   // is trunc(zext) folding, but if we add more, we can easily
   // extend this protection.
 
-  if (!rvalue.isScalar())
-    return PeepholeProtection();
+  if (!rvalue.isScalar()) return PeepholeProtection();
   llvm::Value *value = rvalue.getScalarVal();
-  if (!isa<llvm::ZExtInst>(value))
-    return PeepholeProtection();
+  if (!isa<llvm::ZExtInst>(value)) return PeepholeProtection();
 
   // Just make an extra bitcast.
   assert(HaveInsertPoint());
@@ -2668,8 +2645,7 @@ CodeGenFunction::protectFromPeepholes(RValue rvalue) {
 }
 
 void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
-  if (!protection.Inst)
-    return;
+  if (!protection.Inst) return;
 
   // In theory, we could try to duplicate the peepholes now, but whatever.
   protection.Inst->eraseFromParent();
@@ -2776,7 +2752,7 @@ Address CodeGenFunction::EmitFieldAnnotations(const 
FieldDecl *D,
   return Address(V, Addr.getElementType(), Addr.getAlignment());
 }
 
-CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() {}
+CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { }
 
 CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF)
     : CGF(CGF) {
@@ -2859,13 +2835,12 @@ void 
CodeGenFunction::checkTargetFeatures(SourceLocation Loc,
   // referenced by an accelerator executable function, we emit an error.
   bool IsHipStdPar = getLangOpts().HIPStdPar && getLangOpts().CUDAIsDevice;
   if (BuiltinID) {
-    StringRef FeatureList(
-        CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
-    if (!Builtin::evaluateRequiredTargetFeatures(FeatureList,
-                                                 CallerFeatureMap) &&
-        !IsHipStdPar) {
+    StringRef 
FeatureList(CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
+    if (!Builtin::evaluateRequiredTargetFeatures(
+        FeatureList, CallerFeatureMap) && !IsHipStdPar) {
       CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature)
-          << TargetDecl->getDeclName() << FeatureList;
+          << TargetDecl->getDeclName()
+          << FeatureList;
     }
   } else if (!TargetDecl->isMultiVersion() &&
              TargetDecl->hasAttr<TargetAttr>()) {

>From e5a214d2e990add5c182438149a013295b6bd123 Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Wed, 29 Oct 2025 20:44:43 +0700
Subject: [PATCH 05/12] [Clang][CodeGen] Format

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 86 ++++++++++++++++-----------
 1 file changed, 51 insertions(+), 35 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index 88628530cf66b..58d7810e26cf5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1277,44 +1277,60 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
       MD && !MD->isStatic()) {
     bool IsInLambda =
         MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call;
-    if (MD->isImplicitObjectMemberFunction())
-      CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
-    if (IsInLambda) {
-      // We're in a lambda; figure out the captures.
-      MD->getParent()->getCaptureFields(LambdaCaptureFields,
-                                        LambdaThisCaptureField);
-      if (LambdaThisCaptureField) {
-        // If the lambda captures the object referred to by '*this' - either by
-        // value or by reference, make sure CXXThisValue points to the correct
-        // object.
-
-        // Get the lvalue for the field (which is a copy of the enclosing 
object
-        // or contains the address of the enclosing object).
-        LValue ThisFieldLValue = 
EmitLValueForLambdaField(LambdaThisCaptureField);
-        if (!LambdaThisCaptureField->getType()->isPointerType()) {
-          // If the enclosing object was captured by value, just use its
-          // address. Sign this pointer.
-          CXXThisValue = ThisFieldLValue.getPointer(*this);
-        } else {
-          // Load the lvalue pointed to by the field, since '*this' was 
captured
-          // by reference.
-          CXXThisValue =
-              EmitLoadOfLValue(ThisFieldLValue, 
SourceLocation()).getScalarVal();
+
+    const FunctionDecl *FD = dyn_cast_if_present<FunctionDecl>(D);
+    bool IsNaked = FD && FD->hasAttr<NakedAttr>();
+    if (!IsNaked) {
+      if (MD->isImplicitObjectMemberFunction())
+        CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+
+      if (IsInLambda) {
+        // We're in a lambda; figure out the captures.
+        MD->getParent()->getCaptureFields(LambdaCaptureFields,
+                                          LambdaThisCaptureField);
+        if (LambdaThisCaptureField) {
+          // If the lambda captures the object referred to by '*this' - either
+          // by value or by reference, make sure CXXThisValue points to the
+          // correct object.
+
+          // Get the lvalue for the field (which is a copy of the enclosing
+          // object or contains the address of the enclosing object).
+          LValue ThisFieldLValue =
+              EmitLValueForLambdaField(LambdaThisCaptureField);
+          if (!LambdaThisCaptureField->getType()->isPointerType()) {
+            // If the enclosing object was captured by value, just use its
+            // address. Sign this pointer.
+            CXXThisValue = ThisFieldLValue.getPointer(*this);
+          } else {
+            // Load the lvalue pointed to by the field, since '*this' was
+            // captured by reference.
+            CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
+                               .getScalarVal();
+          }
         }
-      }
-      for (auto *FD : MD->getParent()->fields()) {
-        if (FD->hasCapturedVLAType()) {
-          auto *ExprArg = EmitLoadOfLValue(EmitLValueForLambdaField(FD),
-                                           SourceLocation()).getScalarVal();
-          auto VAT = FD->getCapturedVLAType();
-          VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+
+        for (auto *FD : MD->getParent()->fields()) {
+          if (FD->hasCapturedVLAType()) {
+            auto *ExprArg =
+                EmitLoadOfLValue(EmitLValueForLambdaField(FD), 
SourceLocation())
+                    .getScalarVal();
+            auto VAT = FD->getCapturedVLAType();
+            VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+          }
         }
+      } else if (MD->isImplicitObjectMemberFunction()) {
+        // Not in a lambda; just use 'this' from the method.
+        // FIXME: Should we generate a new load for each use of 'this'?  The
+        // fast register allocator would be happier...
+        CXXThisValue = CXXABIThisValue;
       }
-    } else if (MD->isImplicitObjectMemberFunction()) {
-      // Not in a lambda; just use 'this' from the method.
-      // FIXME: Should we generate a new load for each use of 'this'?  The
-      // fast register allocator would be happier...
-      CXXThisValue = CXXABIThisValue;
+    } else if (IsInLambda && MD->isImplicitObjectMemberFunction()) {
+      // Populate capture fields metadata for analysis. We skip
+      // EmitInstanceProlog to avoid emitting prologue code.
+      // FIXME: Naked functions cannot access captures via LLVM IR; any access
+      // must be done manually in inline assembly.
+      MD->getParent()->getCaptureFields(LambdaCaptureFields,
+                                        LambdaThisCaptureField);
     }
 
     // Check the 'this' pointer once per function, if it's available.

>From 79d94227c41fc5e5f054c0ebc1bf8e3ddf6336a4 Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Thu, 30 Oct 2025 17:16:10 +0700
Subject: [PATCH 06/12] [Clang][Sema] Remove naked attribute from lambdas with
 ODR-used captures

This commit is for GCC compatibility. GCC silently ignores the naked attribute 
if the captures are used.
---
 clang/compile_commands.json                    |  1 +
 clang/lib/Sema/SemaLambda.cpp                  | 14 ++++++++++++++
 .../naked-lambda-odr-used-captures.cpp         | 17 +++++++++++++++++
 clang/test/SemaCXX/naked-lambda-odr.cpp        | 18 ++++++++++++++++++
 4 files changed, 50 insertions(+)
 create mode 120000 clang/compile_commands.json
 create mode 100644 clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp
 create mode 100644 clang/test/SemaCXX/naked-lambda-odr.cpp

diff --git a/clang/compile_commands.json b/clang/compile_commands.json
new file mode 120000
index 0000000000000..d54ffefc90207
--- /dev/null
+++ b/clang/compile_commands.json
@@ -0,0 +1 @@
+../build/compile_commands.json
\ No newline at end of file
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index fbc2e7eb30676..86095ed3ddc29 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -2332,6 +2332,20 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc,
     maybeAddDeclWithEffects(LSI->CallOperator);
   }
 
+  // This is for GCC compatibility. If any lambda captures are actually used 
in the
+  // function body. GCC silently removes the naked attribute when captures are
+  // ODR-used, as naked functions cannot have prologues to set up the closure.
+  if (CallOperator->hasAttr<NakedAttr>() && !Captures.empty()) {
+    // If any captures are ODR-used by examining the capture list
+    // that was already analyzed during semantic analysis, drop it.
+    for (const Capture &Cap : LSI->Captures) {
+      if (Cap.isODRUsed()) {
+        CallOperator->dropAttr<NakedAttr>();
+        break;
+      }
+    }
+  }
+
   return MaybeBindToTemporary(Lambda);
 }
 
diff --git a/clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp 
b/clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp
new file mode 100644
index 0000000000000..032d0b7853cd1
--- /dev/null
+++ b/clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
+
+// Test that naked attribute is removed when captures are ODR-used (GCC compat)
+void test_odr_used_captures() {
+  int x = 42;
+  int y = 6;
+  auto l = [x, &y]() __attribute__((naked)) {
+    asm volatile("movl %0, %%eax\n\tmovl %1, %%ebx\n\tretq" : : "r"(x), 
"r"(y));
+  };
+  l();
+}
+
+// CHECK-LABEL: define internal void @"_ZZ22test_odr_used_capturesvENK3$_0clEv"
+// CHECK-NOT: naked
+// CHECK: alloca
+// CHECK: store
+
diff --git a/clang/test/SemaCXX/naked-lambda-odr.cpp 
b/clang/test/SemaCXX/naked-lambda-odr.cpp
new file mode 100644
index 0000000000000..7d019f9d99dd1
--- /dev/null
+++ b/clang/test/SemaCXX/naked-lambda-odr.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-pc-linux-gnu
+
+void uses_capture() {
+  int x = 42;
+  int y = 6;
+  auto l = [x, &y]() __attribute__((naked)) { // expected-no-diagnostics
+    asm volatile("movl %0, %%eax\n\tmovl %1, %%ebx\n\tretq" : : "r"(x), 
"r"(y));
+  };
+  l();
+}
+
+void unused_captures() {
+  int x = 42;
+  auto l = [x]() __attribute__((naked)) { // expected-no-diagnostics
+    asm volatile("retq");
+  };
+  l();
+}

>From ba6ece5cf0bd378449c19379067547c5586f187a Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Thu, 30 Oct 2025 17:21:27 +0700
Subject: [PATCH 07/12] Remove compilation database

---
 clang/compile_commands.json | 1 -
 1 file changed, 1 deletion(-)
 delete mode 120000 clang/compile_commands.json

diff --git a/clang/compile_commands.json b/clang/compile_commands.json
deleted file mode 120000
index d54ffefc90207..0000000000000
--- a/clang/compile_commands.json
+++ /dev/null
@@ -1 +0,0 @@
-../build/compile_commands.json
\ No newline at end of file

>From d57f8043be86b6c3212c6b08285ff738ce92f753 Mon Sep 17 00:00:00 2001
From: typeal <[email protected]>
Date: Thu, 30 Oct 2025 17:27:59 +0700
Subject: [PATCH 08/12] Remove FIXME in the special path

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index 58d7810e26cf5..5fc812e7eaef0 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1327,8 +1327,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
     } else if (IsInLambda && MD->isImplicitObjectMemberFunction()) {
       // Populate capture fields metadata for analysis. We skip
       // EmitInstanceProlog to avoid emitting prologue code.
-      // FIXME: Naked functions cannot access captures via LLVM IR; any access
-      // must be done manually in inline assembly.
       MD->getParent()->getCaptureFields(LambdaCaptureFields,
                                         LambdaThisCaptureField);
     }

>From 02ce067ebdb0047561adfd9cc7f34d0b724c0aa0 Mon Sep 17 00:00:00 2001
From: alcxpr <[email protected]>
Date: Thu, 25 Dec 2025 21:28:29 +0700
Subject: [PATCH 09/12] Refactor to reduce high code churn

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 80 +++++++++++++--------------
 1 file changed, 39 insertions(+), 41 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index acfeda950db5a..92ae5aebd62f1 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1281,51 +1281,49 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
 
     const FunctionDecl *FD = dyn_cast_if_present<FunctionDecl>(D);
     bool IsNaked = FD && FD->hasAttr<NakedAttr>();
-    if (!IsNaked) {
-      if (MD->isImplicitObjectMemberFunction())
-        CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
-
-      if (IsInLambda) {
-        // We're in a lambda; figure out the captures.
-        MD->getParent()->getCaptureFields(LambdaCaptureFields,
-                                          LambdaThisCaptureField);
-        if (LambdaThisCaptureField) {
-          // If the lambda captures the object referred to by '*this' - either
-          // by value or by reference, make sure CXXThisValue points to the
-          // correct object.
-
-          // Get the lvalue for the field (which is a copy of the enclosing
-          // object or contains the address of the enclosing object).
-          LValue ThisFieldLValue =
-              EmitLValueForLambdaField(LambdaThisCaptureField);
-          if (!LambdaThisCaptureField->getType()->isPointerType()) {
-            // If the enclosing object was captured by value, just use its
-            // address. Sign this pointer.
-            CXXThisValue = ThisFieldLValue.getPointer(*this);
-          } else {
-            // Load the lvalue pointed to by the field, since '*this' was
-            // captured by reference.
-            CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
-                               .getScalarVal();
-          }
+    if (!IsNaked && MD->isImplicitObjectMemberFunction())
+      CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+
+    if (!IsNaked && IsInLambda) {
+      // We're in a lambda; figure out the captures.
+      MD->getParent()->getCaptureFields(LambdaCaptureFields,
+                                        LambdaThisCaptureField);
+      if (LambdaThisCaptureField) {
+        // If the lambda captures the object referred to by '*this' - either
+        // by value or by reference, make sure CXXThisValue points to the
+        // correct object.
+
+        // Get the lvalue for the field (which is a copy of the enclosing
+        // object or contains the address of the enclosing object).
+        LValue ThisFieldLValue =
+            EmitLValueForLambdaField(LambdaThisCaptureField);
+        if (!LambdaThisCaptureField->getType()->isPointerType()) {
+          // If the enclosing object was captured by value, just use its
+          // address. Sign this pointer.
+          CXXThisValue = ThisFieldLValue.getPointer(*this);
+        } else {
+          // Load the lvalue pointed to by the field, since '*this' was
+          // captured by reference.
+          CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
+                             .getScalarVal();
         }
+      }
 
-        for (auto *FD : MD->getParent()->fields()) {
-          if (FD->hasCapturedVLAType()) {
-            auto *ExprArg =
-                EmitLoadOfLValue(EmitLValueForLambdaField(FD), 
SourceLocation())
-                    .getScalarVal();
-            auto VAT = FD->getCapturedVLAType();
-            VLASizeMap[VAT->getSizeExpr()] = ExprArg;
-          }
+      for (auto *FD : MD->getParent()->fields()) {
+        if (FD->hasCapturedVLAType()) {
+          auto *ExprArg =
+              EmitLoadOfLValue(EmitLValueForLambdaField(FD), SourceLocation())
+                  .getScalarVal();
+          auto VAT = FD->getCapturedVLAType();
+          VLASizeMap[VAT->getSizeExpr()] = ExprArg;
         }
-      } else if (MD->isImplicitObjectMemberFunction()) {
-        // Not in a lambda; just use 'this' from the method.
-        // FIXME: Should we generate a new load for each use of 'this'?  The
-        // fast register allocator would be happier...
-        CXXThisValue = CXXABIThisValue;
       }
-    } else if (IsInLambda && MD->isImplicitObjectMemberFunction()) {
+    } else if (MD->isImplicitObjectMemberFunction()) {
+      // Not in a lambda; just use 'this' from the method.
+      // FIXME: Should we generate a new load for each use of 'this'?  The
+      // fast register allocator would be happier...
+      CXXThisValue = CXXABIThisValue;
+    } else if (!IsNaked && IsInLambda && MD->isImplicitObjectMemberFunction()) 
{
       // Populate capture fields metadata for analysis. We skip
       // EmitInstanceProlog to avoid emitting prologue code.
       MD->getParent()->getCaptureFields(LambdaCaptureFields,

>From ff4549f542d3e10843b2ffe81dedfad2e31144cf Mon Sep 17 00:00:00 2001
From: alcxpr <[email protected]>
Date: Thu, 25 Dec 2025 22:59:26 +0700
Subject: [PATCH 10/12] Make ODR use in a naked lambda a downgradable error

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 +++
 clang/lib/Sema/SemaLambda.cpp                 | 12 ++++----
 .../CodeGenCXX/naked-lambda-capture-multi.cpp | 18 ------------
 .../CodeGenCXX/naked-lambda-capture-this.cpp  | 28 -------------------
 .../CodeGenCXX/naked-lambda-capture-var.cpp   | 21 --------------
 .../naked-lambda-odr-used-captures.cpp        | 17 -----------
 clang/test/CodeGenCXX/naked-lambda.cpp        |  8 ++----
 clang/test/SemaCXX/naked-lambda-odr.cpp       | 16 +++--------
 8 files changed, 18 insertions(+), 106 deletions(-)
 delete mode 100644 clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp
 delete mode 100644 clang/test/CodeGenCXX/naked-lambda-capture-this.cpp
 delete mode 100644 clang/test/CodeGenCXX/naked-lambda-capture-var.cpp
 delete mode 100644 clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6c6a26614ad0e..d24b00c5c5c26 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11513,6 +11513,10 @@ def err_asm_naked_this_ref : Error<
   "'this' pointer references not allowed in naked functions">;
 def err_asm_naked_parm_ref : Error<
   "parameter references not allowed in naked functions">;
+def err_naked_attribute_on_lambda_with_captures
+    : Warning<"naked attribute is incompatible with lambda captures">,
+      InGroup<DiagGroup<"naked-lambda-captures">>,
+      DefaultError;
 
 // OpenCL warnings and errors.
 def err_invalid_astype_of_different_size : Error<
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 93a371676ddbb..09802f83e98a9 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -2333,14 +2333,16 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation 
StartLoc,
     maybeAddDeclWithEffects(LSI->CallOperator);
   }
 
-  // This is for GCC compatibility. If any lambda captures are actually used 
in the
-  // function body. GCC silently removes the naked attribute when captures are
-  // ODR-used, as naked functions cannot have prologues to set up the closure.
+  // Naked functions cannot have prologues to set up lambda captures.
+  // GCC silently removes the naked attribute when captures are ODR-used;
+  // we emit an error instead to catch this at compile time.
   if (CallOperator->hasAttr<NakedAttr>() && !Captures.empty()) {
-    // If any captures are ODR-used by examining the capture list
-    // that was already analyzed during semantic analysis, drop it.
+    // Check if any captures are ODR-used by examining the capture list
+    // that was already analyzed during semantic analysis.
     for (const Capture &Cap : LSI->Captures) {
       if (Cap.isODRUsed()) {
+        Diag(CallOperator->getAttr<NakedAttr>()->getLocation(),
+             diag::err_naked_attribute_on_lambda_with_captures);
         CallOperator->dropAttr<NakedAttr>();
         break;
       }
diff --git a/clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp 
b/clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp
deleted file mode 100644
index de52d6dec77e9..0000000000000
--- a/clang/test/CodeGenCXX/naked-lambda-capture-multi.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
-
-void test_naked_lambda_capture_multi() {
-  int x = 42;
-  int y = 100;
-  auto l = [&x, y]() __attribute__((naked)) {
-    asm volatile("retq");
-  };
-  l();
-}
-
-// CHECK-LABEL: define {{.*}} 
@"_ZZ31test_naked_lambda_capture_multivENK3$_0clEv"
-// CHECK-NOT: load i32
-// CHECK-NOT: load ptr
-// CHECK-NOT: getelementptr
-// CHECK-NOT: alloca
-// CHECK: call void asm sideeffect "retq"
-// CHECK-NEXT: unreachable
diff --git a/clang/test/CodeGenCXX/naked-lambda-capture-this.cpp 
b/clang/test/CodeGenCXX/naked-lambda-capture-this.cpp
deleted file mode 100644
index c6bcd2f83b8eb..0000000000000
--- a/clang/test/CodeGenCXX/naked-lambda-capture-this.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S %s -o - | FileCheck %s 
--check-prefix=ASM
-
-struct S {
-  int member;
-  void test_naked_lambda_capture_this() {
-    auto l = [this]() __attribute__((naked)) {
-      asm volatile("retq");
-    };
-    l();
-  }
-};
-
-void test() {
-  S s;
-  s.test_naked_lambda_capture_this();
-}
-
-// CHECK-LABEL: define {{.*}} 
@_ZZN1S30test_naked_lambda_capture_thisEvENKUlvE_clEv
-// CHECK-NOT: load ptr
-// CHECK-NOT: getelementptr
-// CHECK-NOT: alloca
-// CHECK: call void asm sideeffect "retq"
-
-// ASM-LABEL: _ZZN1S30test_naked_lambda_capture_thisEvENKUlvE_clEv:
-// ASM-NOT: push
-// ASM-NOT: mov
-// ASM: retq
diff --git a/clang/test/CodeGenCXX/naked-lambda-capture-var.cpp 
b/clang/test/CodeGenCXX/naked-lambda-capture-var.cpp
deleted file mode 100644
index 543c38bd5ab45..0000000000000
--- a/clang/test/CodeGenCXX/naked-lambda-capture-var.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S %s -o - | FileCheck %s 
--check-prefix=ASM
-
-void test_naked_lambda_capture_var() {
-  int x = 42;
-  auto l = [x]() __attribute__((naked)) {
-    asm volatile("retq");
-  };
-  l();
-}
-
-// CHECK-LABEL: define {{.*}} @"_ZZ29test_naked_lambda_capture_varvENK3$_0clEv"
-// CHECK-NOT: load i32
-// CHECK-NOT: alloca
-// CHECK-NOT: getelementptr
-// CHECK: call void asm sideeffect "retq"
-
-// ASM-LABEL: _ZZ29test_naked_lambda_capture_varvENK3$_0clEv:
-// ASM-NOT: push
-// ASM-NOT: mov
-// ASM: retq
diff --git a/clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp 
b/clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp
deleted file mode 100644
index 032d0b7853cd1..0000000000000
--- a/clang/test/CodeGenCXX/naked-lambda-odr-used-captures.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
-
-// Test that naked attribute is removed when captures are ODR-used (GCC compat)
-void test_odr_used_captures() {
-  int x = 42;
-  int y = 6;
-  auto l = [x, &y]() __attribute__((naked)) {
-    asm volatile("movl %0, %%eax\n\tmovl %1, %%ebx\n\tretq" : : "r"(x), 
"r"(y));
-  };
-  l();
-}
-
-// CHECK-LABEL: define internal void @"_ZZ22test_odr_used_capturesvENK3$_0clEv"
-// CHECK-NOT: naked
-// CHECK: alloca
-// CHECK: store
-
diff --git a/clang/test/CodeGenCXX/naked-lambda.cpp 
b/clang/test/CodeGenCXX/naked-lambda.cpp
index c24699495c0cf..02734487e8fe6 100644
--- a/clang/test/CodeGenCXX/naked-lambda.cpp
+++ b/clang/test/CodeGenCXX/naked-lambda.cpp
@@ -1,18 +1,16 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm %s -o - | FileCheck 
%s
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -S %s -o - | FileCheck %s 
--check-prefix=ASM
 
-void test_naked_lambda() {
+void naked_lambda() {
   auto l = []() __attribute__((naked)) {
     asm volatile("retq");
   };
   l();
 }
-
-// CHECK: define internal void @"_ZZ17test_naked_lambdavENK3$_0clEv"
+// CHECK: define internal void @"_ZZ12naked_lambdavENK3$_0clEv"
 // CHECK-NOT: alloca
 // CHECK-NOT: store
-// CHECK-NOT: call void @_ZN
-// ASM-LABEL: _ZZ17test_naked_lambdavENK3$_0clEv:
+// ASM-LABEL: _ZZ12naked_lambdavENK3$_0clEv:
 // ASM-NOT: push
 // ASM-NOT: pop
 // ASM: retq
diff --git a/clang/test/SemaCXX/naked-lambda-odr.cpp 
b/clang/test/SemaCXX/naked-lambda-odr.cpp
index 7d019f9d99dd1..a9a4dcc41126d 100644
--- a/clang/test/SemaCXX/naked-lambda-odr.cpp
+++ b/clang/test/SemaCXX/naked-lambda-odr.cpp
@@ -1,17 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-pc-linux-gnu
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -verify %s
 
-void uses_capture() {
+void naked_lambda_capture() {
   int x = 42;
-  int y = 6;
-  auto l = [x, &y]() __attribute__((naked)) { // expected-no-diagnostics
-    asm volatile("movl %0, %%eax\n\tmovl %1, %%ebx\n\tretq" : : "r"(x), 
"r"(y));
-  };
-  l();
-}
-
-void unused_captures() {
-  int x = 42;
-  auto l = [x]() __attribute__((naked)) { // expected-no-diagnostics
+  auto l = [x]() __attribute__((naked)) { // expected-error {{naked attribute 
is incompatible with lambda captures}}
+    asm volatile("movl %0, %%eax" : : "r"(x));
     asm volatile("retq");
   };
   l();

>From 7b1a8e9135f433fe321ab852b651eeb1c4c4aaa1 Mon Sep 17 00:00:00 2001
From: alcxpr <[email protected]>
Date: Thu, 25 Dec 2025 23:02:15 +0700
Subject: [PATCH 11/12] Reduce diff size

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index 92ae5aebd62f1..6c2639dce34dc 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1295,17 +1295,15 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
 
         // Get the lvalue for the field (which is a copy of the enclosing
         // object or contains the address of the enclosing object).
-        LValue ThisFieldLValue =
-            EmitLValueForLambdaField(LambdaThisCaptureField);
+        LValue ThisFieldLValue = 
EmitLValueForLambdaField(LambdaThisCaptureField);
         if (!LambdaThisCaptureField->getType()->isPointerType()) {
           // If the enclosing object was captured by value, just use its
           // address. Sign this pointer.
           CXXThisValue = ThisFieldLValue.getPointer(*this);
         } else {
-          // Load the lvalue pointed to by the field, since '*this' was
-          // captured by reference.
-          CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
-                             .getScalarVal();
+          // Load the lvalue pointed to by the field, since '*this' was 
captured
+          // by reference.
+          CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, 
SourceLocation()).getScalarVal();
         }
       }
 

>From 76e1be5ce1a635f3fbde497fa8cfc07671531e69 Mon Sep 17 00:00:00 2001
From: alcxpr <[email protected]>
Date: Thu, 25 Dec 2025 23:02:53 +0700
Subject: [PATCH 12/12] Format

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index 6c2639dce34dc..2e1bd22c5a997 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1295,7 +1295,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
 
         // Get the lvalue for the field (which is a copy of the enclosing
         // object or contains the address of the enclosing object).
-        LValue ThisFieldLValue = 
EmitLValueForLambdaField(LambdaThisCaptureField);
+        LValue ThisFieldLValue =
+            EmitLValueForLambdaField(LambdaThisCaptureField);
         if (!LambdaThisCaptureField->getType()->isPointerType()) {
           // If the enclosing object was captured by value, just use its
           // address. Sign this pointer.
@@ -1303,7 +1304,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, 
QualType RetTy,
         } else {
           // Load the lvalue pointed to by the field, since '*this' was 
captured
           // by reference.
-          CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, 
SourceLocation()).getScalarVal();
+          CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
+                             .getScalarVal();
         }
       }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to