Skip to content

Commit 5e24d21

Browse files
committed
[Clang] skip default argument instantiation for non-defining friend declarations to meet [dcl.fct.default] p4
1 parent 4f3bf1c commit 5e24d21

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

clang/docs/ReleaseNotes.rst

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

640642
Bug Fixes to AST Handling
641643
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4694,6 +4694,10 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
46944694
ParmVarDecl *Param) {
46954695
assert(Param->hasUninstantiatedDefaultArg());
46964696

4697+
if (FD->getFriendObjectKind() != Decl::FOK_None &&
4698+
!FD->getTemplateInstantiationPattern())
4699+
return true;
4700+
46974701
// Instantiate the expression.
46984702
//
46994703
// FIXME: Pass in a correct Pattern argument, otherwise

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,46 @@ 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+
struct S3 {
203+
friend void f4(S3, int = 42) { }
204+
};
205+
206+
template <bool, class> using __enable_if_t = int;
207+
template <int v> struct S4 {
208+
static const int value = v;
209+
};
210+
struct S5 {
211+
template <__enable_if_t<S4<true>::value, int> = 0>
212+
S5(const char *);
213+
};
214+
struct S6 {
215+
template <typename a, typename b>
216+
friend void f5(int, S6, a, b, S5 = "") { }
217+
};
218+
219+
void test() {
220+
f1(S1<>{});
221+
f2(S1<>{});
222+
f3(S2<void>());
223+
224+
S3 s3;
225+
f4(s3);
226+
227+
S6 s6;
228+
auto result = f5(0, s6, [] {}, [] {}); // expected-error {{variable has incomplete type 'void}}
229+
}
230+
} // namespace GH113324

0 commit comments

Comments
 (0)