aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-06-16 22:28:25 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-06-16 22:28:25 -0400
commitccb7042db8997440b8571405742e49b57787490e (patch)
treeba60737c2834ce10d9f3ebeb73ca2e7043826880
parentd4b1d43cec7ff278e97e22d1b06d220b7aa86be8 (diff)
downloadgcc-ccb7042db8997440b8571405742e49b57787490e.zip
gcc-ccb7042db8997440b8571405742e49b57787490e.tar.gz
gcc-ccb7042db8997440b8571405742e49b57787490e.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/call.c3
-rw-r--r--gcc/cp/pt.c36
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/auto-fn27.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/auto-fn39.C48
5 files changed, 85 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1ec3b22..88e148b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9c3f1eb..d1f27dd 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 d2b91b2..57be0ab 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 b114df2..c019d9e 100644
--- a/gcc/testsuite/g++.dg/cpp1y/auto-fn27.C
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn27.C
@@ -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
index 0000000..b4ba29e
--- /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<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; }
+