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