aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/docs/ReleaseNotes.rst2
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp11
-rw-r--r--clang/test/CXX/temp/temp.res/p4.cpp20
-rw-r--r--clang/test/CodeGenCXX/default-arguments.cpp11
4 files changed, 44 insertions, 0 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 956b553..3645dff 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -837,6 +837,8 @@ Bug Fixes to C++ Support
missing placeholder return type. (#GH78694)
- Fixed a bug where bounds of partially expanded pack indexing expressions were checked too early. (#GH116105)
- Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385)
+- Fixed an assertion failure caused by invalid default argument substitutions in non-defining
+ friend declarations. (#GH113324)
- Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659)
- Fixed a parser crash when using pack indexing as a nested name specifier. (#GH119072)
- Fixed a null pointer dereference issue when heuristically computing ``sizeof...(pack)`` expressions. (#GH81436)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c70ee73..e058afe 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4703,6 +4703,17 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) {
assert(Param->hasUninstantiatedDefaultArg());
+ // 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 the standard and only an issue for recovery
+ // purposes. [dcl.fct.default]p4:
+ // if a friend declaration D specifies a default argument expression,
+ // that declaration shall be a definition.
+ if (FD->getFriendObjectKind() != Decl::FOK_None &&
+ !FD->getTemplateInstantiationPattern())
+ return true;
+
// Instantiate the expression.
//
// FIXME: Pass in a correct Pattern argument, otherwise
diff --git a/clang/test/CXX/temp/temp.res/p4.cpp b/clang/test/CXX/temp/temp.res/p4.cpp
index f54d864..9dbdd23 100644
--- a/clang/test/CXX/temp/temp.res/p4.cpp
+++ b/clang/test/CXX/temp/temp.res/p4.cpp
@@ -185,3 +185,23 @@ template<typename T> struct S {
friend void X::f(T::type);
};
}
+
+namespace GH113324 {
+template <typename = int> struct S1 {
+ friend void f1(S1, int = 0); // expected-error {{friend declaration specifying a default argument must be a definition}}
+ friend void f2(S1 a, S1 = decltype(a){}); // expected-error {{friend declaration specifying a default argument must be a definition}}
+};
+
+template <class T> using alias = int;
+template <typename T> struct S2 {
+ // FIXME: We miss diagnosing the default argument instantiation failure
+ // (forming reference to void)
+ friend void f3(S2, int a = alias<T &>(1)); // expected-error {{friend declaration specifying a default argument must be a definition}}
+};
+
+void test() {
+ f1(S1<>{});
+ f2(S1<>{});
+ f3(S2<void>());
+}
+} // namespace GH113324
diff --git a/clang/test/CodeGenCXX/default-arguments.cpp b/clang/test/CodeGenCXX/default-arguments.cpp
index 215bcd8..2459ef1 100644
--- a/clang/test/CodeGenCXX/default-arguments.cpp
+++ b/clang/test/CodeGenCXX/default-arguments.cpp
@@ -12,6 +12,17 @@ void g() {
}
}
+namespace GH113324 {
+struct S1 {
+ friend void f(S1, int = 42) {}
+};
+
+void test() {
+ S1 s1;
+ f(s1);
+}
+};
+
struct A1 {
A1();
~A1();