cp-tree.h (DECL_PARM_LEVEL): New.

* cp-tree.h (DECL_PARM_LEVEL): New.
	(struct lang_decl_parm): Add level field.
	* name-lookup.c (function_parm_depth): New fn.
	* name-lookup.h: Declare it.
	* parser.c (cp_parser_parameter_declaration_list): Use it.
	* mangle.c (struct globals): Add parm_depth field.
	(write_bare_function_type): Adjust it.
	(write_expression): Include the level delta in PARM_DECL mangling
	for abi >= 6.

	* semantics.c (finish_decltype_type): Remove shortcut for decltype
	of id-expression.
	* mangle.c (write_type) [DECLTYPE_TYPE]: Strip it here for abi < 6.

From-SVN: r170459
This commit is contained in:
Jason Merrill 2011-02-23 23:56:26 -05:00 committed by Jason Merrill
parent 5a30f819c7
commit 67e18edbc6
15 changed files with 148 additions and 28 deletions

View file

@ -1,3 +1,7 @@
2011-02-23 Jason Merrill <jason@redhat.com>
* common.opt (fabi-version): Document v5 and v6.
2011-02-23 Richard Guenther <rguenther@suse.de>
PR tree-optimization/47849

View file

@ -741,6 +741,12 @@ Driver Undocumented
; 4: The version of the ABI that introduces unambiguous mangling of
; vector types.
;
; 5: The version of the ABI that ignores attribute const/noreturn
; in function pointer mangling.
;
; 6: The version of the ABI that corrects mangling of decltype and
; function parameters used in other parameters and the return type.
;
; Additional positive integers will be assigned as new versions of
; the ABI become the default version of the ABI.
fabi-version=

View file

@ -1,3 +1,19 @@
2011-02-23 Jason Merrill <jason@redhat.com>
* cp-tree.h (DECL_PARM_LEVEL): New.
(struct lang_decl_parm): Add level field.
* name-lookup.c (function_parm_depth): New fn.
* name-lookup.h: Declare it.
* parser.c (cp_parser_parameter_declaration_list): Use it.
* mangle.c (struct globals): Add parm_depth field.
(write_bare_function_type): Adjust it.
(write_expression): Include the level delta in PARM_DECL mangling
for abi >= 6.
* semantics.c (finish_decltype_type): Remove shortcut for decltype
of id-expression.
* mangle.c (write_type) [DECLTYPE_TYPE]: Strip it here for abi < 6.
2011-02-23 Nathan Froyd <froydnj@codesourcery.com>
PR c++/46868

View file

@ -1914,6 +1914,7 @@ struct GTY(()) lang_decl_ns {
struct GTY(()) lang_decl_parm {
struct lang_decl_base base;
int level;
int index;
};
@ -2108,6 +2109,13 @@ struct GTY((variable_size)) lang_decl {
#define DECL_PARM_INDEX(NODE) \
(LANG_DECL_PARM_CHECK (NODE)->index)
/* The level of a user-declared parameter in its function, starting at 1.
A parameter of the function will have level 1; a parameter of the first
nested function declarator (i.e. t in void f (void (*p)(T t))) will have
level 2. */
#define DECL_PARM_LEVEL(NODE) \
(LANG_DECL_PARM_CHECK (NODE)->level)
/* Nonzero if the VTT parm has been added to NODE. */
#define DECL_HAS_VTT_PARM_P(NODE) \
(LANG_DECL_FN_CHECK (NODE)->has_vtt_parm_p)

View file

@ -96,6 +96,9 @@ typedef struct GTY(()) globals {
/* The entity that is being mangled. */
tree GTY ((skip)) entity;
/* How many parameter scopes we are inside. */
int parm_depth;
/* True if the mangling will be different in a future version of the
ABI. */
bool need_abi_warning;
@ -1931,6 +1934,35 @@ write_type (tree type)
gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
&& !DECLTYPE_FOR_LAMBDA_RETURN (type));
/* In ABI <6, we stripped decltype of a plain decl. */
if (!abi_version_at_least (6)
&& DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
{
tree expr = DECLTYPE_TYPE_EXPR (type);
tree etype = NULL_TREE;
switch (TREE_CODE (expr))
{
case VAR_DECL:
case PARM_DECL:
case RESULT_DECL:
case FUNCTION_DECL:
case CONST_DECL:
case TEMPLATE_PARM_INDEX:
etype = TREE_TYPE (expr);
break;
default:
break;
}
if (etype && !type_uses_auto (etype))
{
G.need_abi_warning = 1;
write_type (etype);
return;
}
}
write_char ('D');
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
write_char ('t');
@ -2270,9 +2302,11 @@ write_bare_function_type (const tree type, const int include_return_type_p,
write_type (TREE_TYPE (type));
/* Now mangle the types of the arguments. */
++G.parm_depth;
write_method_parms (TYPE_ARG_TYPES (type),
TREE_CODE (type) == METHOD_TYPE,
decl);
--G.parm_depth;
}
/* Write the mangled representation of a method parameter list of
@ -2458,8 +2492,28 @@ write_expression (tree expr)
{
/* A function parameter used in a late-specified return type. */
int index = DECL_PARM_INDEX (expr);
int level = DECL_PARM_LEVEL (expr);
int delta = G.parm_depth - level + 1;
gcc_assert (index >= 1);
write_string ("fp");
write_char ('f');
if (delta != 0)
{
if (abi_version_at_least (6))
{
/* Let L be the number of function prototype scopes from the
innermost one (in which the parameter reference occurs) up
to (and including) the one containing the declaration of
the referenced parameter. If the parameter declaration
clause of the innermost function prototype scope has been
completely seen, it is not counted (in that case -- which
is perhaps the most common -- L can be zero). */
write_char ('L');
write_unsigned_number (delta - 1);
}
else
G.need_abi_warning = true;
}
write_char ('p');
write_compact_number (index - 1);
}
else if (DECL_P (expr))

View file

@ -1635,6 +1635,22 @@ getdecls (void)
return current_binding_level->names;
}
/* Return how many function prototypes we are currently nested inside. */
int
function_parm_depth (void)
{
int level = 0;
struct cp_binding_level *b;
for (b = current_binding_level;
b->kind == sk_function_parms;
b = b->level_chain)
++level;
return level;
}
/* For debugging. */
static int no_print_functions = 0;
static int no_print_builtins = 0;

View file

@ -333,6 +333,7 @@ extern bool pushdecl_class_level (tree);
extern tree pushdecl_namespace_level (tree, bool);
extern bool push_class_level_binding (tree, tree);
extern tree getdecls (void);
extern int function_parm_depth (void);
extern tree cp_namespace_decls (tree);
extern void set_decl_namespace (tree, tree, bool);
extern void push_decl_namespace (tree);

View file

@ -15942,6 +15942,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
{
retrofit_lang_decl (decl);
DECL_PARM_INDEX (decl) = ++index;
DECL_PARM_LEVEL (decl) = function_parm_depth ();
}
/* Add the new parameter to the list. */

View file

@ -4772,6 +4772,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
return error_mark_node;
}
/* FIXME instantiation-dependent */
if (type_dependent_expression_p (expr)
/* In a template, a COMPONENT_REF has an IDENTIFIER_NODE for op1 even
if it isn't dependent, so that we can check access control at
@ -4780,27 +4781,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
&& processing_template_decl
&& TREE_CODE (expr) == COMPONENT_REF))
{
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;
}
}
if (type && !type_uses_auto (type))
return type;
treat_as_dependent:
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;

View file

@ -1,3 +1,13 @@
2011-02-23 Jason Merrill <jason@redhat.com>
* g++.dg/abi/mangle39.C: Adjust parm mangling.
* g++.dg/abi/mangle45.C: New.
* g++.dg/cpp0x/trailing1.C: Mangle decltype.
* g++.dg/template/canon-type-9.C: Match use of decltype
between declaration and definition.
* g++.dg/template/canon-type-12.C: Likewise.
2011-02-23 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/40850

View file

@ -1,7 +1,7 @@
// PR c++/42338
// { dg-options "-std=c++0x" }
// { dg-final { scan-assembler "_Z1fIPiEDTcmppfp_Li0EET_" } }
// { dg-final { scan-assembler "_Z1gIiEvRK1AIT_EDTixfp_Li0EE" } }
// { dg-final { scan-assembler "_Z1gIiEvRK1AIT_EDTixfL0p_Li0EE" } }
template<typename T>
auto f(T t) -> decltype(++t, 0)

View file

@ -0,0 +1,25 @@
// Testcase for mangling of parameters used other than in a trailing return type
// { dg-options -std=c++0x }
template<class T> void f(T p, decltype(p)) { } // L = 1
template<class T> void g(T p, decltype(p) (*)()) { } // L = 1
// G++ incorrectly rejects these currently.
// template<class T> void h(T p, auto (*)()->decltype(p)); // L = 1
// template<class T> void i(T p, auto (*)(T q)->decltype(q)); // L = 0
// template<class T> void j(T p, auto (*)(decltype(p))->T); // L = 2
template<class T> void k(T p, int (*(*)(T* p))[sizeof(p)]) {} // L = 1
int garg();
int (*karg (int*))[sizeof(int)];
int main()
{
// { dg-final { scan-assembler "_Z1fIiEvT_DtfL0p_E" } }
f (1,0);
// { dg-final { scan-assembler "_Z1gIiEvT_PFDtfL0p_EvE" } }
g (1,garg);
// h (1,0);
// i (1,0);
// j (1,0);
// { dg-final { scan-assembler "_Z1kIiEvT_PFPAszfL0p__iPS0_E" } }
k (1,karg);
}

View file

@ -78,7 +78,6 @@ auto k(T t, U u, V v) -> decltype (t.U::template B<V>::MEM)
return t.U::template B<V>::MEM;
}
// For these two examples we can elide the 'decltype' and just mangle the type.
template <class T>
auto l(T t) -> decltype (t)
{
@ -111,8 +110,8 @@ int main()
h(a,1.0);
// { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtfp_srNT0_1BIT1_EE3MEMET_S4_S6_" } }
k( C(), A<int>(), D() );
// { dg-final { scan-assembler "_Z1lIiET_S0_" } }
// { dg-final { scan-assembler "_Z1lIiEDtfp_ET_" } }
l(1);
// { dg-final { scan-assembler "_Z1mIiLi1EET_S0_" } }
// { dg-final { scan-assembler "_Z1mIiLi1EEDtT0_ET_" } }
m<int,1>(1);
}

View file

@ -9,7 +9,7 @@ struct S
template<class T, T t>
void
S<T, t>::foo(T)
S<T, t>::foo(decltype(t))
{
}

View file

@ -11,7 +11,7 @@ struct S
};
template<class T, T *u>
T* S<T, u>::foo(T)
decltype(u) S<T, u>::foo(T)
{
T t;
return t;