diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c441baf2d7416..5330cd9caad80 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 `_) +- 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..41e58b91de4e0 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,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 0000000000000..4bcea7eaa1017 --- /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 +struct Problem{ + template + constexpr int FuncAlign(int param = alignof(FunctionTemplateParam)); + + template + constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam)); + + template + constexpr int FuncAlign2(int param = alignof(TemplateParam)); + + template + constexpr int FuncSizeof2(int param = sizeof(TemplateParam)); +}; + +template <> +template +constexpr int Problem::FuncAlign(int param) { + return param; +} + +template <> +template +constexpr int Problem::FuncSizeof(int param) { + return param; +} + +template <> +template +constexpr int Problem::FuncAlign2(int param) { + return param; +} + +template <> +template +constexpr int Problem::FuncSizeof2(int param) { + return param; +} + +int main(){ + Problem p = {}; + static_assert(p.FuncAlign() == alignof(char)); + static_assert(p.FuncSizeof() == sizeof(char)); + static_assert(p.FuncAlign2() == alignof(int)); + static_assert(p.FuncSizeof2() == sizeof(int)); +}