[clang] [Clang][AST] fix crash in mangle lambda expression (PR #78896)

Qizhi Hu via cfe-commits cfe-commits at lists.llvm.org
Sun Jan 21 04:37:32 PST 2024


https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/78896

Try to fix [issue](https://github.com/llvm/llvm-project/issues/78542) by creating a new `FunctionTypeDepthState` and pop it after finish.

>From e4ac395028e651721677d85caf6c76e3a7f79308 Mon Sep 17 00:00:00 2001
From: huqizhi <huqizhi at feysh.com>
Date: Wed, 17 Jan 2024 14:16:34 +0800
Subject: [PATCH 1/2] [Clang][Sema] fix outline member function template with
 default align crash

---
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 12 ++++-
 clang/test/SemaTemplate/default-parm-init.cpp | 50 +++++++++++++++++++
 2 files changed, 60 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaTemplate/default-parm-init.cpp

diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index fc80515b45e35b4..1ed63db75294aab 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3051,6 +3051,7 @@ bool Sema::SubstDefaultArgument(
     //   default argument expression appears.
     ContextRAII SavedContext(*this, FD);
     std::unique_ptr<LocalInstantiationScope> LIS;
+    auto NewTemplateArgs = TemplateArgs;
 
     if (ForCallExpr) {
       // When instantiating a default argument due to use in a call expression,
@@ -3063,11 +3064,18 @@ bool Sema::SubstDefaultArgument(
           /*ForDefinition*/ false);
       if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
         return true;
+      if (FD->isOutOfLine()) {
+        auto *CurrentTemplateArgumentList = TemplateArgumentList::CreateCopy(
+            getASTContext(), TemplateArgs.getInnermost());
+        NewTemplateArgs = getTemplateInstantiationArgs(
+            FD, FD->getDeclContext(), true, CurrentTemplateArgumentList, true,
+            nullptr, false, false);
+      }
     }
 
     runWithSufficientStackSpace(Loc, [&] {
-      Result = SubstInitializer(PatternExpr, TemplateArgs,
-                                /*DirectInit*/false);
+      Result = SubstInitializer(PatternExpr, NewTemplateArgs,
+                                /*DirectInit*/ false);
     });
   }
   if (Result.isInvalid())
diff --git a/clang/test/SemaTemplate/default-parm-init.cpp b/clang/test/SemaTemplate/default-parm-init.cpp
new file mode 100644
index 000000000000000..4bcea7eaa101763
--- /dev/null
+++ b/clang/test/SemaTemplate/default-parm-init.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+template<typename TemplateParam>
+struct Problem{
+  template<typename FunctionTemplateParam>
+  constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));
+
+  template<typename FunctionTemplateParam>
+  constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam));
+
+  template<typename FunctionTemplateParam>
+  constexpr int FuncAlign2(int param = alignof(TemplateParam));
+
+  template<typename FunctionTemplateParam>
+  constexpr int FuncSizeof2(int param = sizeof(TemplateParam));
+};
+
+template <>
+template<typename FunctionTemplateParam>
+constexpr int Problem<int>::FuncAlign(int param) {
+	return param;
+}
+
+template <>
+template<typename FunctionTemplateParam>
+constexpr int Problem<int>::FuncSizeof(int param) {
+	return param;
+}
+
+template <>
+template<typename FunctionTemplateParam>
+constexpr int Problem<int>::FuncAlign2(int param) {
+	return param;
+}
+
+template <>
+template<typename FunctionTemplateParam>
+constexpr int Problem<int>::FuncSizeof2(int param) {
+	return param;
+}
+
+int main(){
+    Problem<int> p = {};
+    static_assert(p.FuncAlign<char>() == alignof(char));
+    static_assert(p.FuncSizeof<char>() == sizeof(char));
+    static_assert(p.FuncAlign2<char>() == alignof(int));
+    static_assert(p.FuncSizeof2<char>() == sizeof(int));
+}

>From f8081d2120b9fd60d0ec1dcadd8d8fcb2334ce37 Mon Sep 17 00:00:00 2001
From: huqizhi <huqizhi at feysh.com>
Date: Sun, 21 Jan 2024 20:30:06 +0800
Subject: [PATCH 2/2] [Clang] fix crash in mangle lambda expression

---
 clang/lib/AST/ItaniumMangle.cpp               |  2 +
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 12 +----
 .../AST/mangle-lambda-expression-no-crash.cpp |  5 ++
 clang/test/SemaTemplate/default-parm-init.cpp | 50 -------------------
 4 files changed, 9 insertions(+), 60 deletions(-)
 create mode 100644 clang/test/AST/mangle-lambda-expression-no-crash.cpp
 delete mode 100644 clang/test/SemaTemplate/default-parm-init.cpp

diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index b1678479888eb77..20f1ec969155a8b 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2128,6 +2128,7 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
 }
 
 void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {
+  FunctionTypeDepthState saved = FunctionTypeDepth.push();
   // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/31.
   for (auto *D : Lambda->getLambdaExplicitTemplateParameters())
     mangleTemplateParamDecl(D);
@@ -2140,6 +2141,7 @@ void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {
       Lambda->getLambdaTypeInfo()->getType()->castAs<FunctionProtoType>();
   mangleBareFunctionType(Proto, /*MangleReturnType=*/false,
                          Lambda->getLambdaStaticInvoker());
+  FunctionTypeDepth.pop(saved);
 }
 
 void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 1ed63db75294aab..fc80515b45e35b4 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3051,7 +3051,6 @@ bool Sema::SubstDefaultArgument(
     //   default argument expression appears.
     ContextRAII SavedContext(*this, FD);
     std::unique_ptr<LocalInstantiationScope> LIS;
-    auto NewTemplateArgs = TemplateArgs;
 
     if (ForCallExpr) {
       // When instantiating a default argument due to use in a call expression,
@@ -3064,18 +3063,11 @@ bool Sema::SubstDefaultArgument(
           /*ForDefinition*/ false);
       if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
         return true;
-      if (FD->isOutOfLine()) {
-        auto *CurrentTemplateArgumentList = TemplateArgumentList::CreateCopy(
-            getASTContext(), TemplateArgs.getInnermost());
-        NewTemplateArgs = getTemplateInstantiationArgs(
-            FD, FD->getDeclContext(), true, CurrentTemplateArgumentList, true,
-            nullptr, false, false);
-      }
     }
 
     runWithSufficientStackSpace(Loc, [&] {
-      Result = SubstInitializer(PatternExpr, NewTemplateArgs,
-                                /*DirectInit*/ false);
+      Result = SubstInitializer(PatternExpr, TemplateArgs,
+                                /*DirectInit*/false);
     });
   }
   if (Result.isInvalid())
diff --git a/clang/test/AST/mangle-lambda-expression-no-crash.cpp b/clang/test/AST/mangle-lambda-expression-no-crash.cpp
new file mode 100644
index 000000000000000..8727e99b9bf64dd
--- /dev/null
+++ b/clang/test/AST/mangle-lambda-expression-no-crash.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+auto ICE = [](auto a) { return [=]<decltype(a) b>() { return 1; }; };
diff --git a/clang/test/SemaTemplate/default-parm-init.cpp b/clang/test/SemaTemplate/default-parm-init.cpp
deleted file mode 100644
index 4bcea7eaa101763..000000000000000
--- a/clang/test/SemaTemplate/default-parm-init.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
-// expected-no-diagnostics
-
-template<typename TemplateParam>
-struct Problem{
-  template<typename FunctionTemplateParam>
-  constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));
-
-  template<typename FunctionTemplateParam>
-  constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam));
-
-  template<typename FunctionTemplateParam>
-  constexpr int FuncAlign2(int param = alignof(TemplateParam));
-
-  template<typename FunctionTemplateParam>
-  constexpr int FuncSizeof2(int param = sizeof(TemplateParam));
-};
-
-template <>
-template<typename FunctionTemplateParam>
-constexpr int Problem<int>::FuncAlign(int param) {
-	return param;
-}
-
-template <>
-template<typename FunctionTemplateParam>
-constexpr int Problem<int>::FuncSizeof(int param) {
-	return param;
-}
-
-template <>
-template<typename FunctionTemplateParam>
-constexpr int Problem<int>::FuncAlign2(int param) {
-	return param;
-}
-
-template <>
-template<typename FunctionTemplateParam>
-constexpr int Problem<int>::FuncSizeof2(int param) {
-	return param;
-}
-
-int main(){
-    Problem<int> p = {};
-    static_assert(p.FuncAlign<char>() == alignof(char));
-    static_assert(p.FuncSizeof<char>() == sizeof(char));
-    static_assert(p.FuncAlign2<char>() == alignof(int));
-    static_assert(p.FuncSizeof2<char>() == sizeof(int));
-}



More information about the cfe-commits mailing list