Skip to content

Commit 2ef4cc6

Browse files
committed
[Clang] skip default argument instantiation for non-defining friend declarations without specialization info to meet [dcl.fct.default]p4
1 parent f5e4ffa commit 2ef4cc6

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
@@ -595,6 +595,8 @@ Bug Fixes to C++ Support
595595
an implicitly instantiated class template specialization. (#GH51051)
596596
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
597597
- Name independent data members were not correctly initialized from default member initializers. (#GH114069)
598+
- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
599+
friend declarations. (#GH113324).
598600

599601
Bug Fixes to AST Handling
600602
^^^^^^^^^^^^^^^^^^^^^^^^^

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)