aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-03-17 19:31:18 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-03-17 19:31:18 -0400
commit448545cb51bdf3d74c3d75f3b88dbf8c7a8de984 (patch)
treea0bf6190acd7e4997d3304c4bfe60c3c1b461532 /gcc/cp
parent0075846f90cb2f586f7600d1dd1d522de9dbc00f (diff)
downloadgcc-448545cb51bdf3d74c3d75f3b88dbf8c7a8de984.zip
gcc-448545cb51bdf3d74c3d75f3b88dbf8c7a8de984.tar.gz
gcc-448545cb51bdf3d74c3d75f3b88dbf8c7a8de984.tar.bz2
decl.c (grokfndecl): Set DECL_CONTEXT on parms.
cp/: * decl.c (grokfndecl): Set DECL_CONTEXT on parms. (duplicate_decls): Adjust DECL_CONTEXT of newdecl's parms. * pt.c (check_explicit_specialization): Likewise. (tsubst_copy) [PARM_DECL]: Return a dummy parm if we don't have a local specialization. * tree.c (cp_tree_equal) [PARM_DECL]: Check type and index, not name. * decl2.c (parm_index): New fn. * semantics.c (finish_decltype_type): Don't use describable_type. * mangle.c (write_expression): Likewise. Mangle ALIGNOF_EXPR. Give a sorry for unsupported codes rather than crash. Mangle conversions with other than 1 operand. New mangling for PARM_DECL. * operators.def (ALIGNOF_EXPR): Mangle as az. * include/demangle.h (enum demangle_component_type): Add DEMANGLE_COMPONENT_FUNCTION_PARAM. * libiberty/cp-demangle.c (d_make_function_param): new fn. (cplus_demangle_mangled_name): Work around abi v2 bug. (d_expr_primary): Likewise. (cplus_demangle_operators): Add alignof ops. (d_expression): Handle function parameters and conversions with other than 1 operand. (d_print_comp): Handle function parameters. Fix bug with function used in type of function. From-SVN: r144924
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c22
-rw-r--r--gcc/cp/decl2.c23
-rw-r--r--gcc/cp/mangle.c75
-rw-r--r--gcc/cp/operators.def2
-rw-r--r--gcc/cp/pt.c30
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/cp/tree.c5
9 files changed, 118 insertions, 57 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a925c5d..1f5dd9d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+2009-03-17 Jason Merrill <jason@redhat.com>
+
+ * decl.c (grokfndecl): Set DECL_CONTEXT on parms.
+ (duplicate_decls): Adjust DECL_CONTEXT of newdecl's parms.
+ * pt.c (check_explicit_specialization): Likewise.
+ (tsubst_copy) [PARM_DECL]: Return a dummy parm if we don't have a
+ local specialization.
+ * tree.c (cp_tree_equal) [PARM_DECL]: Check type and index, not name.
+ * decl2.c (parm_index): New fn.
+ * semantics.c (finish_decltype_type): Don't use describable_type.
+ * mangle.c (write_expression): Likewise. Mangle ALIGNOF_EXPR.
+ Give a sorry for unsupported codes rather than crash. Mangle
+ conversions with other than 1 operand. New mangling for PARM_DECL.
+ * operators.def (ALIGNOF_EXPR): Mangle as "az".
+
2009-03-17 Jing Yu <jingyu@google.com>
PR middle-end/39378
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0b1d7c6..1745ede 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4436,6 +4436,7 @@ extern bool decl_needed_p (tree);
extern void note_vague_linkage_fn (tree);
extern tree build_artificial_parm (tree, tree);
extern bool possibly_inlined_p (tree);
+extern int parm_index (tree);
/* in error.c */
extern void init_error (void);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 03e65d0..9a6ab02 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1684,8 +1684,14 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
= DECL_SOURCE_LOCATION (newdecl);
DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
- DECL_ARGUMENTS (old_result)
- = DECL_ARGUMENTS (new_result);
+ {
+ tree parm;
+ DECL_ARGUMENTS (old_result)
+ = DECL_ARGUMENTS (new_result);
+ for (parm = DECL_ARGUMENTS (old_result); parm;
+ parm = TREE_CHAIN (parm))
+ DECL_CONTEXT (parm) = old_result;
+ }
}
return olddecl;
@@ -1918,6 +1924,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ tree parm;
+
if (DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_TEMPLATE_INSTANTIATION (newdecl))
{
@@ -1974,6 +1982,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
/* Preserve abstractness on cloned [cd]tors. */
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
+ /* Update newdecl's parms to point at olddecl. */
+ for (parm = DECL_ARGUMENTS (newdecl); parm;
+ parm = TREE_CHAIN (parm))
+ DECL_CONTEXT (parm) = olddecl;
+
if (! types_match)
{
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
@@ -2006,7 +2019,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
}
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
- /* Don't clear out the arguments if we're redefining a function. */
+ /* Don't clear out the arguments if we're just redeclaring a
+ function. */
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
@@ -6555,6 +6569,8 @@ grokfndecl (tree ctype,
parms = parm;
}
DECL_ARGUMENTS (decl) = parms;
+ for (t = parms; t; t = TREE_CHAIN (t))
+ DECL_CONTEXT (t) = decl;
/* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index d570150..deba8b4 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3907,4 +3907,27 @@ mark_used (tree decl)
processing_template_decl = saved_processing_template_decl;
}
+/* Given function PARM_DECL PARM, return its index in the function's list
+ of parameters, beginning with 1. */
+
+int
+parm_index (tree parm)
+{
+ int index;
+ tree arg;
+
+ for (index = 1, arg = DECL_ARGUMENTS (DECL_CONTEXT (parm));
+ arg;
+ ++index, arg = TREE_CHAIN (arg))
+ {
+ if (DECL_NAME (parm) == DECL_NAME (arg))
+ break;
+ if (DECL_ARTIFICIAL (arg))
+ --index;
+ }
+
+ gcc_assert (arg);
+ return index;
+}
+
#include "gt-cp-decl2.h"
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index c72747c..eabab7f 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2143,27 +2143,6 @@ write_expression (tree expr)
{
enum tree_code 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
type. */
@@ -2210,10 +2189,12 @@ write_expression (tree expr)
write_template_arg_literal (expr);
else if (code == PARM_DECL)
{
- /* A function parameter used under decltype in a late-specified
- return type. Represented with a type placeholder. */
- write_string ("sT");
- write_type (non_reference (TREE_TYPE (expr)));
+ /* A function parameter used in a late-specified return type. */
+ int index = parm_index (expr);
+ write_string ("fp");
+ if (index > 1)
+ write_unsigned_number (index - 2);
+ write_char ('_');
}
else if (DECL_P (expr))
{
@@ -2231,6 +2212,12 @@ write_expression (tree expr)
write_string ("st");
write_type (TREE_OPERAND (expr, 0));
}
+ else if (TREE_CODE (expr) == ALIGNOF_EXPR
+ && TYPE_P (TREE_OPERAND (expr, 0)))
+ {
+ write_string ("at");
+ write_type (TREE_OPERAND (expr, 0));
+ }
else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
{
tree scope = TREE_OPERAND (expr, 0);
@@ -2298,9 +2285,16 @@ write_expression (tree expr)
write_template_args (template_args);
}
}
+ else if (TREE_CODE (expr) == INDIRECT_REF
+ && TREE_TYPE (TREE_OPERAND (expr, 0))
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
+ {
+ write_expression (TREE_OPERAND (expr, 0));
+ }
else
{
int i;
+ const char *name;
/* When we bind a variable or function to a non-type template
argument with reference type, we create an ADDR_EXPR to show
@@ -2338,7 +2332,14 @@ write_expression (tree expr)
}
/* If it wasn't any of those, recursively expand the expression. */
- write_string (operator_name_info[(int) code].mangled_name);
+ name = operator_name_info[(int) code].mangled_name;
+ if (name == NULL)
+ {
+ sorry ("mangling %C", code);
+ return;
+ }
+ else
+ write_string (name);
switch (code)
{
@@ -2351,23 +2352,29 @@ write_expression (tree expr)
case CAST_EXPR:
write_type (TREE_TYPE (expr));
- /* There is no way to mangle a zero-operand cast like
- "T()". */
- if (!TREE_OPERAND (expr, 0))
- sorry ("zero-operand casts cannot be mangled due to a defect "
- "in the C++ ABI");
- else if (list_length (TREE_OPERAND (expr, 0)) > 1)
- sorry ("mangling function-style cast with more than one argument");
- else
+ if (list_length (TREE_OPERAND (expr, 0)) == 1)
write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
+ else
+ {
+ tree args = TREE_OPERAND (expr, 0);
+ write_char ('_');
+ for (; args; args = TREE_CHAIN (args))
+ write_expression (TREE_VALUE (args));
+ write_char ('E');
+ }
break;
+ /* FIXME these should have a distinct mangling. */
case STATIC_CAST_EXPR:
case CONST_CAST_EXPR:
write_type (TREE_TYPE (expr));
write_expression (TREE_OPERAND (expr, 0));
break;
+ case NEW_EXPR:
+ sorry ("mangling new-expression");
+ break;
+
/* Handle pointers-to-members specially. */
case SCOPE_REF:
write_type (TREE_OPERAND (expr, 0));
diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def
index 698f0de4..20d811b 100644
--- a/gcc/cp/operators.def
+++ b/gcc/cp/operators.def
@@ -94,7 +94,7 @@ DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", 1)
DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", 1)
DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", 1)
/* These are extensions. */
-DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "v17alignof", 1)
+DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", 1)
DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", 1)
DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8ae4ed5..62a7b88 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2217,17 +2217,21 @@ check_explicit_specialization (tree declarator,
the specialization of it. */
if (tsk == tsk_template)
{
+ tree result = DECL_TEMPLATE_RESULT (tmpl);
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
- DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
+ DECL_INITIAL (result) = NULL_TREE;
if (have_def)
{
+ tree parm;
DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
- DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl))
+ DECL_SOURCE_LOCATION (result)
= DECL_SOURCE_LOCATION (decl);
/* We want to use the argument list specified in the
definition, not in the original declaration. */
- DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (tmpl))
- = DECL_ARGUMENTS (decl);
+ DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl);
+ for (parm = DECL_ARGUMENTS (result); parm;
+ parm = TREE_CHAIN (parm))
+ DECL_CONTEXT (parm) = result;
}
return tmpl;
}
@@ -9898,16 +9902,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (r == NULL)
{
/* This can happen for a parameter name used later in a function
- declaration (such as in a late-specified return type).
- Replace it with an arbitrary expression with the same type
- (*(T*)0). This should only occur in an unevaluated context
- (i.e. decltype). */
- gcc_assert (skip_evaluation);
- r = non_reference (TREE_TYPE (t));
- r = tsubst (r, args, complain, in_decl);
- r = build_pointer_type (r);
- r = build_c_cast (r, null_node);
- return cp_build_indirect_ref (r, NULL, tf_warning_or_error);
+ declaration (such as in a late-specified return type). Just
+ make a dummy decl, since it's only used for its type. */
+ gcc_assert (skip_evaluation);
+ r = tsubst_decl (t, args, complain);
+ /* Give it the template pattern as its context; its true context
+ hasn't been instantiated yet and this is good enough for
+ mangling. */
+ DECL_CONTEXT (r) = DECL_CONTEXT (t);
}
if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 82a6797..c728970 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4585,8 +4585,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
break;
}
}
- else
- type = describable_type (expr);
if (type && !type_uses_auto (type))
return type;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 82f3b89..2287f11 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1881,9 +1881,8 @@ cp_tree_equal (tree t1, tree t2)
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))
+ if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+ && parm_index (t1) == parm_index (t2))
return true;
else
return false;