summaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2008-08-30 05:14:54 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2008-08-30 05:14:54 +0000
commit46f4817eeebea5a884a22996e63078ea6f5f1a6b (patch)
treee0bd80b1274106f983a05d33d9c48ec65a2d8085 /gcc/cp/pt.c
parentf41b76e3fa6ca22b7b8266567dbf81460b4158db (diff)
downloadgcc-46f4817eeebea5a884a22996e63078ea6f5f1a6b.tar.gz
Implement C++0x 'auto' semantics.
* decl.c (start_decl_1): Don't complain about auto being incomplete. (cp_finish_decl): Deduce auto. * init.c (build_new): Handle 'new auto'. * typeck2.c (cxx_incomplete_type_diagnostic): Give a different message for auto than for normal template type parms. * pt.c (type_dependent_expression_p): Handle { }. (make_auto): New function. (listify_autos): New function. (do_auto_deduction): New function. (is_auto): New function. (type_uses_auto): New function. * cp-tree.h: Declare them. * parser.c (cp_parser_decl_specifier_seq): In C++0x mode, don't treat auto as a declspec. (cp_parser_simple_type_specifier): It's a type-specifier. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139798 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d5443e65505..3b345f1f4a3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16187,6 +16187,19 @@ type_dependent_expression_p (tree expression)
if (TREE_CODE (expression) == STMT_EXPR)
expression = stmt_expr_value_expr (expression);
+ if (BRACE_ENCLOSED_INITIALIZER_P (expression))
+ {
+ tree elt;
+ unsigned i;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expression), i, elt)
+ {
+ if (type_dependent_expression_p (elt))
+ return true;
+ }
+ return false;
+ }
+
if (TREE_TYPE (expression) == unknown_type_node)
{
if (TREE_CODE (expression) == ADDR_EXPR)
@@ -16673,4 +16686,124 @@ build_non_dependent_args (tree args)
return nreverse (new_args);
}
+/* Returns a type which represents 'auto'. We use a TEMPLATE_TYPE_PARM
+ with a level one deeper than the actual template parms. */
+
+tree
+make_auto (void)
+{
+ tree au;
+
+ /* ??? Is it worth caching this for multiple autos at the same level? */
+ au = cxx_make_type (TEMPLATE_TYPE_PARM);
+ TYPE_NAME (au) = build_decl (TYPE_DECL, get_identifier ("auto"), au);
+ TYPE_STUB_DECL (au) = TYPE_NAME (au);
+ TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
+ (0, processing_template_decl + 1, processing_template_decl + 1,
+ TYPE_NAME (au), NULL_TREE);
+ TYPE_CANONICAL (au) = canonical_type_parameter (au);
+ DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
+ SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
+
+ return au;
+}
+
+/* Replace auto in TYPE with std::initializer_list<auto>. */
+
+static tree
+listify_autos (tree type, tree auto_node)
+{
+ tree std_init_list = namespace_binding
+ (get_identifier ("initializer_list"), std_node);
+ tree argvec;
+ tree init_auto;
+ if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
+ {
+ error ("deducing auto from brace-enclosed initializer list requires "
+ "#include <initializer_list>");
+ return error_mark_node;
+ }
+ argvec = make_tree_vec (1);
+ TREE_VEC_ELT (argvec, 0) = auto_node;
+ init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE,
+ NULL_TREE, 0, tf_warning_or_error);
+
+ TREE_VEC_ELT (argvec, 0) = init_auto;
+ if (processing_template_decl)
+ argvec = add_to_template_args (current_template_args (), argvec);
+ return tsubst (type, argvec, tf_warning_or_error, NULL_TREE);
+}
+
+/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
+ from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE. */
+
+tree
+do_auto_deduction (tree type, tree init, tree auto_node)
+{
+ tree parms, args, tparms, targs;
+ int val;
+
+ /* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
+ with either a new invented type template parameter U or, if the
+ initializer is a braced-init-list (8.5.4), with
+ std::initializer_list<U>. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ type = listify_autos (type, auto_node);
+
+ parms = build_tree_list (NULL_TREE, type);
+ args = build_tree_list (NULL_TREE, init);
+ tparms = make_tree_vec (1);
+ targs = make_tree_vec (1);
+ TREE_VEC_ELT (tparms, 0)
+ = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
+ val = type_unification_real (tparms, targs, parms, args, 0,
+ DEDUCE_CALL, LOOKUP_NORMAL);
+ if (val > 0)
+ {
+ error ("unable to deduce %qT from %qE", type, init);
+ return error_mark_node;
+ }
+
+ if (processing_template_decl)
+ targs = add_to_template_args (current_template_args (), targs);
+ return tsubst (type, targs, tf_warning_or_error, NULL_TREE);
+}
+
+/* Returns true iff TYPE is a TEMPLATE_TYPE_PARM representing 'auto'. */
+
+bool
+is_auto (const_tree type)
+{
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+ && TYPE_IDENTIFIER (type) == get_identifier ("auto"))
+ return true;
+ else
+ 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. */
+
+tree
+type_uses_auto (tree type)
+{
+ 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;
+}
+
#include "gt-cp-pt.h"