Skip to content

Commit f8b9616

Browse files
authored
[Clang] skip default argument instantiation for non-defining friend declarations (#113777)
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. Fixes #113324
1 parent c980cc0 commit f8b9616

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,8 @@ Bug Fixes to C++ Support
613613
an implicitly instantiated class template specialization. (#GH51051)
614614
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
615615
- Name independent data members were not correctly initialized from default member initializers. (#GH114069)
616+
- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
617+
friend declarations. (#GH113324).
616618

617619
Bug Fixes to AST Handling
618620
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaExpr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6018,6 +6018,17 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
60186018
} else {
60196019
assert(Param && "can't use default arguments without a known callee");
60206020

6021+
// FIXME: We don't track member specialization info for non-defining
6022+
// friend declarations, so we will not be able to later find the function
6023+
// pattern. As a workaround, don't instantiate the default argument in
6024+
// this case. This is correct per wording and only an error recovery
6025+
// issue, as per [dcl.fct.default]p4:
6026+
// if a friend declaration D specifies a default argument expression,
6027+
// that declaration shall be a definition.
6028+
if (FDecl->getFriendObjectKind() != Decl::FOK_None &&
6029+
FDecl->getMemberSpecializationInfo() == nullptr)
6030+
return true;
6031+
60216032
ExprResult ArgExpr = BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
60226033
if (ArgExpr.isInvalid())
60236034
return true;

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

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

0 commit comments

Comments
 (0)