Skip to content

Commit 9daf10f

Browse files
authored
Reland [Clang] skip default argument instantiation for non-defining friend declarations to meet [dcl.fct.default] p4 (#115487)
This fixes a crash when instantiating default arguments for templated friend function declarations which lack a definition. There are implementation limits which prevents us from finding the pattern for such functions, and this causes difficulties setting up the instantiation scope for the function parameters. This patch skips instantiating the default argument in these cases, which causes a minor regression in error recovery, but otherwise avoids the crash. The previous attempt #113777 accidentally skipped all default argument constructions, causing some regressions. This patch resolves that by moving the guard to InstantiateDefaultArgument() where the handling of templates takes place. Fixes #113324
1 parent b3eede5 commit 9daf10f

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,8 @@ Bug Fixes to C++ Support
837837
missing placeholder return type. (#GH78694)
838838
- Fixed a bug where bounds of partially expanded pack indexing expressions were checked too early. (#GH116105)
839839
- Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385)
840+
- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
841+
friend declarations. (#GH113324)
840842
- Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659)
841843
- Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072)
842844
- Fixed a null pointer dereference issue when heuristically computing ``sizeof...(pack)`` expressions. (#GH81436)

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4703,6 +4703,17 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
47034703
ParmVarDecl *Param) {
47044704
assert(Param->hasUninstantiatedDefaultArg());
47054705

4706+
// FIXME: We don't track member specialization info for non-defining
4707+
// friend declarations, so we will not be able to later find the function
4708+
// pattern. As a workaround, don't instantiate the default argument in this
4709+
// case. This is correct per the standard and only an issue for recovery
4710+
// purposes. [dcl.fct.default]p4:
4711+
// if a friend declaration D specifies a default argument expression,
4712+
// that declaration shall be a definition.
4713+
if (FD->getFriendObjectKind() != Decl::FOK_None &&
4714+
!FD->getTemplateInstantiationPattern())
4715+
return true;
4716+
47064717
// Instantiate the expression.
47074718
//
47084719
// FIXME: Pass in a correct Pattern argument, otherwise

clang/test/CXX/temp/temp.res/p4.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,23 @@ template<typename T> struct S {
185185
friend void X::f(T::type);
186186
};
187187
}
188+
189+
namespace GH113324 {
190+
template <typename = int> struct S1 {
191+
friend void f1(S1, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}
192+
friend void f2(S1 a, S1 = decltype(a){}); // expected-error {{friend declaration specifying a default argument must be a definition}}
193+
};
194+
195+
template <class T> using alias = int;
196+
template <typename T> struct S2 {
197+
// FIXME: We miss diagnosing the default argument instantiation failure
198+
// (forming reference to void)
199+
friend void f3(S2, int a = alias<T &>(1)); // expected-error {{friend declaration specifying a default argument must be a definition}}
200+
};
201+
202+
void test() {
203+
f1(S1<>{});
204+
f2(S1<>{});
205+
f3(S2<void>());
206+
}
207+
} // namespace GH113324

clang/test/CodeGenCXX/default-arguments.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ void g() {
1212
}
1313
}
1414

15+
namespace GH113324 {
16+
struct S1 {
17+
friend void f(S1, int = 42) {}
18+
};
19+
20+
void test() {
21+
S1 s1;
22+
f(s1);
23+
}
24+
};
25+
1526
struct A1 {
1627
A1();
1728
~A1();

0 commit comments

Comments
 (0)