[clang] 7b33899 - [Clang][Sema] fix outline member function template with default align crash (#78400)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 25 22:46:46 PST 2024


Author: Qizhi Hu
Date: 2024-01-26T14:46:42+08:00
New Revision: 7b3389980ddbd84f72ccc4776889c67519cc2c14

URL: https://github.com/llvm/llvm-project/commit/7b3389980ddbd84f72ccc4776889c67519cc2c14
DIFF: https://github.com/llvm/llvm-project/commit/7b3389980ddbd84f72ccc4776889c67519cc2c14.diff

LOG: [Clang][Sema] fix outline member function template with default align crash (#78400)

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 class.
Fix it by add template args of context when it's out-of-line. This will
make `MultiLevelTemplateArgumentList::getNumLevels` matching the depth
of template parameter. Testcase with some `static_assert` demonstrates
the template parameter has been instanced correctly.

Co-authored-by: huqizhi <836744285 at qq.com>

Added: 
    clang/test/SemaTemplate/default-parm-init.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaTemplateInstantiate.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c441baf2d741623..5330cd9caad8011 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -115,6 +115,10 @@ Bug Fixes to C++ Support
 
 - Fix crash when using lifetimebound attribute in function with trailing return.
   Fixes (`#73619 <https://github.com/llvm/llvm-project/issues/73619>`_)
+- 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 <https://github.com/llvm/llvm-project/issues/68490>`_)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index e12186d7d82f8d0..41e58b91de4e08e 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<LocalInstantiationScope> LIS;
+    MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
     if (ForCallExpr) {
       // When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,19 @@ bool Sema::SubstDefaultArgument(
           /*ForDefinition*/ false);
       if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
         return true;
+      if (FD->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 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));
+}


        


More information about the cfe-commits mailing list