aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/common.opt6
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/mangle.c56
-rw-r--r--gcc/cp/name-lookup.c16
-rw-r--r--gcc/cp/name-lookup.h1
-rw-r--r--gcc/cp/parser.c1
-rw-r--r--gcc/cp/semantics.c22
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle39.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle45.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing1.C5
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-12.C2
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-9.C2
15 files changed, 148 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6fb3936..c064b51 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/common.opt b/gcc/common.opt
index f95805c..2717b11 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -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=
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 195b319..8637ee0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 238d0cf..ee72322 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 4d2ace6..dca8b60 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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))
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index e2e5450..4117202 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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;
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index f81a565..bfcac69 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5b08389..1e8f03b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 4af007d..8a7dd7d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b2abbe7..dc92141 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/abi/mangle39.C b/gcc/testsuite/g++.dg/abi/mangle39.C
index 30a08b0..272385b 100644
--- a/gcc/testsuite/g++.dg/abi/mangle39.C
+++ b/gcc/testsuite/g++.dg/abi/mangle39.C
@@ -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)
diff --git a/gcc/testsuite/g++.dg/abi/mangle45.C b/gcc/testsuite/g++.dg/abi/mangle45.C
new file mode 100644
index 0000000..8e20831
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle45.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing1.C b/gcc/testsuite/g++.dg/cpp0x/trailing1.C
index 11e73d2..fcf65e3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing1.C
@@ -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);
}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-12.C b/gcc/testsuite/g++.dg/template/canon-type-12.C
index 694cc5e..08c86f0 100644
--- a/gcc/testsuite/g++.dg/template/canon-type-12.C
+++ b/gcc/testsuite/g++.dg/template/canon-type-12.C
@@ -9,7 +9,7 @@ struct S
template<class T, T t>
void
-S<T, t>::foo(T)
+S<T, t>::foo(decltype(t))
{
}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
index 8d1aa29..4fcd524 100644
--- a/gcc/testsuite/g++.dg/template/canon-type-9.C
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -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;