Author: rsmith Date: Wed May 1 17:49:05 2019 New Revision: 359746 URL: http://llvm.org/viewvc/llvm-project?rev=359746&view=rev Log: Diagnose non-dependent qualified friend function template declarations that don't match any existing declaration. Don't get confused and treat such declarations as template *specializations*.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/test/SemaCXX/friend-template-redecl.cpp cfe/trunk/test/SemaCXX/lambda-expressions.cpp Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=359746&r1=359745&r2=359746&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed May 1 17:49:05 2019 @@ -9086,8 +9086,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, // nothing will diagnose that error later. if (isFriend && (D.getCXXScopeSpec().getScopeRep()->isDependent() || - (!Previous.empty() && (TemplateParamLists.size() || - CurContext->isDependentContext())))) { + (!Previous.empty() && CurContext->isDependentContext()))) { // ignore these } else { // The user tried to provide an out-of-line definition for a Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=359746&r1=359745&r2=359746&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed May 1 17:49:05 2019 @@ -1056,6 +1056,7 @@ Sema::CheckOverload(Scope *S, FunctionDe // third bullet. If the type of the friend is dependent, skip this lookup // until instantiation. if (New->getFriendObjectKind() && New->getQualifier() && + !New->getDescribedFunctionTemplate() && !New->getDependentSpecializationInfo() && !New->getType()->isDependentType()) { LookupResult TemplateSpecResult(LookupResult::Temporary, Old); Modified: cfe/trunk/test/SemaCXX/friend-template-redecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend-template-redecl.cpp?rev=359746&r1=359745&r2=359746&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/friend-template-redecl.cpp (original) +++ cfe/trunk/test/SemaCXX/friend-template-redecl.cpp Wed May 1 17:49:05 2019 @@ -1,7 +1,5 @@ // RUN: %clang_cc1 -std=c++17 -verify -emit-llvm-only %s -// expected-no-diagnostics - template <class T> void bar(const T &t) { foo(t); } template <class> @@ -18,3 +16,11 @@ void f() { foo(x); bar(x); } + +template<typename T> void droid(); +struct X { + template<typename T> friend void ::droid(); + template<int N> friend void ::droid(); // expected-error {{does not match}} + // FIXME: We should produce a note for the above candidate explaining why + // it's not the droid we're looking for. +}; Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=359746&r1=359745&r2=359746&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original) +++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Wed May 1 17:49:05 2019 @@ -586,25 +586,30 @@ namespace PR25627_dont_odr_use_local_con namespace ConversionOperatorDoesNotHaveDeducedReturnType { auto x = [](int){}; - auto y = [](auto) -> void {}; + auto y = [](auto &v) -> void { v.n = 0; }; using T = decltype(x); using U = decltype(y); using ExpectedTypeT = void (*)(int); template<typename T> - using ExpectedTypeU = void (*)(T); + using ExpectedTypeU = void (*)(T&); struct X { + friend auto T::operator()(int) const; friend T::operator ExpectedTypeT() const; - // Formally, this is invalid, because the return type of the conversion - // function for a generic lambda expression is an unspecified decltype - // type, which this should not match. However, this declaration is - // functionally equivalent to that one, so we're permitted to choose to - // accept this. + // FIXME: The first of these should match. The second should not. template<typename T> - friend U::operator ExpectedTypeU<T>() const; + friend void U::operator()(T&) const; // expected-error {{does not match}} + template<typename T> + friend U::operator ExpectedTypeU<T>() const; // expected-error {{does not match}} + + private: + int n; }; + // Should be OK: lambda's call operator is a friend. + void use(X &x) { y(x); } + // This used to crash in return type deduction for the conversion opreator. struct A { int n; void f() { +[](decltype(n)) {}; } }; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits