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
This commit is contained in:
Jason Merrill 2017-06-16 22:28:25 -04:00 committed by Jason Merrill
parent d4b1d43cec
commit ccb7042db8
5 changed files with 85 additions and 10 deletions

View 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.

View 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)

View 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)

View 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;

View file

@ -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; }