r359746 - Diagnose non-dependent qualified friend function template declarations
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed May 1 17:49:05 PDT 2019
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)) {}; } };
}
More information about the cfe-commits
mailing list