PR c++/81045 - Wrong type-dependence with auto return type.
authorJason Merrill <jason@redhat.com>
Sat, 17 Jun 2017 02:28:25 +0000 (22:28 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 17 Jun 2017 02:28:25 +0000 (22:28 -0400)
* pt.c (type_dependent_expression_p): An undeduced auto outside the
template isn't dependent.
* call.c (build_over_call): Instantiate undeduced auto even in a
template.

From-SVN: r249323

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1y/auto-fn27.C
gcc/testsuite/g++.dg/cpp1y/auto-fn39.C [new file with mode: 0644]

index 1ec3b2261ba889535ad2a3fa1c28c67ab500ba36..88e148b1d8f5e617abe62bf71372db42cb09a377 100644 (file)
@@ -1,5 +1,11 @@
 2017-06-16  Jason Merrill  <jason@redhat.com>
 
+       PR c++/81045 - Wrong type-dependence with auto return type.
+       * pt.c (type_dependent_expression_p): An undeduced auto outside the
+       template isn't dependent.
+       * call.c (build_over_call): Instantiate undeduced auto even in a
+       template.
+
        PR c++/80465 - ICE with generic lambda with noexcept-specifier.
        * lambda.c (maybe_add_lambda_conv_op): Keep processing_template_decl
        set longer for a generic lambda.
index 9c3f1eb2b2bc93d78cda3b510169c3d2a74b462f..d1f27dde830c123c5b0a60900c7979972f9bfb6f 100644 (file)
@@ -7584,6 +7584,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       const tree *argarray;
       unsigned int nargs;
 
+      if (undeduced_auto_decl (fn))
+       mark_used (fn, complain);
+
       return_type = TREE_TYPE (TREE_TYPE (fn));
       nargs = vec_safe_length (args);
       if (first_arg == NULL_TREE)
index d2b91b2435642883b177c746d5dc575a51d7686b..57be0ab43643caf3d88787841f7871115c8389d3 100644 (file)
@@ -24011,17 +24011,35 @@ type_dependent_expression_p (tree expression)
    return true;
 
   /* A function or variable template-id is type-dependent if it has any
-     dependent template arguments.  Note that we only consider the innermost
-     template arguments here, since those are the ones that come from the
-     template-id; the template arguments for the enclosing class do not make it
-     type-dependent, they only make a member function value-dependent.  */
+     dependent template arguments.  */
   if (VAR_OR_FUNCTION_DECL_P (expression)
       && DECL_LANG_SPECIFIC (expression)
-      && DECL_TEMPLATE_INFO (expression)
-      && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression))
-      && (any_dependent_template_arguments_p
-         (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
-    return true;
+      && DECL_TEMPLATE_INFO (expression))
+    {
+      /* Consider the innermost template arguments, since those are the ones
+        that come from the template-id; the template arguments for the
+        enclosing class do not make it type-dependent unless they are used in
+        the type of the decl.  */
+      if (PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression))
+         && (any_dependent_template_arguments_p
+             (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
+       return true;
+
+      /* Otherwise, if the decl isn't from a dependent scope, it can't be
+        type-dependent.  Checking this is important for functions with auto
+        return type, which looks like a dependent type.  */
+      if (TREE_CODE (expression) == FUNCTION_DECL
+         && (!DECL_CLASS_SCOPE_P (expression)
+             || !dependent_type_p (DECL_CONTEXT (expression)))
+         && (!DECL_FRIEND_CONTEXT (expression)
+             || !dependent_type_p (DECL_FRIEND_CONTEXT (expression)))
+         && !DECL_LOCAL_FUNCTION_P (expression))
+       {
+         gcc_assert (!dependent_type_p (TREE_TYPE (expression))
+                     || undeduced_auto_decl (expression));
+         return false;
+       }
+    }
 
   /* Always dependent, on the number of arguments if nothing else.  */
   if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
index b114df2fdd5f8966d7a004796bcd26bb85628da7..c019d9ef5836bda75993cb68f8d8748ba6a61b0c 100644 (file)
@@ -31,7 +31,7 @@ F<T>::bar (const G &)
 {
   auto s = I;
   typedef decltype (s) L;
-  auto u =[&](L) { auto t = foo (J::K (), 0); }; // { dg-error "25:'void t' has incomplete type" }
+  auto u =[&](L) { auto t = foo (J::K (), 0); }; // { dg-error "25:declared void" }
 }
 struct B {
   typedef int G;
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn39.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn39.C
new file mode 100644 (file)
index 0000000..b4ba29e
--- /dev/null
@@ -0,0 +1,48 @@
+// PR c++/81045
+// { dg-do compile { target c++14 } }
+
+template<typename T> class vectorIterator;
+
+template<typename T> class vector {
+  public:
+  auto get(unsigned int i) { return data[i]; }
+
+  auto begin() { return vectorIterator<T>{*this, 0}; }
+  auto end() { return vectorIterator<T>{*this, 10}; }
+
+  private:
+  T data[10] = {};
+};
+
+template<typename T> class vectorIterator {
+  public:
+  vectorIterator(vector<T>& self, unsigned int offset) : self(self), offset(offset) {}
+
+  auto operator*() -> T& { return self.get(offset); }
+  auto operator!=(const vectorIterator& source) -> bool { return offset != source.offset; }
+  auto operator++() -> vectorIterator& { ++offset; return *this; }
+
+  private:
+  vector<T>& self;
+  unsigned int offset;
+};
+
+class Object {
+  public:
+  template<typename T> auto cast() -> T {
+    return T();
+  }
+};
+
+class Group : public Object {
+  public:
+  template<typename T = Object> auto objects() const -> void {
+    vector<Object> easyObjects;
+    for(auto obj : easyObjects) {
+      auto casted = obj.cast<T>();
+    }
+  }
+};
+
+int main() { return 0; }
+