Skip to content

Commit

Permalink
[Clang] skip default argument instantiation for non-defining friend d…
Browse files Browse the repository at this point in the history
…eclarations (#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
  • Loading branch information
a-tarasyuk authored Nov 7, 2024
1 parent c980cc0 commit f8b9616
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 0 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,8 @@ Bug Fixes to C++ Support
an implicitly instantiated class template specialization. (#GH51051)
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
- Name independent data members were not correctly initialized from default member initializers. (#GH114069)
- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
friend declarations. (#GH113324).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6018,6 +6018,17 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
} else {
assert(Param && "can't use default arguments without a known callee");

// FIXME: We don't track member specialization info for non-defining
// friend declarations, so we will not be able to later find the function
// pattern. As a workaround, don't instantiate the default argument in
// this case. This is correct per wording and only an error recovery
// issue, as per [dcl.fct.default]p4:
// if a friend declaration D specifies a default argument expression,
// that declaration shall be a definition.
if (FDecl->getFriendObjectKind() != Decl::FOK_None &&
FDecl->getMemberSpecializationInfo() == nullptr)
return true;

ExprResult ArgExpr = BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
if (ArgExpr.isInvalid())
return true;
Expand Down
19 changes: 19 additions & 0 deletions clang/test/CXX/temp/temp.res/p4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,22 @@ template<typename T> struct S {
friend void X::f(T::type);
};
}

namespace GH113324 {
template <typename = int> struct ct {
friend void f1(ct, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}
friend void f2(ct a, ct = decltype(a){ }); // expected-error {{friend declaration specifying a default argument must be a definition}}
};

template<class T> using alias = int;
template<typename T> struct C {
// FIXME: We miss diagnosing the default argument instantiation failure (forming reference to void)
friend void f3(C, int a = alias<T&>(1)); // expected-error {{friend declaration specifying a default argument must be a definition}}
};

void test() {
f1(ct<>{});
f2(ct<>{});
f3(C<void>());
}
} // namespace GH113324

0 comments on commit f8b9616

Please sign in to comment.