Skip to content

Commit 7b33899

Browse files
authored
[Clang][Sema] fix outline member function template with default align crash (#78400)
Try to fix [issue](#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 <[email protected]>
1 parent 02d5680 commit 7b33899

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ Bug Fixes to C++ Support
115115

116116
- Fix crash when using lifetimebound attribute in function with trailing return.
117117
Fixes (`#73619 <https://github.com/llvm/llvm-project/issues/73619>`_)
118+
- Fix a crash when specializing an out-of-line member function with a default
119+
parameter where we did an incorrect specialization of the initialization of
120+
the default parameter.
121+
Fixes (`#68490 <https://github.com/llvm/llvm-project/issues/68490>`_)
118122

119123
Bug Fixes to AST Handling
120124
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
30493049
// default argument expression appears.
30503050
ContextRAII SavedContext(*this, FD);
30513051
std::unique_ptr<LocalInstantiationScope> LIS;
3052+
MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
30523053

30533054
if (ForCallExpr) {
30543055
// When instantiating a default argument due to use in a call expression,
@@ -3061,11 +3062,19 @@ bool Sema::SubstDefaultArgument(
30613062
/*ForDefinition*/ false);
30623063
if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
30633064
return true;
3065+
if (FD->isOutOfLine()) {
3066+
TemplateArgumentList *CurrentTemplateArgumentList =
3067+
TemplateArgumentList::CreateCopy(getASTContext(),
3068+
TemplateArgs.getInnermost());
3069+
NewTemplateArgs = getTemplateInstantiationArgs(
3070+
FD, FD->getDeclContext(), /*Final=*/false,
3071+
CurrentTemplateArgumentList, /*RelativeToPrimary=*/true);
3072+
}
30643073
}
30653074

30663075
runWithSufficientStackSpace(Loc, [&] {
3067-
Result = SubstInitializer(PatternExpr, TemplateArgs,
3068-
/*DirectInit*/false);
3076+
Result = SubstInitializer(PatternExpr, NewTemplateArgs,
3077+
/*DirectInit*/ false);
30693078
});
30703079
}
30713080
if (Result.isInvalid())
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
2+
// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
3+
// expected-no-diagnostics
4+
5+
template<typename TemplateParam>
6+
struct Problem{
7+
template<typename FunctionTemplateParam>
8+
constexpr int FuncAlign(int param = alignof(FunctionTemplateParam));
9+
10+
template<typename FunctionTemplateParam>
11+
constexpr int FuncSizeof(int param = sizeof(FunctionTemplateParam));
12+
13+
template<typename FunctionTemplateParam>
14+
constexpr int FuncAlign2(int param = alignof(TemplateParam));
15+
16+
template<typename FunctionTemplateParam>
17+
constexpr int FuncSizeof2(int param = sizeof(TemplateParam));
18+
};
19+
20+
template <>
21+
template<typename FunctionTemplateParam>
22+
constexpr int Problem<int>::FuncAlign(int param) {
23+
return param;
24+
}
25+
26+
template <>
27+
template<typename FunctionTemplateParam>
28+
constexpr int Problem<int>::FuncSizeof(int param) {
29+
return param;
30+
}
31+
32+
template <>
33+
template<typename FunctionTemplateParam>
34+
constexpr int Problem<int>::FuncAlign2(int param) {
35+
return param;
36+
}
37+
38+
template <>
39+
template<typename FunctionTemplateParam>
40+
constexpr int Problem<int>::FuncSizeof2(int param) {
41+
return param;
42+
}
43+
44+
int main(){
45+
Problem<int> p = {};
46+
static_assert(p.FuncAlign<char>() == alignof(char));
47+
static_assert(p.FuncSizeof<char>() == sizeof(char));
48+
static_assert(p.FuncAlign2<char>() == alignof(int));
49+
static_assert(p.FuncSizeof2<char>() == sizeof(int));
50+
}

0 commit comments

Comments
 (0)