Author: Oleksandr T. Date: 2024-11-07T14:13:04-03:00 New Revision: f8b96160feb99b3fc37b1857caf2abcfea7e5a06
URL: https://github.com/llvm/llvm-project/commit/f8b96160feb99b3fc37b1857caf2abcfea7e5a06 DIFF: https://github.com/llvm/llvm-project/commit/f8b96160feb99b3fc37b1857caf2abcfea7e5a06.diff LOG: [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 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaExpr.cpp clang/test/CXX/temp/temp.res/p4.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bd0045a898b8e4..46beb3fe39dec8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 49fdb5b5ab43da..df8f025030e2b1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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; diff --git a/clang/test/CXX/temp/temp.res/p4.cpp b/clang/test/CXX/temp/temp.res/p4.cpp index f54d8649f5da88..743ffed14d81a8 100644 --- a/clang/test/CXX/temp/temp.res/p4.cpp +++ b/clang/test/CXX/temp/temp.res/p4.cpp @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits