erik.pilkington created this revision.
erik.pilkington added a reviewer: rsmith.
Herald added a subscriber: dexonsmith.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0961r1.html

I don't believe an actual defect report was filed for this, but the paper (in 
the "wording" section) claims that we should back-port this to C++17 as if it 
were a defect report. Besides that, this is pretty straightforward.

Thanks for taking a look!
Erik


Repository:
  rC Clang

https://reviews.llvm.org/D50418

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===================================================================
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -755,7 +755,7 @@
       <tr>
         <!-- from Jacksonville 2018 -->
         <td><a href="http://wg21.link/p0961r1";>P0961R1</a> (<a href="#dr">DR</a>)</td>
-        <td class="none" align="center">No</td>
+        <td class="none" align="center">SVN</td>
       </tr>
       <tr>
         <!-- from Jacksonville 2018 -->
Index: clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
===================================================================
--- clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
+++ clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
@@ -36,7 +36,7 @@
   auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}
 }
 
-template<int> float &get(A);
+template<int> float &get(A); // expected-note 2 {{no known conversion}}
 
 void no_tuple_element_1() {
   auto [a0, a1, a2] = A(); // expected-error-re {{'std::tuple_element<0U{{L*}}, A>::type' does not name a type}} expected-note {{in implicit}}
@@ -57,7 +57,7 @@
 template<> struct std::tuple_element<1, A> { typedef float &type; };
 template<> struct std::tuple_element<2, A> { typedef const float &type; };
 
-template<int N> auto get(B) -> int (&)[N + 1];
+template<int N> auto get(B) -> int (&)[N + 1]; // expected-note 2 {{no known conversion}}
 template<int N> struct std::tuple_element<N, B> { typedef int type[N +1 ]; };
 
 template<typename T> struct std::tuple_size<const T> : std::tuple_size<T> {};
@@ -138,19 +138,25 @@
   return c;
 }
 
-struct D { template<int> struct get {}; }; // expected-note {{declared here}}
+struct D {
+  // FIXME: Emit a note here explaining why this was ignored.
+  template<int> struct get {};
+};
 template<> struct std::tuple_size<D> { static const int value = 1; };
 template<> struct std::tuple_element<0, D> { typedef D::get<0> type; };
 void member_get_class_template() {
-  auto [d] = D(); // expected-error {{cannot refer to member 'get' in 'D' with '.'}} expected-note {{in implicit init}}
+  auto [d] = D(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}
 }
 
-struct E { int get(); };
+struct E {
+  // FIXME: Emit a note here explaining why this was ignored.
+  int get();
+};
 template<> struct std::tuple_size<E> { static const int value = 1; };
 template<> struct std::tuple_element<0, E> { typedef int type; };
 void member_get_non_template() {
   // FIXME: This diagnostic is not very good.
-  auto [e] = E(); // expected-error {{no member named 'get'}} expected-note {{in implicit init}}
+  auto [e] = E(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}
 }
 
 namespace ADL {
@@ -230,3 +236,35 @@
   }
   static_assert(g() == 4); // expected-error {{constant}} expected-note {{in call to 'g()'}}
 }
+
+// P0961R1
+struct InvalidMemberGet {
+  int get();
+  template <class T> int get();
+  struct get {};
+};
+template <> struct std::tuple_size<InvalidMemberGet> { static constexpr size_t value = 1; };
+template <> struct std::tuple_element<0, InvalidMemberGet> { typedef float type; };
+template <size_t> float get(InvalidMemberGet) { return 0; }
+int f() {
+  InvalidMemberGet img;
+  auto [x] = img;
+  typedef decltype(x) same_as_float;
+  typedef float same_as_float;
+}
+
+struct ValidMemberGet {
+  int get();
+  template <class T> int get() { return 0; }
+  template <size_t N> float get() { return 0; }
+};
+template <> struct std::tuple_size<ValidMemberGet> { static constexpr size_t value = 1; };
+template <> struct std::tuple_element<0, ValidMemberGet> { typedef float type; };
+// Don't use this one; we should use the member get.
+template <size_t N> int get(ValidMemberGet) { static_assert(N && false, ""); }
+int f2() {
+  ValidMemberGet img;
+  auto [x] = img;
+  typedef decltype(x) same_as_float;
+  typedef float same_as_float;
+}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -1108,14 +1108,29 @@
 
   // [dcl.decomp]p3:
   //   The unqualified-id get is looked up in the scope of E by class member
-  //   access lookup
+  //   access lookup ...
   LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName);
   bool UseMemberGet = false;
   if (S.isCompleteType(Src->getLocation(), DecompType)) {
     if (auto *RD = DecompType->getAsCXXRecordDecl())
       S.LookupQualifiedName(MemberGet, RD);
+
+    //   ... and if that finds at least one declaration that is a function
+    //   template whose first template parameter is a non-type parameter ...
+    LookupResult::Filter Filter = MemberGet.makeFilter();
+    while (Filter.hasNext()) {
+      NamedDecl *ND = Filter.next();
+      if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) {
+        TemplateParameterList *TPL = FTD->getTemplateParameters();
+        if (TPL->size() != 0 && isa<NonTypeTemplateParmDecl>(TPL->getParam(0)))
+          continue;
+      }
+      Filter.erase();
+    }
+    Filter.done();
     if (MemberGet.isAmbiguous())
       return true;
+    //   ... the initializer is e.get<i>().
     UseMemberGet = !MemberGet.empty();
     S.FilterAcceptableTemplateNames(MemberGet);
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D50418: [... Erik Pilkington via Phabricator via cfe-commits

Reply via email to