diff options
author | Jason Merrill <jason@redhat.com> | 2008-12-17 14:08:14 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2008-12-17 14:08:14 -0500 |
commit | a77f94e24084115b80f1eb05836d7538b3500c36 (patch) | |
tree | 2fc764010bfc532f00bb2946a496b9d1884f5ed0 /gcc/cp | |
parent | 3aea2d1ce29ba8a41d54857de2c5bcf1a4dce254 (diff) | |
download | gcc-a77f94e24084115b80f1eb05836d7538b3500c36.zip gcc-a77f94e24084115b80f1eb05836d7538b3500c36.tar.gz gcc-a77f94e24084115b80f1eb05836d7538b3500c36.tar.bz2 |
semantics.c (describable_type): New function.
gcc/cp:
* semantics.c (describable_type): New function.
(finish_decltype_type): Use it for dependent exprs.
* cp-tree.h: Declare it.
* mangle.c (write_type) [DECLTYPE_TYPE]: Set skip_evaluation.
(write_expression): If skip_evaluation, use type stubs.
* tree.c (cp_tree_equal): Handle PARM_DECLs from different
declarations of a function.
* init.c (build_new): Do auto deduction if type is describable.
* decl.c (cp_finish_decl): Likewise.
* parser.c (cp_parser_omp_for_loop): Likewise.
gcc/testsuite:
* g++.dg/cpp0x/auto6.C: Test more stuff.
* g++.dg/cpp0x/auto12.C: New test.
libiberty:
* cp-demangle.c (d_expression): Handle rvalue stubs too.
[DEMANGLE_COMPONENT_CAST]: Update mangling.
(d_print_comp): Avoid extra ", " with empty template argument packs.
Remove handling for obsolete T() mangling.
From-SVN: r142799
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 2 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 25 | ||||
-rw-r--r-- | gcc/cp/parser.c | 2 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 90 | ||||
-rw-r--r-- | gcc/cp/tree.c | 11 |
8 files changed, 140 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4b33059..2c681c0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2008-12-17 Jason Merrill <jason@redhat.com> + + * semantics.c (describable_type): New function. + (finish_decltype_type): Use it for dependent exprs. + * cp-tree.h: Declare it. + * mangle.c (write_type) [DECLTYPE_TYPE]: Set skip_evaluation. + (write_expression): If skip_evaluation, use type stubs. + * tree.c (cp_tree_equal): Handle PARM_DECLs from different + declarations of a function. + * init.c (build_new): Do auto deduction if type is describable. + * decl.c (cp_finish_decl): Likewise. + * parser.c (cp_parser_omp_for_loop): Likewise. + 2008-12-10 Jason Merrill <jason@redhat.com> PR c++/35319 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bf22eb4..ff43bc7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4814,6 +4814,7 @@ extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool); extern tree baselink_for_fns (tree); extern void finish_static_assert (tree, tree, location_t, bool); +extern tree describable_type (tree); extern tree finish_decltype_type (tree, bool); extern tree finish_trait_expr (enum cp_trait_kind, tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e786b39..efc7e2e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5496,7 +5496,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, TREE_TYPE (decl) = error_mark_node; return; } - else if (!type_dependent_expression_p (init)) + else if (describable_type (init)) { type = TREE_TYPE (decl) = do_auto_deduction (type, init, auto_node); if (type == error_mark_node) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index d71b68b..abcf858 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2329,7 +2329,7 @@ build_new (tree placement, tree type, tree nelts, tree init, orig_init = init; if (nelts == NULL_TREE && init != void_zero_node && list_length (init) == 1 - && !any_type_dependent_arguments_p (init)) + && describable_type (TREE_VALUE (init))) { tree auto_node = type_uses_auto (type); if (auto_node) diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 36b984e..1ec27c1 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1680,7 +1680,9 @@ write_type (tree type) write_char ('t'); else write_char ('T'); + ++skip_evaluation; write_expression (DECLTYPE_TYPE_EXPR (type)); + --skip_evaluation; write_char ('E'); break; @@ -2139,9 +2141,28 @@ write_member_name (tree member) static void write_expression (tree expr) { - enum tree_code code; + enum tree_code code = TREE_CODE (expr); - code = TREE_CODE (expr); + /* Inside decltype we can simplify some expressions, since we're only + interested in the type. */ + if (skip_evaluation) + { + tree type = describable_type (expr); + if (type == NULL_TREE) + ; + else if (TREE_CODE (type) == REFERENCE_TYPE) + { + write_string ("sT"); + write_type (TREE_TYPE (type)); + return; + } + else + { + write_string ("sR"); + write_type (type); + return; + } + } /* Skip NOP_EXPRs. They can occur when (say) a pointer argument is converted (via qualification conversions) to another diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 45abd24..79be488 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -21159,7 +21159,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses) &is_direct_init, &is_non_constant_init); - if (auto_node && !type_dependent_expression_p (init)) + if (auto_node && describable_type (init)) { TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), init, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e0ae6ff..d5efb83 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4438,12 +4438,79 @@ finish_static_assert (tree condition, tree message, location_t location, } } +/* Returns decltype((EXPR)) for cases where we can drop the decltype and + just return the type even though EXPR is a type-dependent expression. + The ABI specifies which cases this applies to, which is a subset of the + possible cases. */ + +tree +describable_type (tree expr) +{ + tree type = NULL_TREE; + + /* processing_template_decl isn't set when we're called from the mangling + code, so bump it now. */ + ++processing_template_decl; + if (! type_dependent_expression_p (expr) + && ! type_unknown_p (expr)) + { + type = TREE_TYPE (expr); + if (real_lvalue_p (expr)) + type = build_reference_type (type); + } + --processing_template_decl; + + if (type) + return type; + + switch (TREE_CODE (expr)) + { + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + case FUNCTION_DECL: + /* Named rvalue reference becomes lvalue. */ + type = build_reference_type (non_reference (TREE_TYPE (expr))); + break; + + case NEW_EXPR: + case CONST_DECL: + case TEMPLATE_PARM_INDEX: + case CAST_EXPR: + case STATIC_CAST_EXPR: + case REINTERPRET_CAST_EXPR: + case CONST_CAST_EXPR: + case DYNAMIC_CAST_EXPR: + type = TREE_TYPE (expr); + break; + + case INDIRECT_REF: + { + tree ptrtype = describable_type (TREE_OPERAND (expr, 0)); + if (ptrtype && POINTER_TYPE_P (ptrtype)) + type = build_reference_type (TREE_TYPE (ptrtype)); + } + break; + + default: + if (TREE_CODE_CLASS (TREE_CODE (expr)) == tcc_constant) + type = TREE_TYPE (expr); + break; + } + + if (type && type_uses_auto (type)) + return NULL_TREE; + else + return type; +} + /* Implements the C++0x decltype keyword. Returns the type of EXPR, suitable for use as a type-specifier. ID_EXPRESSION_OR_MEMBER_ACCESS_P is true when EXPR was parsed as an id-expression or a class member access, FALSE when it was parsed as a full expression. */ + tree finish_decltype_type (tree expr, bool id_expression_or_member_access_p) { @@ -4464,6 +4531,29 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) if (type_dependent_expression_p (expr)) { + if (id_expression_or_member_access_p) + { + switch (TREE_CODE (expr)) + { + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + case FUNCTION_DECL: + case CONST_DECL: + case TEMPLATE_PARM_INDEX: + type = TREE_TYPE (expr); + break; + + default: + break; + } + } + else + type = describable_type (expr); + + if (type && !type_uses_auto (type)) + return type; + type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = expr; DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2ae6543..1f2c631 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1857,8 +1857,17 @@ cp_tree_equal (tree t1, tree t2) return false; return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); - case VAR_DECL: case PARM_DECL: + /* For comparing uses of parameters in late-specified return types + with an out-of-class definition of the function. */ + if ((!DECL_CONTEXT (t1) || !DECL_CONTEXT (t2)) + && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) + && DECL_NAME (t1) == DECL_NAME (t2)) + return true; + else + return false; + + case VAR_DECL: case CONST_DECL: case FUNCTION_DECL: case TEMPLATE_DECL: |