From ccb7042db8997440b8571405742e49b57787490e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 16 Jun 2017 22:28:25 -0400 Subject: [PATCH] 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. From-SVN: r249323 --- gcc/cp/ChangeLog | 6 ++++ gcc/cp/call.c | 3 ++ gcc/cp/pt.c | 36 ++++++++++++++----- gcc/testsuite/g++.dg/cpp1y/auto-fn27.C | 2 +- gcc/testsuite/g++.dg/cpp1y/auto-fn39.C | 48 ++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/auto-fn39.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1ec3b2261ba..88e148b1d8f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2017-06-16 Jason Merrill + 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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9c3f1eb2b2b..d1f27dde830 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d2b91b24356..57be0ab4364 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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) diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn27.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn27.C index b114df2fdd5..c019d9ef583 100644 --- a/gcc/testsuite/g++.dg/cpp1y/auto-fn27.C +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn27.C @@ -31,7 +31,7 @@ F::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 index 00000000000..b4ba29eb200 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn39.C @@ -0,0 +1,48 @@ +// PR c++/81045 +// { dg-do compile { target c++14 } } + +template class vectorIterator; + +template class vector { + public: + auto get(unsigned int i) { return data[i]; } + + auto begin() { return vectorIterator{*this, 0}; } + auto end() { return vectorIterator{*this, 10}; } + + private: + T data[10] = {}; +}; + +template class vectorIterator { + public: + vectorIterator(vector& 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& self; + unsigned int offset; +}; + +class Object { + public: + template auto cast() -> T { + return T(); + } +}; + +class Group : public Object { + public: + template auto objects() const -> void { + vector easyObjects; + for(auto obj : easyObjects) { + auto casted = obj.cast(); + } + } +}; + +int main() { return 0; } + -- 2.30.2