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
This commit is contained in:
parent
19ba6aab7b
commit
f3a880f8ce
|
@ -1,62 +1,8 @@
|
|||
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>
|
||||
|
||||
PR driver/42955
|
||||
* Make-lang.in: Do not install driver binaries in $(target)/bin.
|
||||
|
||||
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
|
||||
|
|
|
@ -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 cp/type-utils.h
|
||||
c-family/c-objc.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,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)
|
||||
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) \
|
||||
cp/type-utils.h
|
||||
c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_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 \
|
||||
|
|
|
@ -5455,12 +5455,10 @@ 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);
|
||||
|
|
|
@ -10320,23 +10320,8 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
|
||||
if (type_uses_auto (type))
|
||||
{
|
||||
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");
|
||||
error ("parameter declared %<auto%>");
|
||||
type = error_mark_node;
|
||||
}
|
||||
|
||||
/* A parameter declared as an array of T is really a pointer to T.
|
||||
|
|
|
@ -507,9 +507,8 @@ check_member_template (tree tmpl)
|
|||
|| (TREE_CODE (decl) == TYPE_DECL
|
||||
&& MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))))
|
||||
{
|
||||
/* The parser rejects template declarations in local classes
|
||||
(with the exception of generic lambdas). */
|
||||
gcc_assert (!current_function_decl || LAMBDA_FUNCTION_P (decl));
|
||||
/* The parser rejects template declarations in local classes. */
|
||||
gcc_assert (!current_function_decl);
|
||||
/* The parser rejects any use of virtual in a function template. */
|
||||
gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_VIRTUAL_P (decl)));
|
||||
|
|
189
gcc/cp/lambda.c
189
gcc/cp/lambda.c
|
@ -196,7 +196,7 @@ lambda_function (tree lambda)
|
|||
/*protect=*/0, /*want_type=*/false,
|
||||
tf_warning_or_error);
|
||||
if (lambda)
|
||||
lambda = STRIP_TEMPLATE (get_first_fn (lambda));
|
||||
lambda = BASELINK_FUNCTIONS (lambda);
|
||||
return lambda;
|
||||
}
|
||||
|
||||
|
@ -741,22 +741,6 @@ nonlambda_method_basetype (void)
|
|||
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
|
||||
pointer. */
|
||||
|
||||
|
@ -765,6 +749,9 @@ maybe_add_lambda_conv_op (tree type)
|
|||
{
|
||||
bool nested = (current_function_decl != NULL_TREE);
|
||||
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)
|
||||
return;
|
||||
|
@ -772,10 +759,6 @@ maybe_add_lambda_conv_op (tree type)
|
|||
if (processing_template_decl)
|
||||
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 the op() wasn't instantiated due to errors, give up. */
|
||||
|
@ -783,127 +766,16 @@ maybe_add_lambda_conv_op (tree type)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Non-template conversion operators are defined directly with build_call_a
|
||||
and using DIRECT_ARGVEC for arguments (including 'this'). Templates are
|
||||
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));
|
||||
stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
|
||||
FUNCTION_ARG_CHAIN (callop));
|
||||
|
||||
/* First build up the conversion op. */
|
||||
|
||||
tree rettype = build_pointer_type (stattype);
|
||||
tree name = mangle_conv_op_name_for_type (rettype);
|
||||
tree thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST);
|
||||
tree fntype = build_method_type_directly (thistype, rettype, void_list_node);
|
||||
tree convfn = build_lang_decl (FUNCTION_DECL, name, fntype);
|
||||
tree fn = convfn;
|
||||
rettype = build_pointer_type (stattype);
|
||||
name = mangle_conv_op_name_for_type (rettype);
|
||||
thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST);
|
||||
fntype = build_method_type_directly (thistype, rettype, void_list_node);
|
||||
fn = convfn = build_lang_decl (FUNCTION_DECL, name, fntype);
|
||||
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
|
||||
|
||||
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
|
||||
|
@ -922,9 +794,6 @@ maybe_add_lambda_conv_op (tree type)
|
|||
if (nested)
|
||||
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);
|
||||
|
||||
/* Generic thunk code fails for varargs; we'll complain in mark_used if
|
||||
|
@ -938,8 +807,7 @@ maybe_add_lambda_conv_op (tree type)
|
|||
/* Now build up the thunk to be returned. */
|
||||
|
||||
name = get_identifier ("_FUN");
|
||||
tree statfn = build_lang_decl (FUNCTION_DECL, name, stattype);
|
||||
fn = statfn;
|
||||
fn = statfn = build_lang_decl (FUNCTION_DECL, name, stattype);
|
||||
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
|
||||
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
|
||||
&& DECL_ALIGN (fn) < 2 * BITS_PER_UNIT)
|
||||
|
@ -952,8 +820,8 @@ maybe_add_lambda_conv_op (tree type)
|
|||
DECL_NOT_REALLY_EXTERN (fn) = 1;
|
||||
DECL_DECLARED_INLINE_P (fn) = 1;
|
||||
DECL_STATIC_FUNCTION_P (fn) = 1;
|
||||
DECL_ARGUMENTS (fn) = fn_args;
|
||||
for (tree arg = fn_args; arg; arg = DECL_CHAIN (arg))
|
||||
DECL_ARGUMENTS (fn) = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
|
||||
for (arg = DECL_ARGUMENTS (fn); arg; arg = DECL_CHAIN (arg))
|
||||
{
|
||||
/* Avoid duplicate -Wshadow warnings. */
|
||||
DECL_NAME (arg) = NULL_TREE;
|
||||
|
@ -962,9 +830,6 @@ maybe_add_lambda_conv_op (tree type)
|
|||
if (nested)
|
||||
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);
|
||||
|
||||
if (nested)
|
||||
|
@ -985,17 +850,29 @@ maybe_add_lambda_conv_op (tree type)
|
|||
((symtab_node) cgraph_get_create_node (statfn),
|
||||
(symtab_node) cgraph_get_create_node (callop));
|
||||
}
|
||||
tree body = begin_function_body ();
|
||||
tree compound_stmt = begin_compound_stmt (0);
|
||||
body = begin_function_body ();
|
||||
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);
|
||||
finish_return_stmt (call);
|
||||
|
||||
finish_compound_stmt (compound_stmt);
|
||||
finish_function_body (body);
|
||||
|
||||
fn = finish_function (/*inline*/2);
|
||||
if (!generic_lambda_p)
|
||||
expand_or_defer_fn (fn);
|
||||
expand_or_defer_fn (finish_function (2));
|
||||
|
||||
/* Generate the body of the conversion op. */
|
||||
|
||||
|
@ -1011,9 +888,7 @@ maybe_add_lambda_conv_op (tree type)
|
|||
finish_compound_stmt (compound_stmt);
|
||||
finish_function_body (body);
|
||||
|
||||
fn = finish_function (/*inline*/2);
|
||||
if (!generic_lambda_p)
|
||||
expand_or_defer_fn (fn);
|
||||
expand_or_defer_fn (finish_function (2));
|
||||
|
||||
if (nested)
|
||||
pop_function_context ();
|
||||
|
|
235
gcc/cp/parser.c
235
gcc/cp/parser.c
|
@ -38,7 +38,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "plugin.h"
|
||||
#include "tree-pretty-print.h"
|
||||
#include "parser.h"
|
||||
#include "type-utils.h"
|
||||
|
||||
|
||||
/* The lexer. */
|
||||
|
@ -2064,11 +2063,6 @@ static vec<constructor_elt, va_gc> *cp_parser_initializer_list
|
|||
static bool cp_parser_ctor_initializer_opt_and_function_body
|
||||
(cp_parser *, bool);
|
||||
|
||||
static tree add_implicit_template_parms
|
||||
(cp_parser *, size_t, tree);
|
||||
static tree finish_fully_implicit_template
|
||||
(cp_parser *, tree);
|
||||
|
||||
/* Classes [gram.class] */
|
||||
|
||||
static tree cp_parser_class_name
|
||||
|
@ -3391,9 +3385,6 @@ cp_parser_new (void)
|
|||
/* No template parameters apply. */
|
||||
parser->num_template_parameter_lists = 0;
|
||||
|
||||
/* Not declaring an implicit function template. */
|
||||
parser->fully_implicit_function_template_p = false;
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
|
@ -8558,12 +8549,10 @@ cp_parser_lambda_expression (cp_parser* parser)
|
|||
= parser->num_template_parameter_lists;
|
||||
unsigned char in_statement = parser->in_statement;
|
||||
bool in_switch_statement_p = parser->in_switch_statement_p;
|
||||
bool fully_implicit_function_template_p = parser->fully_implicit_function_template_p;
|
||||
|
||||
parser->num_template_parameter_lists = 0;
|
||||
parser->in_statement = 0;
|
||||
parser->in_switch_statement_p = false;
|
||||
parser->fully_implicit_function_template_p = false;
|
||||
|
||||
/* By virtue of defining a local class, a lambda expression has access to
|
||||
the private variables of enclosing classes. */
|
||||
|
@ -8587,7 +8576,6 @@ cp_parser_lambda_expression (cp_parser* parser)
|
|||
parser->num_template_parameter_lists = saved_num_template_parameter_lists;
|
||||
parser->in_statement = in_statement;
|
||||
parser->in_switch_statement_p = in_switch_statement_p;
|
||||
parser->fully_implicit_function_template_p = fully_implicit_function_template_p;
|
||||
}
|
||||
|
||||
pop_deferring_access_checks ();
|
||||
|
@ -8795,7 +8783,6 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
|
|||
/* Parse the (optional) middle of a lambda expression.
|
||||
|
||||
lambda-declarator:
|
||||
< template-parameter-list [opt] >
|
||||
( parameter-declaration-clause [opt] )
|
||||
attribute-specifier [opt]
|
||||
mutable [opt]
|
||||
|
@ -8815,30 +8802,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
|
|||
tree param_list = void_list_node;
|
||||
tree attributes = NULL_TREE;
|
||||
tree exception_spec = NULL_TREE;
|
||||
tree template_param_list = NULL_TREE;
|
||||
|
||||
/* The template-parameter-list is optional, but must begin with
|
||||
an opening angle if present. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
|
||||
{
|
||||
if (cxx_dialect < cxx1y)
|
||||
pedwarn (parser->lexer->next_token->location, 0,
|
||||
"lambda templates are only available with "
|
||||
"-std=c++1y or -std=gnu++1y");
|
||||
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
template_param_list = cp_parser_template_parameter_list (parser);
|
||||
|
||||
cp_parser_skip_to_end_of_template_parameter_list (parser);
|
||||
|
||||
/* We just processed one more parameter list. */
|
||||
++parser->num_template_parameter_lists;
|
||||
}
|
||||
|
||||
/* The parameter-declaration-clause is optional (unless
|
||||
template-parameter-list was given), but must begin with an
|
||||
opening parenthesis if present. */
|
||||
/* The lambda-declarator is optional, but must begin with an opening
|
||||
parenthesis if present. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
|
||||
{
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
@ -8881,8 +8847,6 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
|
|||
trailing-return-type in case of decltype. */
|
||||
pop_bindings_and_leave_scope ();
|
||||
}
|
||||
else if (template_param_list != NULL_TREE) // generate diagnostic
|
||||
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
|
||||
|
||||
/* Create the function call operator.
|
||||
|
||||
|
@ -8926,14 +8890,6 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
|
|||
DECL_ARTIFICIAL (fco) = 1;
|
||||
/* Give the object parameter a different name. */
|
||||
DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure");
|
||||
if (template_param_list)
|
||||
{
|
||||
fco = finish_member_template_decl (fco);
|
||||
finish_template_decl (template_param_list);
|
||||
--parser->num_template_parameter_lists;
|
||||
}
|
||||
else if (parser->fully_implicit_function_template_p)
|
||||
fco = finish_fully_implicit_template (parser, fco);
|
||||
}
|
||||
|
||||
finish_member_declaration (fco);
|
||||
|
@ -9056,11 +9012,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
|
|||
finish_lambda_scope ();
|
||||
|
||||
/* Finish the function and generate code for it if necessary. */
|
||||
tree fn = finish_function (/*inline*/2);
|
||||
|
||||
/* Only expand if the call op is not a template. */
|
||||
if (!DECL_TEMPLATE_INFO (fco))
|
||||
expand_or_defer_fn (fn);
|
||||
expand_or_defer_fn (finish_function (/*inline*/2));
|
||||
}
|
||||
|
||||
parser->local_variables_forbidden_p = local_variables_forbidden_p;
|
||||
|
@ -16804,10 +16756,8 @@ cp_parser_direct_declarator (cp_parser* parser,
|
|||
/* Parse the parameter-declaration-clause. */
|
||||
params = cp_parser_parameter_declaration_clause (parser);
|
||||
|
||||
/* Restore saved template parameter lists accounting for implicit
|
||||
template parameters. */
|
||||
parser->num_template_parameter_lists
|
||||
+= saved_num_template_parameter_lists;
|
||||
= saved_num_template_parameter_lists;
|
||||
|
||||
/* Consume the `)'. */
|
||||
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
|
||||
|
@ -17905,7 +17855,6 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
|
|||
tree *tail = ¶meters;
|
||||
bool saved_in_unbraced_linkage_specification_p;
|
||||
int index = 0;
|
||||
int implicit_template_parms = 0;
|
||||
|
||||
/* Assume all will go well. */
|
||||
*is_error = false;
|
||||
|
@ -17933,18 +17882,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
|
|||
deprecated_state = DEPRECATED_SUPPRESS;
|
||||
|
||||
if (parameter)
|
||||
{
|
||||
decl = grokdeclarator (parameter->declarator,
|
||||
¶meter->decl_specifiers,
|
||||
PARM,
|
||||
parameter->default_argument != NULL_TREE,
|
||||
¶meter->decl_specifiers.attributes);
|
||||
|
||||
if (TREE_TYPE (decl) != error_mark_node
|
||||
&& parameter->decl_specifiers.type
|
||||
&& is_auto_or_concept (parameter->decl_specifiers.type))
|
||||
++implicit_template_parms;
|
||||
}
|
||||
decl = grokdeclarator (parameter->declarator,
|
||||
¶meter->decl_specifiers,
|
||||
PARM,
|
||||
parameter->default_argument != NULL_TREE,
|
||||
¶meter->decl_specifiers.attributes);
|
||||
|
||||
deprecated_state = DEPRECATED_NORMAL;
|
||||
|
||||
|
@ -18032,11 +17974,6 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
|
|||
parser->in_unbraced_linkage_specification_p
|
||||
= saved_in_unbraced_linkage_specification_p;
|
||||
|
||||
if (parameters != error_mark_node && implicit_template_parms)
|
||||
parameters = add_implicit_template_parms (parser,
|
||||
implicit_template_parms,
|
||||
parameters);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
@ -20043,11 +19980,7 @@ cp_parser_member_declaration (cp_parser* parser)
|
|||
attributes);
|
||||
/* If the member was not a friend, declare it here. */
|
||||
if (!friend_p)
|
||||
{
|
||||
if (parser->fully_implicit_function_template_p)
|
||||
decl = finish_fully_implicit_template (parser, decl);
|
||||
finish_member_declaration (decl);
|
||||
}
|
||||
finish_member_declaration (decl);
|
||||
/* Peek at the next token. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
/* If the next token is a semicolon, consume it. */
|
||||
|
@ -20063,8 +19996,6 @@ cp_parser_member_declaration (cp_parser* parser)
|
|||
initializer, /*init_const_expr_p=*/true,
|
||||
asm_specification,
|
||||
attributes);
|
||||
if (parser->fully_implicit_function_template_p)
|
||||
decl = finish_fully_implicit_template (parser, decl);
|
||||
}
|
||||
|
||||
/* Reset PREFIX_ATTRIBUTES. */
|
||||
|
@ -22332,9 +22263,6 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
|
|||
= saved_num_template_parameter_lists;
|
||||
parser->in_function_body = saved_in_function_body;
|
||||
|
||||
if (parser->fully_implicit_function_template_p)
|
||||
finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
|
@ -28880,147 +28808,4 @@ c_parse_file (void)
|
|||
the_parser = NULL;
|
||||
}
|
||||
|
||||
/* Create an identifier for a generic parameter type (a synthesized
|
||||
template parameter implied by `auto' or a concept identifier). */
|
||||
|
||||
static tree
|
||||
make_generic_type_name (int i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf (buf, "__GenT%d", i);
|
||||
return get_identifier (buf);
|
||||
}
|
||||
|
||||
/* Predicate that behaves as is_auto_or_concept but matches the parent
|
||||
node of the generic type rather than the generic type itself. This
|
||||
allows for type transformation in add_implicit_template_parms. */
|
||||
|
||||
static inline bool
|
||||
tree_type_is_auto_or_concept (const_tree t)
|
||||
{
|
||||
return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t));
|
||||
}
|
||||
|
||||
/* Add COUNT implicit template parameters gleaned from the generic
|
||||
type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS
|
||||
(creating a new template parameter list if necessary). Returns
|
||||
PARAMETERS suitably rewritten to reference the newly created types
|
||||
or ERROR_MARK_NODE on failure. */
|
||||
|
||||
tree
|
||||
add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters)
|
||||
{
|
||||
gcc_assert (current_binding_level->kind == sk_function_parms);
|
||||
|
||||
cp_binding_level *fn_parms_scope = current_binding_level;
|
||||
|
||||
bool become_template =
|
||||
fn_parms_scope->level_chain->kind != sk_template_parms;
|
||||
|
||||
size_t synth_idx = 0;
|
||||
|
||||
/* Roll back a scope level and either introduce a new template parameter list
|
||||
or update an existing one. The function scope is added back after template
|
||||
parameter synthesis below. */
|
||||
current_binding_level = fn_parms_scope->level_chain;
|
||||
|
||||
/* TPARMS tracks the function's template parameter list. This is either a new
|
||||
chain in the case of a fully implicit function template or an extension of
|
||||
the function's explicitly specified template parameter list. */
|
||||
tree tparms = NULL_TREE;
|
||||
|
||||
if (become_template)
|
||||
{
|
||||
push_deferring_access_checks (dk_deferred);
|
||||
begin_template_parm_list ();
|
||||
|
||||
parser->fully_implicit_function_template_p = true;
|
||||
++parser->num_template_parameter_lists;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Roll back the innermost template parameter list such that it may be
|
||||
extended in the loop below as if it were being explicitly declared. */
|
||||
|
||||
gcc_assert (current_template_parms);
|
||||
|
||||
/* Pop the innermost template parms into TPARMS. */
|
||||
tree inner_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
|
||||
current_template_parms = TREE_CHAIN (current_template_parms);
|
||||
|
||||
size_t inner_vec_len = TREE_VEC_LENGTH (inner_vec);
|
||||
if (inner_vec_len != 0)
|
||||
{
|
||||
tree t = tparms = TREE_VEC_ELT (inner_vec, 0);
|
||||
for (size_t n = 1; n < inner_vec_len; ++n)
|
||||
t = TREE_CHAIN (t) = TREE_VEC_ELT (inner_vec, n);
|
||||
}
|
||||
|
||||
++processing_template_parmlist;
|
||||
}
|
||||
|
||||
for (tree p = parameters; p && synth_idx < count; p = TREE_CHAIN (p))
|
||||
{
|
||||
tree generic_type_ptr
|
||||
= find_type_usage (TREE_VALUE (p), tree_type_is_auto_or_concept);
|
||||
|
||||
if (!generic_type_ptr)
|
||||
continue;
|
||||
|
||||
tree synth_id = make_generic_type_name (synth_idx++);
|
||||
tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
|
||||
synth_id);
|
||||
tparms = process_template_parm (tparms, DECL_SOURCE_LOCATION (TREE_VALUE
|
||||
(p)),
|
||||
build_tree_list (NULL_TREE,
|
||||
synth_tmpl_parm),
|
||||
/*non_type=*/false,
|
||||
/*param_pack=*/false);
|
||||
|
||||
/* Rewrite the type of P to be the template_parm added above (getdecls is
|
||||
used to retrieve it since it is the most recent declaration in this
|
||||
scope). Qualifiers need to be preserved also. */
|
||||
|
||||
tree& cur_type = TREE_TYPE (generic_type_ptr);
|
||||
tree new_type = TREE_TYPE (getdecls ());
|
||||
|
||||
if (TYPE_QUALS (cur_type))
|
||||
cur_type = cp_build_qualified_type (new_type, TYPE_QUALS (cur_type));
|
||||
else
|
||||
cur_type = new_type;
|
||||
}
|
||||
|
||||
gcc_assert (synth_idx == count);
|
||||
|
||||
push_binding_level (fn_parms_scope);
|
||||
|
||||
end_template_parm_list (tparms);
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/* Finish the declaration of a fully implicit function template. Such a
|
||||
template has no explicit template parameter list so has not been through the
|
||||
normal template head and tail processing. add_implicit_template_parms tries
|
||||
to do the head; this tries to do the tail. MEMBER_DECL_OPT should be
|
||||
provided if the declaration is a class member such that its template
|
||||
declaration can be completed. If MEMBER_DECL_OPT is provided the finished
|
||||
form is returned. Otherwise NULL_TREE is returned. */
|
||||
|
||||
tree
|
||||
finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt)
|
||||
{
|
||||
gcc_assert (parser->fully_implicit_function_template_p);
|
||||
|
||||
pop_deferring_access_checks ();
|
||||
if (member_decl_opt)
|
||||
member_decl_opt = finish_member_template_decl (member_decl_opt);
|
||||
end_template_decl ();
|
||||
|
||||
parser->fully_implicit_function_template_p = false;
|
||||
--parser->num_template_parameter_lists;
|
||||
|
||||
return member_decl_opt;
|
||||
}
|
||||
|
||||
#include "gt-cp-parser.h"
|
||||
|
|
|
@ -341,12 +341,6 @@ 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 */
|
||||
|
|
47
gcc/cp/pt.c
47
gcc/cp/pt.c
|
@ -41,7 +41,6 @@ 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. */
|
||||
|
@ -9104,9 +9103,7 @@ instantiate_class_template_1 (tree type)
|
|||
tree decl = lambda_function (type);
|
||||
if (decl)
|
||||
{
|
||||
if (!DECL_TEMPLATE_INFO (decl)
|
||||
|| DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) != decl)
|
||||
instantiate_decl (decl, false, false);
|
||||
instantiate_decl (decl, false, false);
|
||||
|
||||
/* We need to instantiate the capture list from the template
|
||||
after we've instantiated the closure members, but before we
|
||||
|
@ -21111,35 +21108,31 @@ is_auto (const_tree type)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Returns the TEMPLATE_TYPE_PARM in TYPE representing `auto' iff TYPE contains
|
||||
a use of `auto'. Returns NULL_TREE otherwise. */
|
||||
/* 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. */
|
||||
|
||||
tree
|
||||
type_uses_auto (tree type)
|
||||
{
|
||||
return find_type_usage (type, is_auto);
|
||||
enum tree_code code;
|
||||
if (is_auto (type))
|
||||
return type;
|
||||
|
||||
code = TREE_CODE (type);
|
||||
|
||||
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));
|
||||
|
||||
if (TYPE_PTRMEMFUNC_P (type))
|
||||
return type_uses_auto (TREE_TYPE (TREE_TYPE
|
||||
(TYPE_PTRMEMFUNC_FN_TYPE (type))));
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto',
|
||||
'decltype(auto)' or a concept. */
|
||||
|
||||
bool
|
||||
is_auto_or_concept (const_tree type)
|
||||
{
|
||||
return is_auto (type); // or concept
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
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.
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/* 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
|
Loading…
Reference in New Issue