[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-01 Thread Qizhi Hu via cfe-commits

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

Try to fix [issue](https://github.com/llvm/llvm-project/issues/68490 ) and some 
extented problem. Root cause of current issue is that error handling in 
instantiation of function parameter with default initialization on sizeof or 
align expression. When instance an out-of-line template member function, depth 
of `TemplateTypeParmDecl` in default initialization doesn't change while depth 
of other template parameter does and this will lead to some template parameter 
uninstanced. Also, sometime it will leader to wrong instantiation when it uses 
the template parameter of the template class.
Fix it by add template args of context. This will make 
MultiLevelTemplateArgumentList::getNumLevels matching the depth of template 
parameter. Testcase with some static_assert demonstrates the template parameter 
has been instanced correctly.
But, the default initialization of lambda expression compiles failed when only 
checking if the member function is out-of-line. We should check the 
`PrimaryFunctionTemplateDecl` of the funtion if it's out-of-line.

>From b9360998d234cccda4f632067cc9aa62f5593021 Mon Sep 17 00:00:00 2001
From: huqizhi 
Date: Thu, 1 Feb 2024 20:54:46 +0800
Subject: [PATCH] [Clang][Sema] fix outline member function template with
 default align crash

---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  14 +-
 clang/test/SemaTemplate/default-parm-init.cpp | 190 ++
 3 files changed, 206 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaTemplate/default-parm-init.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ec9e3ef07057f..263d64d610950 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -182,6 +182,10 @@ Bug Fixes to C++ Support
   and (`#79745 `_)
 - Fix incorrect code generation caused by the object argument of ``static 
operator()`` and ``static operator[]`` calls not being evaluated.
   Fixes (`#67976 `_)
+- Fix a crash when specializing an out-of-line member function with a default
+  parameter where we did an incorrect specialization of the initialization of
+  the default parameter.
+  Fixes (`#68490 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e12186d7d82f8..c107702aeba1c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
 //   default argument expression appears.
 ContextRAII SavedContext(*this, FD);
 std::unique_ptr LIS;
+MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
 if (ForCallExpr) {
   // When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,20 @@ bool Sema::SubstDefaultArgument(
   /*ForDefinition*/ false);
   if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
 return true;
+  const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
+  if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
+TemplateArgumentList *CurrentTemplateArgumentList =
+TemplateArgumentList::CreateCopy(getASTContext(),
+ TemplateArgs.getInnermost());
+NewTemplateArgs = getTemplateInstantiationArgs(
+FD, FD->getDeclContext(), /*Final=*/false,
+CurrentTemplateArgumentList, /*RelativeToPrimary=*/true);
+  }
 }
 
 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 0..6ad69c39d93dc
--- /dev/null
+++ b/clang/test/SemaTemplate/default-parm-init.cpp
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+namespace std {
+
+template class function;
+
+template class invoker_base {
+public: 
+  virtual ~invoker_base() { } 
+  virtual R invoke(Args...) = 0; 
+  virtual invoker_base* clone() = 0;
+};
+
+template 
+class functor_invoker : public invoker_base {
+public: 
+  explicit functor_invoker(const F& f) : f(f) { } 
+  R invoke(Args... args) { return f(args...); } 
+  functor_invoker* clone() { return new functor_invoker(f); }
+
+private:
+  F f;
+};
+
+template

[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-01 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Qizhi Hu (jcsxky)


Changes

Try to fix [issue](https://github.com/llvm/llvm-project/issues/68490 ) and some 
extented problem. Root cause of current issue is that error handling in 
instantiation of function parameter with default initialization on sizeof or 
align expression. When instance an out-of-line template member function, depth 
of `TemplateTypeParmDecl` in default initialization doesn't change while depth 
of other template parameter does and this will lead to some template parameter 
uninstanced. Also, sometime it will leader to wrong instantiation when it uses 
the template parameter of the template class.
Fix it by add template args of context. This will make 
MultiLevelTemplateArgumentList::getNumLevels matching the depth of template 
parameter. Testcase with some static_assert demonstrates the template parameter 
has been instanced correctly.
But, the default initialization of lambda expression compiles failed when only 
checking if the member function is out-of-line. We should check the 
`PrimaryFunctionTemplateDecl` of the funtion if it's out-of-line.

---
Full diff: https://github.com/llvm/llvm-project/pull/80288.diff


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+4) 
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+12-2) 
- (added) clang/test/SemaTemplate/default-parm-init.cpp (+190) 


``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ec9e3ef07057f..263d64d610950 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -182,6 +182,10 @@ Bug Fixes to C++ Support
   and (`#79745 `_)
 - Fix incorrect code generation caused by the object argument of ``static 
operator()`` and ``static operator[]`` calls not being evaluated.
   Fixes (`#67976 `_)
+- Fix a crash when specializing an out-of-line member function with a default
+  parameter where we did an incorrect specialization of the initialization of
+  the default parameter.
+  Fixes (`#68490 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e12186d7d82f8..c107702aeba1c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
 //   default argument expression appears.
 ContextRAII SavedContext(*this, FD);
 std::unique_ptr LIS;
+MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
 if (ForCallExpr) {
   // When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,20 @@ bool Sema::SubstDefaultArgument(
   /*ForDefinition*/ false);
   if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
 return true;
+  const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
+  if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
+TemplateArgumentList *CurrentTemplateArgumentList =
+TemplateArgumentList::CreateCopy(getASTContext(),
+ TemplateArgs.getInnermost());
+NewTemplateArgs = getTemplateInstantiationArgs(
+FD, FD->getDeclContext(), /*Final=*/false,
+CurrentTemplateArgumentList, /*RelativeToPrimary=*/true);
+  }
 }
 
 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 0..6ad69c39d93dc
--- /dev/null
+++ b/clang/test/SemaTemplate/default-parm-init.cpp
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+namespace std {
+
+template class function;
+
+template class invoker_base {
+public: 
+  virtual ~invoker_base() { } 
+  virtual R invoke(Args...) = 0; 
+  virtual invoker_base* clone() = 0;
+};
+
+template 
+class functor_invoker : public invoker_base {
+public: 
+  explicit functor_invoker(const F& f) : f(f) { } 
+  R invoke(Args... args) { return f(args...); } 
+  functor_invoker* clone() { return new functor_invoker(f); }
+
+private:
+  F f;
+};
+
+template
+class function {
+public: 
+  typedef R result_type;
+  function() : invoker (0) { }
+  function(const function& other) : invoker(0) { 
+if (other.invoker)
+  invoker = other.invoker->clone();
+  }
+
+  template function(const F& f) :

[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-01 Thread Qizhi Hu via cfe-commits

jcsxky wrote:

details:
```cpp
template
constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));

template <>
template
constexpr int Problem::FuncAlign(int param) { // depth of 
FunctionTemplateParam in default 
   // initialization of  
alignof(FunctionTemplateParam) is still 1
return param;
}
```
Add template instantiation args of context(`TemplateClassSpecialize`) to 
`MultiLevelTemplateArgumentList` and level of `MultiLevelTemplateArgumentList` 
is 2, and make `alignof(FunctionTemplateParam)` instantiated successfully. 

```cpp
void run(
std::function f1 = [](auto&&) {},
std::function f2 = [](auto&&) {});
template 
void A::run(std::function f1,
   std::function f2) {
  Helper h(f2);
}
```
Here we can't add template instantiation args of context because level of 
`MultiLevelTemplateArgumentList` in this case is 2 and it's the same with depth 
of `auto&&` . This remind us make the condition 
```cpp
const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
if (PrimaryTemplate && PrimaryTemplate->isOutOfLine())
```
I think this should distinguish the first case from others.

https://github.com/llvm/llvm-project/pull/80288
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-01 Thread Qizhi Hu via cfe-commits

https://github.com/jcsxky updated 
https://github.com/llvm/llvm-project/pull/80288

>From 3d7adb18e15668216f39b2ba757b7b52bca99812 Mon Sep 17 00:00:00 2001
From: huqizhi 
Date: Thu, 1 Feb 2024 20:54:46 +0800
Subject: [PATCH] [Clang][Sema] fix outline member function template with
 default align crash

---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  14 +-
 clang/test/SemaTemplate/default-parm-init.cpp | 190 ++
 3 files changed, 206 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaTemplate/default-parm-init.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ec9e3ef07057f..263d64d610950 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -182,6 +182,10 @@ Bug Fixes to C++ Support
   and (`#79745 `_)
 - Fix incorrect code generation caused by the object argument of ``static 
operator()`` and ``static operator[]`` calls not being evaluated.
   Fixes (`#67976 `_)
+- Fix a crash when specializing an out-of-line member function with a default
+  parameter where we did an incorrect specialization of the initialization of
+  the default parameter.
+  Fixes (`#68490 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e12186d7d82f8..c107702aeba1c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
 //   default argument expression appears.
 ContextRAII SavedContext(*this, FD);
 std::unique_ptr LIS;
+MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
 if (ForCallExpr) {
   // When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,20 @@ bool Sema::SubstDefaultArgument(
   /*ForDefinition*/ false);
   if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
 return true;
+  const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
+  if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
+TemplateArgumentList *CurrentTemplateArgumentList =
+TemplateArgumentList::CreateCopy(getASTContext(),
+ TemplateArgs.getInnermost());
+NewTemplateArgs = getTemplateInstantiationArgs(
+FD, FD->getDeclContext(), /*Final=*/false,
+CurrentTemplateArgumentList, /*RelativeToPrimary=*/true);
+  }
 }
 
 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 0..0d17c4d0b143a
--- /dev/null
+++ b/clang/test/SemaTemplate/default-parm-init.cpp
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+namespace std {
+
+template class function;
+
+template class invoker_base {
+public: 
+  virtual ~invoker_base() { } 
+  virtual R invoke(Args...) = 0; 
+  virtual invoker_base* clone() = 0;
+};
+
+template 
+class functor_invoker : public invoker_base {
+public: 
+  explicit functor_invoker(const F& f) : f(f) { } 
+  R invoke(Args... args) { return f(args...); } 
+  functor_invoker* clone() { return new functor_invoker(f); }
+
+private:
+  F f;
+};
+
+template
+class function {
+public: 
+  typedef R result_type;
+  function() : invoker (0) { }
+  function(const function& other) : invoker(0) { 
+if (other.invoker)
+  invoker = other.invoker->clone();
+  }
+
+  template function(const F& f) : invoker(0) {
+invoker = new functor_invoker(f);
+  }
+
+  ~function() { 
+if (invoker)
+  delete invoker;
+  }
+
+  function& operator=(const function& other) { 
+function(other).swap(*this); 
+return *this;
+  }
+
+  template 
+  function& operator=(const F& f) {
+function(f).swap(*this); 
+return *this;
+  }
+
+  void swap(function& other) { 
+invoker_base* tmp = invoker; 
+invoker = other.invoker; 
+other.invoker = tmp;
+  }
+
+  result_type operator()(Args... args) const { 
+return invoker->invoke(args...);
+  }
+
+private: 
+  invoker_base* invoker;
+};
+
+}
+
+template
+struct Problem{
+  template
+  constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));
+
+  template
+  constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam));
+

[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-01 Thread Qizhi Hu via cfe-commits

https://github.com/jcsxky updated 
https://github.com/llvm/llvm-project/pull/80288

>From 88c382b0af1ebc76e5d80d36ddb5345e0bc9f676 Mon Sep 17 00:00:00 2001
From: huqizhi 
Date: Thu, 1 Feb 2024 20:54:46 +0800
Subject: [PATCH] [Clang][Sema] fix outline member function template with
 default align crash

---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  14 +-
 clang/test/SemaTemplate/default-parm-init.cpp | 190 ++
 3 files changed, 206 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaTemplate/default-parm-init.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 53040aa0f9074..8efdbf65abc19 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -188,6 +188,10 @@ Bug Fixes to C++ Support
   and (`#79745 `_)
 - Fix incorrect code generation caused by the object argument of ``static 
operator()`` and ``static operator[]`` calls not being evaluated.
   Fixes (`#67976 `_)
+- Fix a crash when specializing an out-of-line member function with a default
+  parameter where we did an incorrect specialization of the initialization of
+  the default parameter.
+  Fixes (`#68490 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 01b78e4424fb5..bff7960578875 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
 //   default argument expression appears.
 ContextRAII SavedContext(*this, FD);
 std::unique_ptr LIS;
+MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
 if (ForCallExpr) {
   // When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,20 @@ bool Sema::SubstDefaultArgument(
   /*ForDefinition*/ false);
   if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
 return true;
+  const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
+  if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
+TemplateArgumentList *CurrentTemplateArgumentList =
+TemplateArgumentList::CreateCopy(getASTContext(),
+ TemplateArgs.getInnermost());
+NewTemplateArgs = getTemplateInstantiationArgs(
+FD, FD->getDeclContext(), /*Final=*/false,
+CurrentTemplateArgumentList, /*RelativeToPrimary=*/true);
+  }
 }
 
 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 0..73ba8998df6a9
--- /dev/null
+++ b/clang/test/SemaTemplate/default-parm-init.cpp
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+namespace std {
+
+template class function;
+
+template class invoker_base {
+public: 
+  virtual ~invoker_base() { } 
+  virtual R invoke(Args...) = 0; 
+  virtual invoker_base* clone() = 0;
+};
+
+template 
+class functor_invoker : public invoker_base {
+public: 
+  explicit functor_invoker(const F& f) : f(f) { } 
+  R invoke(Args... args) { return f(args...); } 
+  functor_invoker* clone() { return new functor_invoker(f); }
+
+private:
+  F f;
+};
+
+template
+class function {
+public: 
+  typedef R result_type;
+  function() : invoker (0) { }
+  function(const function& other) : invoker(0) { 
+if (other.invoker)
+  invoker = other.invoker->clone();
+  }
+
+  template function(const F& f) : invoker(0) {
+invoker = new functor_invoker(f);
+  }
+
+  ~function() { 
+if (invoker)
+  delete invoker;
+  }
+
+  function& operator=(const function& other) { 
+function(other).swap(*this); 
+return *this;
+  }
+
+  template 
+  function& operator=(const F& f) {
+function(f).swap(*this); 
+return *this;
+  }
+
+  void swap(function& other) { 
+invoker_base* tmp = invoker; 
+invoker = other.invoker; 
+other.invoker = tmp;
+  }
+
+  result_type operator()(Args... args) const { 
+return invoker->invoke(args...);
+  }
+
+private: 
+  invoker_base* invoker;
+};
+
+}
+
+template
+struct Problem {
+  template
+  constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));
+
+  template
+  constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam));

[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-01 Thread Qizhi Hu via cfe-commits

https://github.com/jcsxky updated 
https://github.com/llvm/llvm-project/pull/80288

>From 329e78b18bf83fe984cc1ff8830f5a8be8cf3f7b Mon Sep 17 00:00:00 2001
From: huqizhi 
Date: Thu, 1 Feb 2024 20:54:46 +0800
Subject: [PATCH] [Clang][Sema] fix outline member function template with
 default align crash

---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  14 +-
 clang/test/SemaTemplate/default-parm-init.cpp | 190 ++
 3 files changed, 206 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaTemplate/default-parm-init.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 53040aa0f9074..8efdbf65abc19 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -188,6 +188,10 @@ Bug Fixes to C++ Support
   and (`#79745 `_)
 - Fix incorrect code generation caused by the object argument of ``static 
operator()`` and ``static operator[]`` calls not being evaluated.
   Fixes (`#67976 `_)
+- Fix a crash when specializing an out-of-line member function with a default
+  parameter where we did an incorrect specialization of the initialization of
+  the default parameter.
+  Fixes (`#68490 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 01b78e4424fb5..e5999fa50117e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
 //   default argument expression appears.
 ContextRAII SavedContext(*this, FD);
 std::unique_ptr LIS;
+MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
 if (ForCallExpr) {
   // When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,20 @@ bool Sema::SubstDefaultArgument(
   /*ForDefinition*/ false);
   if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
 return true;
+  const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
+  if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
+TemplateArgumentList *CurrentTemplateArgumentList =
+TemplateArgumentList::CreateCopy(getASTContext(),
+ TemplateArgs.getInnermost());
+NewTemplateArgs = getTemplateInstantiationArgs(
+FD, FD->getDeclContext(), /*Final=*/false,
+CurrentTemplateArgumentList->asArray(), 
/*RelativeToPrimary=*/true);
+  }
 }
 
 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 0..73ba8998df6a9
--- /dev/null
+++ b/clang/test/SemaTemplate/default-parm-init.cpp
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+namespace std {
+
+template class function;
+
+template class invoker_base {
+public: 
+  virtual ~invoker_base() { } 
+  virtual R invoke(Args...) = 0; 
+  virtual invoker_base* clone() = 0;
+};
+
+template 
+class functor_invoker : public invoker_base {
+public: 
+  explicit functor_invoker(const F& f) : f(f) { } 
+  R invoke(Args... args) { return f(args...); } 
+  functor_invoker* clone() { return new functor_invoker(f); }
+
+private:
+  F f;
+};
+
+template
+class function {
+public: 
+  typedef R result_type;
+  function() : invoker (0) { }
+  function(const function& other) : invoker(0) { 
+if (other.invoker)
+  invoker = other.invoker->clone();
+  }
+
+  template function(const F& f) : invoker(0) {
+invoker = new functor_invoker(f);
+  }
+
+  ~function() { 
+if (invoker)
+  delete invoker;
+  }
+
+  function& operator=(const function& other) { 
+function(other).swap(*this); 
+return *this;
+  }
+
+  template 
+  function& operator=(const F& f) {
+function(f).swap(*this); 
+return *this;
+  }
+
+  void swap(function& other) { 
+invoker_base* tmp = invoker; 
+invoker = other.invoker; 
+other.invoker = tmp;
+  }
+
+  result_type operator()(Args... args) const { 
+return invoker->invoke(args...);
+  }
+
+private: 
+  invoker_base* invoker;
+};
+
+}
+
+template
+struct Problem {
+  template
+  constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));
+
+  template
+  constexpr int FuncSizeof(int param = sizeof(FunctionTempl

[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-02 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.


https://github.com/llvm/llvm-project/pull/80288
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-03 Thread Qizhi Hu via cfe-commits

https://github.com/jcsxky updated 
https://github.com/llvm/llvm-project/pull/80288

>From cfcffbfa15959963b2b91078ec1911504811d3c1 Mon Sep 17 00:00:00 2001
From: huqizhi 
Date: Thu, 1 Feb 2024 20:54:46 +0800
Subject: [PATCH] [Clang][Sema] fix outline member function template with
 default align crash

---
 clang/docs/ReleaseNotes.rst   |   4 +
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  14 +-
 clang/test/SemaTemplate/default-parm-init.cpp | 190 ++
 3 files changed, 206 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaTemplate/default-parm-init.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e634db3c718c9..3596109bf044f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -197,6 +197,10 @@ Bug Fixes to C++ Support
   Fixes (`#67976 `_)
 - Fix crash and diagnostic with const qualified member operator new.
   Fixes (`#79748 `_)
+- Fix a crash when specializing an out-of-line member function with a default
+  parameter where we did an incorrect specialization of the initialization of
+  the default parameter.
+  Fixes (`#68490 `_)
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 01b78e4424fb5..e5999fa50117e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
 //   default argument expression appears.
 ContextRAII SavedContext(*this, FD);
 std::unique_ptr LIS;
+MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
 if (ForCallExpr) {
   // When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,20 @@ bool Sema::SubstDefaultArgument(
   /*ForDefinition*/ false);
   if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
 return true;
+  const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
+  if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
+TemplateArgumentList *CurrentTemplateArgumentList =
+TemplateArgumentList::CreateCopy(getASTContext(),
+ TemplateArgs.getInnermost());
+NewTemplateArgs = getTemplateInstantiationArgs(
+FD, FD->getDeclContext(), /*Final=*/false,
+CurrentTemplateArgumentList->asArray(), 
/*RelativeToPrimary=*/true);
+  }
 }
 
 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 0..73ba8998df6a9
--- /dev/null
+++ b/clang/test/SemaTemplate/default-parm-init.cpp
@@ -0,0 +1,190 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+namespace std {
+
+template class function;
+
+template class invoker_base {
+public: 
+  virtual ~invoker_base() { } 
+  virtual R invoke(Args...) = 0; 
+  virtual invoker_base* clone() = 0;
+};
+
+template 
+class functor_invoker : public invoker_base {
+public: 
+  explicit functor_invoker(const F& f) : f(f) { } 
+  R invoke(Args... args) { return f(args...); } 
+  functor_invoker* clone() { return new functor_invoker(f); }
+
+private:
+  F f;
+};
+
+template
+class function {
+public: 
+  typedef R result_type;
+  function() : invoker (0) { }
+  function(const function& other) : invoker(0) { 
+if (other.invoker)
+  invoker = other.invoker->clone();
+  }
+
+  template function(const F& f) : invoker(0) {
+invoker = new functor_invoker(f);
+  }
+
+  ~function() { 
+if (invoker)
+  delete invoker;
+  }
+
+  function& operator=(const function& other) { 
+function(other).swap(*this); 
+return *this;
+  }
+
+  template 
+  function& operator=(const F& f) {
+function(f).swap(*this); 
+return *this;
+  }
+
+  void swap(function& other) { 
+invoker_base* tmp = invoker; 
+invoker = other.invoker; 
+other.invoker = tmp;
+  }
+
+  result_type operator()(Args... args) const { 
+return invoker->invoke(args...);
+  }
+
+private: 
+  invoker_base* invoker;
+};
+
+}
+
+template
+struct Problem {
+  template
+  constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));
+
+  template
+  constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam));
+
+  template
+  constexpr int FuncAlign2(int param = alig

[clang] [Clang][Sema] fix outline member function template with default align crash (PR #80288)

2024-02-03 Thread Qizhi Hu via cfe-commits

https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/80288
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits