Commit 1a11a94f by Adam Butcher

Support using 'auto' in a function parameter list to introduce an implicit template parameter.

gcc/cp/
	* cp-tree.h (type_uses_auto_or_concept): Declare.
	(is_auto_or_concept): Declare.
	* decl.c (grokdeclarator): Allow 'auto' parameters in lambdas with
	-std=gnu++1y or -std=c++1y or, as a GNU extension, in plain functions.
	* type-utils.h: New header defining ...
	(find_type_usage): ... this new function based on pt.c (type_uses_auto)
	for searching a type tree given a predicate.
	* pt.c (type_uses_auto): Reimplement via type-utils.h (find_type_usage).
	(is_auto_or_concept): New function.
	(type_uses_auto_or_concept): New function.
	* parser.h (struct cp_parser): Add fully_implicit_function_template_p.
	* parser.c (cp_parser_new): Initialize fully_implicit_function_template_p.
	(cp_parser_new): Initialize fully_implicit_function_template_p.
	(cp_parser_lambda_expression): Copy and restore value of
	fully_implicit_function_template_p as per other parser fields.
	(cp_parser_parameter_declaration_list): Count generic
	parameters and call ...
	(add_implicit_template_parms): ... this new function to synthesize them
	with help from type-utils.h (find_type_usage), ...
	(tree_type_is_auto_or_concept): ... this new static function and ...
	(make_generic_type_name): ... this new static function.
	(cp_parser_direct_declarator): Account for implicit template parameters.
	(cp_parser_lambda_declarator_opt): Finish fully implicit template if
	necessary by calling ...
	(finish_fully_implicit_template): ... this new function.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_function_definition_after_declarator): Likewise.
	(cp_parser_member_declaration): Likewise.
	* Make-lang.in (cp/pt.o): Add dependency on type-utils.h.
	(cp/parser.o): Likewise.

gcc/testsuite/
	g++.dg/cpp0x/auto9.C: Downgrade two previously expected errors (now
	interpreted as implicit templates) to be expected pedwarns instead.

From-SVN: r202612
parent 6a8b219b
......@@ -312,7 +312,7 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) $(TM_P_H)
cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \
toplev.h $(TREE_INLINE_H) pointer-set.h gt-cp-pt.h intl.h \
c-family/c-objc.h
c-family/c-objc.h cp/type-utils.h
cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_H) \
$(FLAGS_H) $(REAL_H) $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H) \
tree-diagnostic.h tree-pretty-print.h pointer-set.h c-family/c-objc.h
......@@ -331,7 +331,8 @@ cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) $(REAL_H) \
gt-cp-mangle.h $(TARGET_H) $(TM_P_H) $(CGRAPH_H)
cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_CORE_H) \
gt-cp-parser.h $(TARGET_H) $(PLUGIN_H) intl.h cp/decl.h \
c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_H)
c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_H) \
cp/type-utils.h
cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) $(C_COMMON_H) \
$(TM_H) coretypes.h pointer-set.h tree-iterator.h $(SPLAY_TREE_H)
cp/vtable-class-hierarchy.o: cp/vtable-class-hierarchy.c \
......
......@@ -5453,10 +5453,12 @@ extern tree make_auto (void);
extern tree make_decltype_auto (void);
extern tree do_auto_deduction (tree, tree, tree);
extern tree type_uses_auto (tree);
extern tree type_uses_auto_or_concept (tree);
extern void append_type_to_template_for_access_check (tree, tree, tree,
location_t);
extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree);
extern bool is_auto_or_concept (const_tree);
extern tree process_template_parm (tree, location_t, tree,
bool, bool);
extern tree end_template_parm_list (tree);
......
......@@ -10323,8 +10323,33 @@ grokdeclarator (const cp_declarator *declarator,
if (type_uses_auto (type))
{
error ("parameter declared %<auto%>");
type = error_mark_node;
if (template_parm_flag)
{
error ("template parameter declared %<auto%>");
type = error_mark_node;
}
else if (decl_context == CATCHPARM)
{
error ("catch parameter declared %<auto%>");
type = error_mark_node;
}
else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
{
if (cxx_dialect < cxx1y)
pedwarn (location_of (type), 0,
"use of %<auto%> in lambda parameter declaration "
"only available with "
"-std=c++1y or -std=gnu++1y");
}
else if (cxx_dialect < cxx1y)
pedwarn (location_of (type), 0,
"use of %<auto%> in parameter declaration "
"only available with "
"-std=c++1y or -std=gnu++1y");
else
pedwarn (location_of (type), OPT_Wpedantic,
"ISO C++ forbids use of %<auto%> in parameter "
"declaration");
}
/* A parameter declared as an array of T is really a pointer to T.
......
......@@ -341,6 +341,12 @@ typedef struct GTY(()) cp_parser {
/* The number of template parameter lists that apply directly to the
current declaration. */
unsigned num_template_parameter_lists;
/* TRUE if the function being declared was made a template due to its
parameter list containing generic type specifiers (`auto' or concept
identifiers) rather than an explicit template parameter list. */
bool fully_implicit_function_template_p;
} cp_parser;
/* In parser.c */
......
......@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h"
#include "timevar.h"
#include "tree-iterator.h"
#include "type-utils.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
......@@ -21229,31 +21230,35 @@ is_auto (const_tree type)
return false;
}
/* Returns true iff TYPE contains a use of 'auto'. Since auto can only
appear as a type-specifier for the declaration in question, we don't
have to look through the whole type. */
/* Returns the TEMPLATE_TYPE_PARM in TYPE representing `auto' iff TYPE contains
a use of `auto'. Returns NULL_TREE otherwise. */
tree
type_uses_auto (tree type)
{
enum tree_code code;
if (is_auto (type))
return type;
return find_type_usage (type, is_auto);
}
code = TREE_CODE (type);
/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto',
'decltype(auto)' or a concept. */
if (code == POINTER_TYPE || code == REFERENCE_TYPE
|| code == OFFSET_TYPE || code == FUNCTION_TYPE
|| code == METHOD_TYPE || code == ARRAY_TYPE)
return type_uses_auto (TREE_TYPE (type));
bool
is_auto_or_concept (const_tree type)
{
return is_auto (type); // or concept
}
if (TYPE_PTRMEMFUNC_P (type))
return type_uses_auto (TREE_TYPE (TREE_TYPE
(TYPE_PTRMEMFUNC_FN_TYPE (type))));
/* Returns the TEMPLATE_TYPE_PARM in TYPE representing a generic type (`auto' or
a concept identifier) iff TYPE contains a use of a generic type. Returns
NULL_TREE otherwise. */
return NULL_TREE;
tree
type_uses_auto_or_concept (tree type)
{
return find_type_usage (type, is_auto_or_concept);
}
/* For a given template T, return the vector of typedefs referenced
in T for which access check is needed at T instantiation time.
T is either a FUNCTION_DECL or a RECORD_TYPE.
......
/* Utilities for querying and manipulating type trees.
Copyright (C) 2013 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_CP_TYPE_UTILS_H
#define GCC_CP_TYPE_UTILS_H
/* Returns the first tree within T that is directly matched by PRED. T may be a
type or PARM_DECL and is incrementally decomposed toward its type-specifier
until a match is found. NULL_TREE is returned if PRED does not match any
part of T.
This is primarily intended for detecting whether T uses `auto' or a concept
identifier. Since either of these can only appear as a type-specifier for
the declaration in question, only top-level qualifications are traversed;
find_type_usage does not look through the whole type. */
inline tree
find_type_usage (tree t, bool (*pred) (const_tree))
{
enum tree_code code;
if (pred (t))
return t;
code = TREE_CODE (t);
if (code == POINTER_TYPE || code == REFERENCE_TYPE
|| code == PARM_DECL || code == OFFSET_TYPE
|| code == FUNCTION_TYPE || code == METHOD_TYPE
|| code == ARRAY_TYPE)
return find_type_usage (TREE_TYPE (t), pred);
if (TYPE_PTRMEMFUNC_P (t))
return find_type_usage
(TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (t))), pred);
return NULL_TREE;
}
#endif // GCC_CP_TYPE_UTILS_H
......@@ -117,8 +117,8 @@ template <auto V = 4> struct G {}; // { dg-error "auto" }
template <typename T> struct H { H (); ~H (); };
H<auto> h; // { dg-error "invalid" }
void qq (auto); // { dg-error "auto" }
void qr (auto*); // { dg-error "auto" }
void qq (auto); // { dg-warning "auto" }
void qr (auto*); // { dg-warning "auto" }
// PR c++/46145
typedef auto autot; // { dg-error "auto" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment