summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog69
-rw-r--r--gcc/cp/call.c3
-rw-r--r--gcc/cp/cp-tree.h30
-rw-r--r--gcc/cp/cvt.c1
-rw-r--r--gcc/cp/mangle.c95
-rw-r--r--gcc/cp/name-lookup.c5
-rw-r--r--gcc/cp/parser.c14
-rw-r--r--gcc/cp/pt.c160
-rw-r--r--gcc/cp/semantics.c34
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cp/typeck.c6
11 files changed, 363 insertions, 56 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 269773532fb..063db183eb3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,72 @@
+2009-10-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/36816
+ * pt.c (maybe_adjust_types_for_deduction): Do rvalue ref adjustment
+ even when DEDUCE_EXACT.
+
+ PR c++/37177
+ * pt.c (resolve_nondeduced_context): New.
+ * cvt.c (convert_to_void): Call it.
+ * semantics.c (finish_decltype_type): Likewise.
+ * typeck.c (decay_conversion): Here too.
+ * pt.c (tsubst_decl): Don't clobber input_location.
+ Don't register a bad specialization.
+
+2009-10-07 Gabriel Dos Reis <gdr@cs.tamu.edu>
+
+ * cp-tree.h: Fix location of documentation for DECL_LANG_FLAG_7.
+
+2009-10-07 Jason Merrill <jason@redhat.com>
+
+ PR c++/39863
+ * pt.c (tsubst_pack_expansion): Don't do anything now if we
+ have incomplete packs of different lengths.
+
+ PR c++/41038
+ * tree.c (build_qualified_name): Call convert_from_reference.
+
+2009-10-06 Jason Merrill <jason@redhat.com>
+
+ Fix lookup of initialized captures in unevaluated context.
+ * cp-tree.h (DECL_NORMAL_CAPTURE_P): New.
+ * name-lookup.c (qualify_lookup): Check it.
+ * parser.c (cp_parser_lambda_introducer): Pass explicit_init_p
+ to add_capture.
+ * semantics.c (add_capture): Set DECL_NORMAL_CAPTURE_P
+ on captures without explicit init.
+ (add_default_capture): Pass explicit_init_p.
+
+ Fix capture by copy of types with explicit copy constructor.
+ * cp-tree.h (TARGET_EXPR_DIRECT_INIT_P): New.
+ (DIRECT_INIT_EXPR_P): New.
+ * typeck.c (convert_for_initialization): Just return if
+ DIRECT_INIT_EXPR_P.
+ * semantics.c (build_lambda_object): Use
+ TARGET_EXPR_DIRECT_INIT_P for normal captures.
+
+2009-10-05 Jason Merrill <jason@redhat.com>
+
+ * parser.c: Mark lambda_scope and lambda_count for PCH.
+
+2009-10-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/41553
+ * parser.c (cp_parser_lambda_introducer): Avoid infinite loop on
+ parse error.
+
+2009-10-02 Jason Merrill <jason@redhat.com>
+
+ * mangle.c (write_unnamed_type_name): Implement.
+ (local_class_index): Split out from...
+ (discriminator_for_local_entity): ...here.
+ (nested_anon_class_index): New.
+ * cp-tree.h (TYPE_FUNCTION_SCOPE_P): New.
+
+2009-10-02 Janis Johnson <janis187@us.ibm.com>
+
+ * call.c (convert_arg_to_ellipsis): Avoid promoting decimal32
+ to double.
+
2009-10-01 Jason Merrill <jason@redhat.com>
* parser.c (cp_parser_lambda_expression): Compute visibility.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 8c1bb0edd47..3fc22f2b911 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5104,7 +5104,8 @@ convert_arg_to_ellipsis (tree arg)
promoted type before the call. */
if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (arg))
- < TYPE_PRECISION (double_type_node)))
+ < TYPE_PRECISION (double_type_node))
+ && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (arg))))
arg = convert_to_real (double_type_node, arg);
else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
arg = perform_integral_promotions (arg);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fc00176c276..3d826b9ad92 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -97,6 +97,7 @@ framework extensions, you must include this file before toplev.h, not after.
STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
TYPENAME_IS_RESOLVING_P (in TYPE_NAME_TYPE)
LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (in LAMBDA_EXPR)
+ TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK)
@@ -112,8 +113,6 @@ framework extensions, you must include this file before toplev.h, not after.
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
TYPE_MARKED_P (in _TYPE)
- 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL)
- 8: DECL_DECLARED_CONSTEXPR_P (in VAR_DECL, FUNCTION_DECL)
Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P
@@ -147,6 +146,8 @@ framework extensions, you must include this file before toplev.h, not after.
DECL_FIELD_IS_BASE (in FIELD_DECL)
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
DECL_THUNK_P (in a member FUNCTION_DECL)
+ DECL_NORMAL_CAPTURE_P (in FIELD_DECL)
+ 8: DECL_DECLARED_CONSTEXPR_P (in VAR_DECL, FUNCTION_DECL)
Usage of language-independent fields in a language-dependent manner:
@@ -2249,6 +2250,9 @@ struct GTY(()) lang_decl {
(DECL_CONTEXT (NODE) \
&& TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL)
+#define TYPE_FUNCTION_SCOPE_P(NODE) \
+ (TYPE_CONTEXT (NODE) && TREE_CODE (TYPE_CONTEXT (NODE)) == FUNCTION_DECL)
+
/* 1 iff VAR_DECL node NODE is a type-info decl. This flag is set for
both the primary typeinfo object and the associated NTBS name. */
#define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE))
@@ -3196,6 +3200,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define DECL_FIELD_IS_BASE(NODE) \
DECL_LANG_FLAG_6 (FIELD_DECL_CHECK (NODE))
+/* Nonzero for FIELD_DECL node means that this field is a simple (no
+ explicit initializer) lambda capture field, making it invisible to
+ name lookup in unevaluated contexts. */
+#define DECL_NORMAL_CAPTURE_P(NODE) \
+ DECL_LANG_FLAG_7 (FIELD_DECL_CHECK (NODE))
+
/* Nonzero if TYPE is an anonymous union or struct type. We have to use a
flag for this because "A union for which objects or pointers are
declared is not an anonymous union" [class.union]. */
@@ -3630,6 +3640,16 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define TARGET_EXPR_LIST_INIT_P(NODE) \
TREE_LANG_FLAG_1 (TARGET_EXPR_CHECK (NODE))
+/* True if this TARGET_EXPR expresses direct-initialization of an object
+ to be named later. */
+#define TARGET_EXPR_DIRECT_INIT_P(NODE) \
+ TREE_LANG_FLAG_2 (TARGET_EXPR_CHECK (NODE))
+
+/* True if EXPR expresses direct-initialization of a TYPE. */
+#define DIRECT_INIT_EXPR_P(TYPE,EXPR) \
+ (TREE_CODE (EXPR) == TARGET_EXPR && TREE_LANG_FLAG_2 (EXPR) \
+ && same_type_ignoring_top_level_qualifiers_p (TYPE, TREE_TYPE (EXPR)))
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types {
none_type = 0, /* Not a tag type. */
@@ -4825,7 +4845,9 @@ bool template_template_parameter_p (const_tree);
extern tree get_primary_template_innermost_parameters (const_tree);
extern tree get_template_innermost_arguments (const_tree);
extern tree get_template_argument_pack_elems (const_tree);
-extern tree get_function_template_decl (const_tree);
+extern tree get_function_template_decl (const_tree);
+extern tree resolve_nondeduced_context (tree);
+
/* in repo.c */
extern void init_repo (void);
extern int repo_emit_p (tree);
@@ -5038,7 +5060,7 @@ extern tree lambda_capture_field_type (tree);
extern tree lambda_return_type (tree);
extern tree lambda_function (tree);
extern void apply_lambda_return_type (tree, tree);
-extern tree add_capture (tree, tree, tree, bool);
+extern tree add_capture (tree, tree, tree, bool, bool);
extern tree add_default_capture (tree, tree, tree);
extern tree lambda_expr_this_capture (tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index aff002dc666..8c5b001dd15 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -956,6 +956,7 @@ convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain)
default:;
}
+ expr = resolve_nondeduced_context (expr);
{
tree probe = expr;
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 1e08465195c..d96a929ec5c 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -217,6 +217,7 @@ static void write_discriminator (const int);
static void write_local_name (tree, const tree, const tree);
static void dump_substitution_candidates (void);
static tree mangle_decl_string (const tree);
+static int local_class_index (tree);
/* Control functions. */
@@ -1204,8 +1205,7 @@ write_unqualified_name (const tree decl)
tree type = TREE_TYPE (decl);
if (TREE_CODE (decl) == TYPE_DECL
- && TYPE_ANONYMOUS_P (type)
- && !ANON_UNION_TYPE_P (type))
+ && TYPE_ANONYMOUS_P (type))
write_unnamed_type_name (type);
else if (TREE_CODE (decl) == TYPE_DECL
&& LAMBDA_TYPE_P (type))
@@ -1252,14 +1252,48 @@ write_compact_number (int num)
write_char ('_');
}
+/* Return how many unnamed types precede TYPE in its enclosing class. */
+
+static int
+nested_anon_class_index (tree type)
+{
+ int index = 0;
+ tree member = TYPE_FIELDS (TYPE_CONTEXT (type));
+ for (; member; member = TREE_CHAIN (member))
+ if (DECL_IMPLICIT_TYPEDEF_P (member))
+ {
+ tree memtype = TREE_TYPE (member);
+ if (memtype == type)
+ return index;
+ else if (TYPE_ANONYMOUS_P (memtype))
+ ++index;
+ }
+
+ gcc_unreachable ();
+}
+
+/* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
+
static void
write_unnamed_type_name (const tree type __attribute__ ((__unused__)))
{
+ int discriminator;
MANGLE_TRACE_TREE ("unnamed-type-name", type);
+ if (TYPE_FUNCTION_SCOPE_P (type))
+ discriminator = local_class_index (type);
+ else if (TYPE_CLASS_SCOPE_P (type))
+ discriminator = nested_anon_class_index (type);
+ else
+ {
+ gcc_assert (no_linkage_check (type, /*relaxed_p=*/true));
+ /* Just use the old mangling at namespace scope. */
+ write_source_name (TYPE_IDENTIFIER (type));
+ return;
+ }
+
write_string ("Ut");
- /* TODO: Implement discriminators for unnamed-types. */
- write_char ('_');
+ write_compact_number (discriminator);
}
/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
@@ -1539,6 +1573,29 @@ write_special_name_destructor (const tree dtor)
}
}
+/* Scan the vector of local classes and return how many others with the
+ same name (or same no name) and context precede ENTITY. */
+
+static int
+local_class_index (tree entity)
+{
+ int ix, discriminator = 0;
+ tree name = (TYPE_ANONYMOUS_P (entity) ? NULL_TREE
+ : TYPE_IDENTIFIER (entity));
+ tree ctx = TYPE_CONTEXT (entity);
+ for (ix = 0; ; ix++)
+ {
+ tree type = VEC_index (tree, local_classes, ix);
+ if (type == entity)
+ return discriminator;
+ if (TYPE_CONTEXT (type) == ctx
+ && (name ? TYPE_IDENTIFIER (type) == name
+ : TYPE_ANONYMOUS_P (type)))
+ ++discriminator;
+ }
+ gcc_unreachable ();
+}
+
/* Return the discriminator for ENTITY appearing inside
FUNCTION. The discriminator is the lexical ordinal of VAR among
entities with the same name in the same FUNCTION. */
@@ -1546,15 +1603,17 @@ write_special_name_destructor (const tree dtor)
static int
discriminator_for_local_entity (tree entity)
{
- /* Assume this is the only local entity with this name. */
- int discriminator = 0;
-
- if (DECL_DISCRIMINATOR_P (entity) && DECL_LANG_SPECIFIC (entity))
- discriminator = DECL_DISCRIMINATOR (entity);
+ if (DECL_DISCRIMINATOR_P (entity))
+ {
+ if (DECL_LANG_SPECIFIC (entity))
+ return DECL_DISCRIMINATOR (entity);
+ else
+ /* The first entity with a particular name doesn't get
+ DECL_LANG_SPECIFIC/DECL_DISCRIMINATOR. */
+ return 0;
+ }
else if (TREE_CODE (entity) == TYPE_DECL)
{
- int ix;
-
/* Scan the list of local classes. */
entity = TREE_TYPE (entity);
@@ -1562,18 +1621,10 @@ discriminator_for_local_entity (tree entity)
if (LAMBDA_TYPE_P (entity) || TYPE_ANONYMOUS_P (entity))
return 0;
- for (ix = 0; ; ix++)
- {
- tree type = VEC_index (tree, local_classes, ix);
- if (type == entity)
- break;
- if (TYPE_IDENTIFIER (type) == TYPE_IDENTIFIER (entity)
- && TYPE_CONTEXT (type) == TYPE_CONTEXT (entity))
- ++discriminator;
- }
+ return local_class_index (entity);
}
-
- return discriminator;
+ else
+ gcc_unreachable ();
}
/* Return the discriminator for STRING, a string literal used inside
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 459e7390805..6e31f8a058a 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3757,10 +3757,9 @@ qualify_lookup (tree val, int flags)
return true;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return false;
- /* In unevaluated context, look past capture fields. */
- /* FIXME this will cause trouble with the initializer extension. */
+ /* In unevaluated context, look past normal capture fields. */
if (cp_unevaluated_operand && TREE_CODE (val) == FIELD_DECL
- && LAMBDA_TYPE_P (DECL_CONTEXT (val)))
+ && DECL_NORMAL_CAPTURE_P (val))
return false;
return true;
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 210d3dda0e0..44dceb21f74 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6955,8 +6955,8 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
/* Lambdas that appear in variable initializer or default argument scope
get that in their mangling, so we need to record it. We might as well
use the count for function and namespace scopes as well. */
-static tree lambda_scope;
-static int lambda_count;
+static GTY(()) tree lambda_scope;
+static GTY(()) int lambda_count;
typedef struct GTY(()) tree_int
{
tree t;
@@ -7125,6 +7125,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
tree capture_id;
tree capture_init_expr;
cp_id_kind idk = CP_ID_KIND_NONE;
+ bool explicit_init_p = false;
enum capture_kind_type
{
@@ -7151,7 +7152,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
add_capture (lambda_expr,
/*id=*/get_identifier ("__this"),
/*initializer=*/finish_this_expr(),
- /*by_reference_p=*/false);
+ /*by_reference_p=*/false,
+ explicit_init_p);
continue;
}
@@ -7176,7 +7178,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/*recovering=*/true,
/*or_comma=*/true,
/*consume_paren=*/true);
- continue;
+ break;
}
/* Find the initializer for this capture. */
@@ -7190,6 +7192,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
capture_init_expr = cp_parser_assignment_expression (parser,
/*cast_p=*/true,
&idk);
+ explicit_init_p = true;
}
else
{
@@ -7231,7 +7234,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
add_capture (lambda_expr,
capture_id,
capture_init_expr,
- /*by_reference_p=*/capture_kind == BY_REFERENCE);
+ /*by_reference_p=*/capture_kind == BY_REFERENCE,
+ explicit_init_p);
}
cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6b98956d6e6..148adab2cba 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7944,6 +7944,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
}
else if (len != my_len)
{
+ if (incomplete)
+ /* We got explicit args for some packs but not others;
+ do nothing now and try again after deduction. */
+ return t;
if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
error ("mismatched argument pack lengths while expanding "
"%<%T%>",
@@ -8457,6 +8461,7 @@ tsubst_default_arguments (tree fn)
static tree
tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{
+#define RETURN(EXP) do { r = (EXP); goto out; } while(0)
location_t saved_loc;
tree r = NULL_TREE;
tree in_decl = t;
@@ -8482,7 +8487,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Template template parameter is treated here. */
tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (new_type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
r = copy_decl (t);
TREE_CHAIN (r) = NULL_TREE;
@@ -8513,12 +8518,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
complain, in_decl);
--processing_template_decl;
if (full_args == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
/* If this is a default template template argument,
tsubst might not have changed anything. */
if (full_args == tmpl_args)
- return t;
+ RETURN (t);
hash = hash_tmpl_and_args (t, full_args);
spec = retrieve_specialization (t, full_args, hash);
@@ -8546,7 +8551,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
--processing_template_decl;
if (new_type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = r;
@@ -8561,7 +8566,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
new_decl = tsubst (decl, args, complain, in_decl);
--processing_template_decl;
if (new_decl == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
DECL_TEMPLATE_RESULT (r) = new_decl;
DECL_TI_TEMPLATE (new_decl) = r;
@@ -8619,7 +8624,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
dependent_p = value_dependent_expression_p (t);
--processing_template_decl;
if (!dependent_p)
- return t;
+ RETURN (t);
/* Calculate the most general template of which R is a
specialization, and the complete set of arguments used to
@@ -8710,7 +8715,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
}
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
/* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this
@@ -8753,6 +8758,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* We'll re-clone as appropriate in instantiate_template. */
DECL_CLONED_FUNCTION (r) = NULL_TREE;
+ /* If we aren't complaining now, return on error before we register
+ the specialization so that we'll complain eventually. */
+ if ((complain & tf_error) == 0
+ && IDENTIFIER_OPNAME_P (DECL_NAME (r))
+ && !grok_op_properties (r, /*complain=*/false))
+ RETURN (error_mark_node);
+
/* Set up the DECL_TEMPLATE_INFO for R. There's no need to do
this in the special friend case mentioned above where
GEN_TMPL is NULL. */
@@ -8804,9 +8816,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (PRIMARY_TEMPLATE_P (gen_tmpl))
clone_function_decl (r, /*update_method_vec_p=*/0);
}
- else if (IDENTIFIER_OPNAME_P (DECL_NAME (r))
- && !grok_op_properties (r, (complain & tf_error) != 0))
- return error_mark_node;
+ else if ((complain & tf_error) != 0
+ && IDENTIFIER_OPNAME_P (DECL_NAME (r))
+ && !grok_op_properties (r, /*complain=*/true))
+ RETURN (error_mark_node);
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r,
@@ -8847,7 +8860,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (spec
&& TREE_CODE (spec) == PARM_DECL
&& TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
- return spec;
+ RETURN (spec);
/* Expand the TYPE_PACK_EXPANSION that provides the types for
the parameters in this function parameter pack. */
@@ -8860,8 +8873,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Zero-length parameter packs are boring. Just substitute
into the chain. */
if (len == 0)
- return tsubst (TREE_CHAIN (t), args, complain,
- TREE_CHAIN (t));
+ RETURN (tsubst (TREE_CHAIN (t), args, complain,
+ TREE_CHAIN (t)));
}
else
{
@@ -8951,7 +8964,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
r = copy_decl (t);
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
@@ -9014,7 +9027,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
we've copied the type for a typedef. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
r = TYPE_NAME (type);
break;
}
@@ -9087,7 +9100,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0;
if (type == error_mark_node)
- return error_mark_node;
+ RETURN (error_mark_node);
if (TREE_CODE (type) == FUNCTION_TYPE)
{
/* It may seem that this case cannot occur, since:
@@ -9107,7 +9120,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* R is not yet sufficiently initialized, so we
just use its name. */
DECL_NAME (r));
- return error_mark_node;
+ RETURN (error_mark_node);
}
type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
@@ -9203,7 +9216,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
default:
gcc_unreachable ();
}
+#undef RETURN
+ out:
/* Restore the file and line information. */
input_location = saved_loc;
@@ -12891,7 +12906,17 @@ maybe_adjust_types_for_deduction (unification_kind_t strict,
}
case DEDUCE_EXACT:
- /* There is nothing to do in this case. */
+ /* Core issue #873: Do the DR606 thing (see below) for these cases,
+ too, but here handle it by stripping the reference from PARM
+ rather than by adding it to ARG. */
+ if (TREE_CODE (*parm) == REFERENCE_TYPE
+ && TYPE_REF_IS_RVALUE (*parm)
+ && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM
+ && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED
+ && TREE_CODE (*arg) == REFERENCE_TYPE
+ && !TYPE_REF_IS_RVALUE (*arg))
+ *parm = TREE_TYPE (*parm);
+ /* Nothing else to do in this case. */
return 0;
default:
@@ -13303,6 +13328,105 @@ resolve_overloaded_unification (tree tparms,
return false;
}
+/* Core DR 115: In contexts where deduction is done and fails, or in
+ contexts where deduction is not done, if a template argument list is
+ specified and it, along with any default template arguments, identifies
+ a single function template specialization, then the template-id is an
+ lvalue for the function template specialization. */
+
+tree
+resolve_nondeduced_context (tree orig_expr)
+{
+ tree expr, offset, baselink;
+ bool addr;
+
+ if (!type_unknown_p (orig_expr))
+ return orig_expr;
+
+ expr = orig_expr;
+ addr = false;
+ offset = NULL_TREE;
+ baselink = NULL_TREE;
+
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ {
+ expr = TREE_OPERAND (expr, 0);
+ addr = true;
+ }
+ if (TREE_CODE (expr) == OFFSET_REF)
+ {
+ offset = expr;
+ expr = TREE_OPERAND (expr, 1);
+ }
+ if (TREE_CODE (expr) == BASELINK)
+ {
+ baselink = expr;
+ expr = BASELINK_FUNCTIONS (expr);
+ }
+
+ if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+ {
+ int good = 0;
+ tree goodfn = NULL_TREE;
+
+ /* If we got some explicit template args, we need to plug them into
+ the affected templates before we try to unify, in case the
+ explicit args will completely resolve the templates in question. */
+
+ tree expl_subargs = TREE_OPERAND (expr, 1);
+ tree arg = TREE_OPERAND (expr, 0);
+ tree badfn = NULL_TREE;
+ tree badargs = NULL_TREE;
+
+ for (; arg; arg = OVL_NEXT (arg))
+ {
+ tree fn = OVL_CURRENT (arg);
+ tree subargs, elem;
+
+ if (TREE_CODE (fn) != TEMPLATE_DECL)
+ continue;
+
+ ++processing_template_decl;
+ subargs = get_bindings (fn, DECL_TEMPLATE_RESULT (fn),
+ expl_subargs, /*check_ret=*/false);
+ if (subargs && !any_dependent_template_arguments_p (subargs))
+ {
+ elem = instantiate_template (fn, subargs, tf_none);
+ if (elem == error_mark_node)
+ {
+ badfn = fn;
+ badargs = subargs;
+ }
+ else if (elem && (!goodfn || !decls_match (goodfn, elem)))
+ {
+ goodfn = elem;
+ ++good;
+ }
+ }
+ --processing_template_decl;
+ }
+ if (good == 1)
+ {
+ expr = goodfn;
+ if (baselink)
+ expr = build_baselink (BASELINK_BINFO (baselink),
+ BASELINK_ACCESS_BINFO (baselink),
+ expr, BASELINK_OPTYPE (baselink));
+ if (offset)
+ expr = build2 (OFFSET_REF, TREE_TYPE (expr),
+ TREE_OPERAND (offset, 0), expr);
+ if (addr)
+ expr = build_address (expr);
+ return expr;
+ }
+ else if (good == 0 && badargs)
+ /* There were no good options and at least one bad one, so let the
+ user know what the problem is. */
+ instantiate_template (badfn, badargs, tf_warning_or_error);
+ }
+ return orig_expr;
+}
+
/* Subroutine of resolve_overloaded_unification; does deduction for a single
overload. Fills TARGS with any deduced arguments, or error_mark_node if
different overloads deduce different arguments for a given parm.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 8199af0e693..6cf22204a5e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4741,6 +4741,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
/* The type denoted by decltype(e) is defined as follows: */
+ expr = resolve_nondeduced_context (expr);
if (id_expression_or_member_access_p)
{
/* If e is an id-expression or a class member access (5.2.5
@@ -4766,9 +4767,13 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
/* See through BASELINK nodes to the underlying functions. */
expr = BASELINK_FUNCTIONS (expr);
+ if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
if (TREE_CODE (expr) == OVERLOAD)
{
- if (OVL_CHAIN (expr))
+ if (OVL_CHAIN (expr)
+ || TREE_CODE (OVL_FUNCTION (expr)) == TEMPLATE_DECL)
{
error ("%qE refers to a set of overloaded functions", orig_expr);
return error_mark_node;
@@ -5328,6 +5333,20 @@ build_lambda_object (tree lambda_expr)
do some magic to make it work here. */
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
val = build_array_copy (val);
+ else if (DECL_NORMAL_CAPTURE_P (field)
+ && TREE_CODE (TREE_TYPE (field)) != REFERENCE_TYPE)
+ {
+ /* "the entities that are captured by copy are used to
+ direct-initialize each corresponding non-static data
+ member of the resulting closure object."
+
+ There's normally no way to express direct-initialization
+ from an element of a CONSTRUCTOR, so we build up a special
+ TARGET_EXPR to bypass the usual copy-initialization. */
+ val = force_rvalue (val);
+ if (TREE_CODE (val) == TARGET_EXPR)
+ TARGET_EXPR_DIRECT_INIT_P (val) = true;
+ }
CONSTRUCTOR_APPEND_ELT (elts, DECL_NAME (field), val);
}
@@ -5545,7 +5564,8 @@ capture_decltype (tree decl)
and return it. */
tree
-add_capture (tree lambda, tree id, tree initializer, bool by_reference_p)
+add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
+ bool explicit_init_p)
{
tree type;
tree member;
@@ -5560,6 +5580,13 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p)
/* Make member variable. */
member = build_lang_decl (FIELD_DECL, id, type);
+ if (!explicit_init_p)
+ /* Normal captures are invisible to name lookup but uses are replaced
+ with references to the capture field; we implement this by only
+ really making them invisible in unevaluated context; see
+ qualify_lookup. For now, let's make explicitly initialized captures
+ always visible. */
+ DECL_NORMAL_CAPTURE_P (member) = true;
/* Add it to the appropriate closure class. */
finish_member_declaration (member);
@@ -5605,7 +5632,8 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
/*by_reference_p=*/
(!this_capture_p
&& (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
- == CPLD_REFERENCE)));
+ == CPLD_REFERENCE)),
+ /*explicit_init_p=*/false);
{
/* Have to get the old value of current_class_ref. */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 1cd2bf596f8..156a09e25a6 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1284,6 +1284,8 @@ build_qualified_name (tree type, tree scope, tree name, bool template_p)
return error_mark_node;
t = build2 (SCOPE_REF, type, scope, name);
QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
+ if (type)
+ t = convert_from_reference (t);
return t;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index b4d54fc4089..526e7066a60 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1613,6 +1613,7 @@ decay_conversion (tree exp)
if (type == error_mark_node)
return error_mark_node;
+ exp = resolve_nondeduced_context (exp);
if (type_unknown_p (exp))
{
cxx_incomplete_type_error (exp, TREE_TYPE (exp));
@@ -6893,6 +6894,11 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
type = complete_type (type);
+ if (DIRECT_INIT_EXPR_P (type, rhs))
+ /* Don't try to do copy-initialization if we already have
+ direct-initialization. */
+ return rhs;
+
if (MAYBE_CLASS_TYPE_P (type))
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);