[PR c++/86246] ICE tsubst explicit operator call
authorNathan Sidwell <nathan@gcc.gnu.org>
Thu, 15 Nov 2018 19:54:25 +0000 (19:54 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 15 Nov 2018 19:54:25 +0000 (19:54 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg01405.html
PR c++/86246
PR c++/87989
* typeck.c (finish_class_member_access_expr): Conversion operator
to dependent type is dependent.

* g++.dg/template/pr86246.C: New.
* g++.dg/template/pr87989.C: New.

From-SVN: r266193

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/pr86246.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/pr87989.C [new file with mode: 0644]

index 6d87c293dd60ae000cd3a9efe8603e0f7afdb98d..deec822b924f87e198694390be7ec6f6f3c41053 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-15  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/86246
+       PR c++/87989
+       * typeck.c (finish_class_member_access_expr): Conversion operator
+       to dependent type is dependent.
+
 2018-11-15  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * constexpr.c (ensure_literal_type_for_constexpr_object): Use
index 7b42d539dfb93e50ee7c06d7526447c4e09e3b86..81cb4057a5b424882bdc82392ab00a15fccabaa8 100644 (file)
@@ -2884,7 +2884,12 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
             expression is dependent.  */
          || (TREE_CODE (name) == SCOPE_REF
              && TYPE_P (TREE_OPERAND (name, 0))
-             && dependent_scope_p (TREE_OPERAND (name, 0))))
+             && dependent_scope_p (TREE_OPERAND (name, 0)))
+         /* If NAME is operator T where "T" is dependent, we can't
+            lookup until we instantiate the T.  */
+         || (TREE_CODE (name) == IDENTIFIER_NODE
+             && IDENTIFIER_CONV_OP_P (name)
+             && dependent_type_p (TREE_TYPE (name))))
        {
        dependent:
          return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,
index 24ea36ec91242947f61574bad9175d5a8f21cc2c..dc8625600dce690fcea15525e80c348017de786e 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-15  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/86246
+       PR c++/87989
+       * g++.dg/template/pr86246.C: New.
+       * g++.dg/template/pr87989.C: New.
+
 2018-11-15  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * g++.dg/cpp0x/constexpr-diag3.C: Check locations too.
@@ -39,7 +46,7 @@
        PR tree-optimization/88031
        * gcc.dg/pr88031.c: New testcase.
 
-2018-11-15  Wilco Dijkstra  <wdijkstr@arm.com>  
+2018-11-15  Wilco Dijkstra  <wdijkstr@arm.com>
 
        * gcc.target/aarch64/pr62178.c: Fix spaces.
 
diff --git a/gcc/testsuite/g++.dg/template/pr86246.C b/gcc/testsuite/g++.dg/template/pr86246.C
new file mode 100644 (file)
index 0000000..43ce545
--- /dev/null
@@ -0,0 +1,38 @@
+// { dg-do compile { target c++11 } }
+// PR c++/86246 ICE in tsubst
+
+namespace std {
+  template<typename T> struct is_class {
+    static constexpr bool value = true;
+  };
+  template<> struct is_class<double> {
+    static constexpr bool value = false;
+  };
+}
+
+class MyClass {
+ public:
+  operator double() const {
+    return 1;
+  }
+  template<typename T>
+  operator T() const {
+    static_assert(std::is_class<T>::value, "problem");
+    return T();
+  }
+};
+
+template<typename T>
+void SetValue(const MyClass& obj, T* value) {
+  //  erroneously dispatched to operator T when T is double
+  *value = obj.operator T();
+}
+
+int main() {
+  MyClass obj;
+  // works fine
+  obj.operator double ();
+  double x;
+  // error, when operator T is called in SetValue
+  SetValue(obj, &x);
+}
diff --git a/gcc/testsuite/g++.dg/template/pr87989.C b/gcc/testsuite/g++.dg/template/pr87989.C
new file mode 100644 (file)
index 0000000..34e6e95
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/87989
+// { dg-do link }
+// Resolved to template instantiation rather than non-template fn.
+
+struct X {
+  template <class T> operator T() const; // no definition
+  operator float() const {return 0.f;}
+};
+
+template <class T>
+T f(const X &x) {
+  // Resoved in error to X::operator float<float>() const`
+  // instead of correct `X::operator float() const
+  return x.operator T();
+}
+
+int main ()
+{
+  return f<float>(X ());
+}