Commit f3a880f8 by Adam Butcher

Revert r202554, r202540 and r202539.

 - r202554: Fix uninitialized variables causing breakage with -Werror.
 - r202540: Support using 'auto' in a function parameter list to introduce an implicit template parameter.
 - r202539: Support lambda templates.

From-SVN: r202570
parent 19ba6aab
2013-09-13 Adam Butcher <adam@jessamine.co.uk>
* lambda.c (maybe_add_lambda_conv_op): Initialize direct_argvec and call
to nullptr to avoid breakage with -Werror.
2013-09-12 Brooks Moses <bmoses@google.com> 2013-09-12 Brooks Moses <bmoses@google.com>
PR driver/42955 PR driver/42955
...@@ -10,55 +5,6 @@ ...@@ -10,55 +5,6 @@
2013-09-12 Adam Butcher <adam@jessamine.co.uk> 2013-09-12 Adam Butcher <adam@jessamine.co.uk>
* 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_member_declaration): Likewise.
(cp_parser_function_definition_after_declarator): Likewise.
* Make-lang.in (cp/pt.o): Add dependency on type-utils.h.
(cp/parser.o): Likewise.
2013-09-12 Adam Butcher <adam@jessamine.co.uk>
* parser.c (cp_parser_lambda_declarator_opt): Accept template parameter
list with std=c++1y or std=gnu++1y.
(cp_parser_lambda_body): Don't call 'expand_or_defer_fn' for lambda call
operator template to avoid adding template result to symbol table.
* lambda.c (lambda_function): Return template result if call operator is
a template.
(maybe_add_lambda_conv_op): Move declarations to point of use. Refactor
operator call building in order to support conversion of a non-capturing
lambda template to a function pointer with help from ...
(prepare_op_call): ... this new function.
* decl2.c (check_member_template): Don't reject lambda call operator
template in local [lambda] class.
* pt.c (instantiate_class_template_1): Don't instantiate lambda call
operator template when instantiating lambda class.
2013-09-12 Adam Butcher <adam@jessamine.co.uk>
* pt.c (instantiate_decl): Save/restore cp_unevaluated_operand and * pt.c (instantiate_decl): Save/restore cp_unevaluated_operand and
c_inhibit_evaluation_warnings. Reset if instantiating within a c_inhibit_evaluation_warnings. Reset if instantiating within a
function-local template. function-local template.
......
...@@ -312,7 +312,7 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \ ...@@ -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/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 \ 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 \ toplev.h $(TREE_INLINE_H) pointer-set.h gt-cp-pt.h intl.h \
c-family/c-objc.h cp/type-utils.h c-family/c-objc.h
cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_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) \ $(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 tree-diagnostic.h tree-pretty-print.h pointer-set.h c-family/c-objc.h
...@@ -331,8 +331,7 @@ cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) $(REAL_H) \ ...@@ -331,8 +331,7 @@ cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) $(REAL_H) \
gt-cp-mangle.h $(TARGET_H) $(TM_P_H) $(CGRAPH_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) \ 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 \ 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) \ 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) $(TM_H) coretypes.h pointer-set.h tree-iterator.h $(SPLAY_TREE_H)
cp/vtable-class-hierarchy.o: cp/vtable-class-hierarchy.c \ cp/vtable-class-hierarchy.o: cp/vtable-class-hierarchy.c \
......
...@@ -5455,12 +5455,10 @@ extern tree make_auto (void); ...@@ -5455,12 +5455,10 @@ extern tree make_auto (void);
extern tree make_decltype_auto (void); extern tree make_decltype_auto (void);
extern tree do_auto_deduction (tree, tree, tree); extern tree do_auto_deduction (tree, tree, tree);
extern tree type_uses_auto (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, extern void append_type_to_template_for_access_check (tree, tree, tree,
location_t); location_t);
extern tree splice_late_return_type (tree, tree); extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree); extern bool is_auto (const_tree);
extern bool is_auto_or_concept (const_tree);
extern tree process_template_parm (tree, location_t, tree, extern tree process_template_parm (tree, location_t, tree,
bool, bool); bool, bool);
extern tree end_template_parm_list (tree); extern tree end_template_parm_list (tree);
......
...@@ -10320,23 +10320,8 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -10320,23 +10320,8 @@ grokdeclarator (const cp_declarator *declarator,
if (type_uses_auto (type)) if (type_uses_auto (type))
{ {
if (current_class_type && LAMBDA_TYPE_P (current_class_type)) error ("parameter declared %<auto%>");
{ type = error_mark_node;
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. /* A parameter declared as an array of T is really a pointer to T.
......
...@@ -507,9 +507,8 @@ check_member_template (tree tmpl) ...@@ -507,9 +507,8 @@ check_member_template (tree tmpl)
|| (TREE_CODE (decl) == TYPE_DECL || (TREE_CODE (decl) == TYPE_DECL
&& MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)))) && MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))))
{ {
/* The parser rejects template declarations in local classes /* The parser rejects template declarations in local classes. */
(with the exception of generic lambdas). */ gcc_assert (!current_function_decl);
gcc_assert (!current_function_decl || LAMBDA_FUNCTION_P (decl));
/* The parser rejects any use of virtual in a function template. */ /* The parser rejects any use of virtual in a function template. */
gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
&& DECL_VIRTUAL_P (decl))); && DECL_VIRTUAL_P (decl)));
......
...@@ -196,7 +196,7 @@ lambda_function (tree lambda) ...@@ -196,7 +196,7 @@ lambda_function (tree lambda)
/*protect=*/0, /*want_type=*/false, /*protect=*/0, /*want_type=*/false,
tf_warning_or_error); tf_warning_or_error);
if (lambda) if (lambda)
lambda = STRIP_TEMPLATE (get_first_fn (lambda)); lambda = BASELINK_FUNCTIONS (lambda);
return lambda; return lambda;
} }
...@@ -741,22 +741,6 @@ nonlambda_method_basetype (void) ...@@ -741,22 +741,6 @@ nonlambda_method_basetype (void)
return TYPE_METHOD_BASETYPE (TREE_TYPE (fn)); return TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
} }
/* Helper function for maybe_add_lambda_conv_op; build a CALL_EXPR with
indicated FN and NARGS, but do not initialize the return type or any of the
argument slots. */
static tree
prepare_op_call (tree fn, int nargs)
{
tree t;
t = build_vl_exp (CALL_EXPR, nargs + 3);
CALL_EXPR_FN (t) = fn;
CALL_EXPR_STATIC_CHAIN (t) = NULL;
return t;
}
/* If the closure TYPE has a static op(), also add a conversion to function /* If the closure TYPE has a static op(), also add a conversion to function
pointer. */ pointer. */
...@@ -765,6 +749,9 @@ maybe_add_lambda_conv_op (tree type) ...@@ -765,6 +749,9 @@ maybe_add_lambda_conv_op (tree type)
{ {
bool nested = (current_function_decl != NULL_TREE); bool nested = (current_function_decl != NULL_TREE);
tree callop = lambda_function (type); tree callop = lambda_function (type);
tree rettype, name, fntype, fn, body, compound_stmt;
tree thistype, stattype, statfn, convfn, call, arg;
vec<tree, va_gc> *argvec;
if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE) if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
return; return;
...@@ -772,10 +759,6 @@ maybe_add_lambda_conv_op (tree type) ...@@ -772,10 +759,6 @@ maybe_add_lambda_conv_op (tree type)
if (processing_template_decl) if (processing_template_decl)
return; return;
bool const generic_lambda_p
= (DECL_TEMPLATE_INFO (callop)
&& DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop);
if (DECL_INITIAL (callop) == NULL_TREE) if (DECL_INITIAL (callop) == NULL_TREE)
{ {
/* If the op() wasn't instantiated due to errors, give up. */ /* If the op() wasn't instantiated due to errors, give up. */
...@@ -783,127 +766,16 @@ maybe_add_lambda_conv_op (tree type) ...@@ -783,127 +766,16 @@ maybe_add_lambda_conv_op (tree type)
return; return;
} }
/* Non-template conversion operators are defined directly with build_call_a stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
and using DIRECT_ARGVEC for arguments (including 'this'). Templates are FUNCTION_ARG_CHAIN (callop));
deferred and the CALL is built in-place. In the case of a deduced return
call op, the decltype expression, DECLTYPE_CALL, used as a substitute for
the return type is also built in-place. The arguments of DECLTYPE_CALL in
the return expression may differ in flags from those in the body CALL. In
particular, parameter pack expansions are marked PACK_EXPANSION_LOCAL_P in
the body CALL, but not in DECLTYPE_CALL. */
vec<tree, va_gc> *direct_argvec = 0;
tree decltype_call = 0, call = 0;
tree fn_result = TREE_TYPE (TREE_TYPE (callop));
if (generic_lambda_p)
{
/* Prepare the dependent member call for the static member function
'_FUN' and, potentially, prepare another call to be used in a decltype
return expression for a deduced return call op to allow for simple
implementation of the conversion operator. */
tree instance = build_nop (type, null_pointer_node);
tree objfn = build_min (COMPONENT_REF, NULL_TREE,
instance, DECL_NAME (callop), NULL_TREE);
int nargs = list_length (DECL_ARGUMENTS (callop)) - 1;
call = prepare_op_call (objfn, nargs);
if (type_uses_auto (fn_result))
decltype_call = prepare_op_call (objfn, nargs);
}
else
{
direct_argvec = make_tree_vector ();
direct_argvec->quick_push (build1 (NOP_EXPR,
TREE_TYPE (DECL_ARGUMENTS (callop)),
null_pointer_node));
}
/* Copy CALLOP's argument list (as per 'copy_list') as FN_ARGS in order to
declare the static member function "_FUN" below. For each arg append to
DIRECT_ARGVEC (for the non-template case) or populate the pre-allocated
call args (for the template case). If a parameter pack is found, expand
it, flagging it as PACK_EXPANSION_LOCAL_P for the body call. */
tree fn_args = NULL_TREE;
{
int ix = 0;
tree src = DECL_CHAIN (DECL_ARGUMENTS (callop));
tree tgt;
while (src)
{
tree new_node = copy_node (src);
if (!fn_args)
fn_args = tgt = new_node;
else
{
TREE_CHAIN (tgt) = new_node;
tgt = new_node;
}
mark_exp_read (tgt);
if (generic_lambda_p)
{
if (FUNCTION_PARAMETER_PACK_P (tgt))
{
tree a = make_pack_expansion (tgt);
if (decltype_call)
CALL_EXPR_ARG (decltype_call, ix) = copy_node (a);
PACK_EXPANSION_LOCAL_P (a) = true;
CALL_EXPR_ARG (call, ix) = a;
}
else
{
tree a = convert_from_reference (tgt);
CALL_EXPR_ARG (call, ix) = a;
if (decltype_call)
CALL_EXPR_ARG (decltype_call, ix) = copy_node (a);
}
++ix;
}
else
vec_safe_push (direct_argvec, tgt);
src = TREE_CHAIN (src);
}
}
if (generic_lambda_p)
{
if (decltype_call)
{
++processing_template_decl;
fn_result = finish_decltype_type
(decltype_call, /*id_expression_or_member_access_p=*/false,
tf_warning_or_error);
--processing_template_decl;
}
}
else
{
call = build_call_a (callop,
direct_argvec->length (),
direct_argvec->address ());
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
}
CALL_FROM_THUNK_P (call) = 1;
tree stattype = build_function_type (fn_result, FUNCTION_ARG_CHAIN (callop));
/* First build up the conversion op. */ /* First build up the conversion op. */
tree rettype = build_pointer_type (stattype); rettype = build_pointer_type (stattype);
tree name = mangle_conv_op_name_for_type (rettype); name = mangle_conv_op_name_for_type (rettype);
tree thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST); thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST);
tree fntype = build_method_type_directly (thistype, rettype, void_list_node); fntype = build_method_type_directly (thistype, rettype, void_list_node);
tree convfn = build_lang_decl (FUNCTION_DECL, name, fntype); fn = convfn = build_lang_decl (FUNCTION_DECL, name, fntype);
tree fn = convfn;
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
...@@ -922,9 +794,6 @@ maybe_add_lambda_conv_op (tree type) ...@@ -922,9 +794,6 @@ maybe_add_lambda_conv_op (tree type)
if (nested) if (nested)
DECL_INTERFACE_KNOWN (fn) = 1; DECL_INTERFACE_KNOWN (fn) = 1;
if (generic_lambda_p)
fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
add_method (type, fn, NULL_TREE); add_method (type, fn, NULL_TREE);
/* Generic thunk code fails for varargs; we'll complain in mark_used if /* Generic thunk code fails for varargs; we'll complain in mark_used if
...@@ -938,8 +807,7 @@ maybe_add_lambda_conv_op (tree type) ...@@ -938,8 +807,7 @@ maybe_add_lambda_conv_op (tree type)
/* Now build up the thunk to be returned. */ /* Now build up the thunk to be returned. */
name = get_identifier ("_FUN"); name = get_identifier ("_FUN");
tree statfn = build_lang_decl (FUNCTION_DECL, name, stattype); fn = statfn = build_lang_decl (FUNCTION_DECL, name, stattype);
fn = statfn;
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
&& DECL_ALIGN (fn) < 2 * BITS_PER_UNIT) && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT)
...@@ -952,8 +820,8 @@ maybe_add_lambda_conv_op (tree type) ...@@ -952,8 +820,8 @@ maybe_add_lambda_conv_op (tree type)
DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1;
DECL_STATIC_FUNCTION_P (fn) = 1; DECL_STATIC_FUNCTION_P (fn) = 1;
DECL_ARGUMENTS (fn) = fn_args; DECL_ARGUMENTS (fn) = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
for (tree arg = fn_args; arg; arg = DECL_CHAIN (arg)) for (arg = DECL_ARGUMENTS (fn); arg; arg = DECL_CHAIN (arg))
{ {
/* Avoid duplicate -Wshadow warnings. */ /* Avoid duplicate -Wshadow warnings. */
DECL_NAME (arg) = NULL_TREE; DECL_NAME (arg) = NULL_TREE;
...@@ -962,9 +830,6 @@ maybe_add_lambda_conv_op (tree type) ...@@ -962,9 +830,6 @@ maybe_add_lambda_conv_op (tree type)
if (nested) if (nested)
DECL_INTERFACE_KNOWN (fn) = 1; DECL_INTERFACE_KNOWN (fn) = 1;
if (generic_lambda_p)
fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
add_method (type, fn, NULL_TREE); add_method (type, fn, NULL_TREE);
if (nested) if (nested)
...@@ -985,17 +850,29 @@ maybe_add_lambda_conv_op (tree type) ...@@ -985,17 +850,29 @@ maybe_add_lambda_conv_op (tree type)
((symtab_node) cgraph_get_create_node (statfn), ((symtab_node) cgraph_get_create_node (statfn),
(symtab_node) cgraph_get_create_node (callop)); (symtab_node) cgraph_get_create_node (callop));
} }
tree body = begin_function_body (); body = begin_function_body ();
tree compound_stmt = begin_compound_stmt (0); compound_stmt = begin_compound_stmt (0);
arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)),
null_pointer_node);
argvec = make_tree_vector ();
argvec->quick_push (arg);
for (arg = DECL_ARGUMENTS (statfn); arg; arg = DECL_CHAIN (arg))
{
mark_exp_read (arg);
vec_safe_push (argvec, arg);
}
call = build_call_a (callop, argvec->length (), argvec->address ());
CALL_FROM_THUNK_P (call) = 1;
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
call = convert_from_reference (call); call = convert_from_reference (call);
finish_return_stmt (call); finish_return_stmt (call);
finish_compound_stmt (compound_stmt); finish_compound_stmt (compound_stmt);
finish_function_body (body); finish_function_body (body);
fn = finish_function (/*inline*/2); expand_or_defer_fn (finish_function (2));
if (!generic_lambda_p)
expand_or_defer_fn (fn);
/* Generate the body of the conversion op. */ /* Generate the body of the conversion op. */
...@@ -1011,9 +888,7 @@ maybe_add_lambda_conv_op (tree type) ...@@ -1011,9 +888,7 @@ maybe_add_lambda_conv_op (tree type)
finish_compound_stmt (compound_stmt); finish_compound_stmt (compound_stmt);
finish_function_body (body); finish_function_body (body);
fn = finish_function (/*inline*/2); expand_or_defer_fn (finish_function (2));
if (!generic_lambda_p)
expand_or_defer_fn (fn);
if (nested) if (nested)
pop_function_context (); pop_function_context ();
......
...@@ -341,12 +341,6 @@ typedef struct GTY(()) cp_parser { ...@@ -341,12 +341,6 @@ typedef struct GTY(()) cp_parser {
/* The number of template parameter lists that apply directly to the /* The number of template parameter lists that apply directly to the
current declaration. */ current declaration. */
unsigned num_template_parameter_lists; 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; } cp_parser;
/* In parser.c */ /* In parser.c */
......
...@@ -41,7 +41,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -41,7 +41,6 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h" #include "toplev.h"
#include "timevar.h" #include "timevar.h"
#include "tree-iterator.h" #include "tree-iterator.h"
#include "type-utils.h"
/* The type of functions taking a tree, and some additional data, and /* The type of functions taking a tree, and some additional data, and
returning an int. */ returning an int. */
...@@ -9104,9 +9103,7 @@ instantiate_class_template_1 (tree type) ...@@ -9104,9 +9103,7 @@ instantiate_class_template_1 (tree type)
tree decl = lambda_function (type); tree decl = lambda_function (type);
if (decl) if (decl)
{ {
if (!DECL_TEMPLATE_INFO (decl) instantiate_decl (decl, false, false);
|| DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) != decl)
instantiate_decl (decl, false, false);
/* We need to instantiate the capture list from the template /* We need to instantiate the capture list from the template
after we've instantiated the closure members, but before we after we've instantiated the closure members, but before we
...@@ -21111,35 +21108,31 @@ is_auto (const_tree type) ...@@ -21111,35 +21108,31 @@ is_auto (const_tree type)
return false; return false;
} }
/* Returns the TEMPLATE_TYPE_PARM in TYPE representing `auto' iff TYPE contains /* Returns true iff TYPE contains a use of 'auto'. Since auto can only
a use of `auto'. Returns NULL_TREE otherwise. */ appear as a type-specifier for the declaration in question, we don't
have to look through the whole type. */
tree tree
type_uses_auto (tree type) type_uses_auto (tree type)
{ {
return find_type_usage (type, is_auto); enum tree_code code;
} if (is_auto (type))
return type;
/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto', code = TREE_CODE (type);
'decltype(auto)' or a concept. */
bool if (code == POINTER_TYPE || code == REFERENCE_TYPE
is_auto_or_concept (const_tree type) || code == OFFSET_TYPE || code == FUNCTION_TYPE
{ || code == METHOD_TYPE || code == ARRAY_TYPE)
return is_auto (type); // or concept return type_uses_auto (TREE_TYPE (type));
}
/* Returns the TEMPLATE_TYPE_PARM in TYPE representing a generic type (`auto' or if (TYPE_PTRMEMFUNC_P (type))
a concept identifier) iff TYPE contains a use of a generic type. Returns return type_uses_auto (TREE_TYPE (TREE_TYPE
NULL_TREE otherwise. */ (TYPE_PTRMEMFUNC_FN_TYPE (type))));
tree return NULL_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 /* For a given template T, return the vector of typedefs referenced
in T for which access check is needed at T instantiation time. in T for which access check is needed at T instantiation time.
T is either a FUNCTION_DECL or a RECORD_TYPE. 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
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