In gcc/cp/: 2010-10-23 Nicola Pero <nicola.pero@meta-innovation.com>

In gcc/cp/:
2010-10-23  Nicola Pero  <nicola.pero@meta-innovation.com>

        * tree.c (cxx_printable_name_internal): In Objective-C++, call
        objc_maybe_printable_name.

In gcc/objc/:
2010-10-23  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc-act.c (OBJC_GEN_METHOD_LABEL): Updated comments.
        (objc_demangle): Return NULL if demangling can not be done because
        the string to demangle is not an Objective-C mangled method name.
        Be smarter in demangling method names so that at least for methods
        with no arguments we are able to almost always demangle '_' correctly.
        Updated comments.
        (objc_maybe_printable_name): New.
        (objc_printable_name): Call objc_maybe_printable_name.  If it
        returns NULL, call cxx_printable_name in Objective-C++.

In gcc/testsuite/:
2010-10-23  Nicola Pero  <nicola.pero@meta-innovation.com>

        * objc.dg/demangle-1.m: New test.
        * obj-c++.dg/demangle-1.mm: New test.
        * obj-c++.dg/demangle-2.mm: New test.
        * obj-c++.dg/demangle-3.mm: New test.

In gcc/c-family/:
2010-10-23  Nicola Pero  <nicola.pero@meta-innovation.com>

        * c-common.h (objc_maybe_printable_name): New.
        * stub-objc.c (objc_maybe_printable_name): New.

From-SVN: r165887
This commit is contained in:
Nicola Pero 2010-10-23 18:40:39 +00:00 committed by Nicola Pero
parent 487a9a3ef8
commit b8a1880581
12 changed files with 358 additions and 13 deletions

View File

@ -1,3 +1,8 @@
2010-10-23 Nicola Pero <nicola.pero@meta-innovation.com>
* c-common.h (objc_maybe_printable_name): New.
* stub-objc.c (objc_maybe_printable_name): New.
2010-10-22 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
Andrew Pinski <pinskia@gmail.com>

View File

@ -1048,6 +1048,7 @@ extern tree objc_build_getter_call (tree, tree);
extern tree objc_build_setter_call (tree, tree);
extern void objc_add_synthesize_declaration (location_t, tree);
extern void objc_add_dynamic_declaration (location_t, tree);
extern const char * objc_maybe_printable_name (tree, int);
/* The following are provided by the C and C++ front-ends, and called by
ObjC/ObjC++. */

View File

@ -359,6 +359,13 @@ objc_add_dynamic_declaration (location_t ARG_UNUSED (start_locus),
{
}
const char *
objc_maybe_printable_name (tree ARG_UNUSED (decl),
int ARG_UNUSED (v))
{
return NULL;
}
tree
objc_build_throw_stmt (location_t ARG_UNUSED (loc), tree ARG_UNUSED (expr))
{

View File

@ -1,3 +1,8 @@
2010-10-23 Nicola Pero <nicola.pero@meta-innovation.com>
* tree.c (cxx_printable_name_internal): In Objective-C++, call
objc_maybe_printable_name.
2010-10-22 Jason Merrill <jason@redhat.com>
PR c++/46129

View File

@ -1409,6 +1409,15 @@ cxx_printable_name_internal (tree decl, int v, bool translate)
static int ring_counter;
int i;
/* If doing Objective-C++, give Objective-C a chance to demangle
Objective-C method names. */
if (c_dialect_objc ())
{
const char *demangled = objc_maybe_printable_name (decl, v);
if (demangled)
return demangled;
}
/* Only cache functions. */
if (v < 2
|| TREE_CODE (decl) != FUNCTION_DECL

View File

@ -1,3 +1,15 @@
2010-10-23 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (OBJC_GEN_METHOD_LABEL): Updated comments.
(objc_demangle): Return NULL if demangling can not be done because
the string to demangle is not an Objective-C mangled method name.
Be smarter in demangling method names so that at least for methods
with no arguments we are able to almost always demangle '_' correctly.
Updated comments.
(objc_maybe_printable_name): New.
(objc_printable_name): Call objc_maybe_printable_name. If it
returns NULL, call cxx_printable_name in Objective-C++.
2010-10-21 Iain Sandoe <iains@gcc.gnu.org>
Based on the CFString implementation in FSF apple/trunk branch.

View File

@ -75,9 +75,14 @@ bool in_late_binary_op = false;
#endif /* OBJCPLUS */
/* This is the default way of generating a method name. */
/* I am not sure it is really correct.
Perhaps there's a danger that it will make name conflicts
if method names contain underscores. -- rms. */
/* This has the problem that "test_method:argument:" and
"test:method_argument:" will generate the same name
("_i_Test__test_method_argument_" for an instance method of the
class "Test"), so you can't have them both in the same class!
Moreover, the demangling (going from
"_i_Test__test_method_argument" back to the original name) is
undefined because there are two correct ways of demangling the
name. */
#ifndef OBJC_GEN_METHOD_LABEL
#define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \
do { \
@ -10615,7 +10620,64 @@ dump_interface (FILE *fp, tree chain)
fprintf (fp, "@end\n");
}
/* Demangle function for Objective-C */
#if 0
/* Produce the pretty printing for an Objective-C method. This is
currently unused, but could be handy while reorganizing the pretty
printing to be more robust. */
static const char *
objc_pretty_print_method (bool is_class_method,
const char *class_name,
const char *category_name,
const char *selector)
{
if (category_name)
{
char *result = XNEWVEC (char, strlen (class_name) + strlen (category_name)
+ strlen (selector) + 7);
if (is_class_method)
sprintf (result, "+[%s(%s) %s]", class_name, category_name, selector);
else
sprintf (result, "-[%s(%s) %s]", class_name, category_name, selector);
return result;
}
else
{
char *result = XNEWVEC (char, strlen (class_name)
+ strlen (selector) + 5);
if (is_class_method)
sprintf (result, "+[%s %s]", class_name, selector);
else
sprintf (result, "-[%s %s]", class_name, selector);
return result;
}
}
#endif
/* Demangle function for Objective-C. Attempt to demangle the
function name associated with a method (eg, going from
"_i_NSObject__class" to "-[NSObject class]"); usually for the
purpose of pretty printing or error messages. Return the demangled
name, or NULL if the string is not an Objective-C mangled method
name.
Because of how the mangling is done, any method that has a '_' in
its original name is at risk of being demangled incorrectly. In
some cases there are multiple valid ways to demangle a method name
and there is no way we can decide.
TODO: objc_demangle() can't always get it right; the right way to
get this correct for all method names would be to store the
Objective-C method name somewhere in the function decl. Then,
there is no demangling to do; we'd just pull the method name out of
the decl. As an additional bonus, when printing error messages we
could check for such a method name, and if we find it, we know the
function is actually an Objective-C method and we could print error
messages saying "In method '+[NSObject class]" instead of "In
function '+[NSObject class]" as we do now. */
static const char *
objc_demangle (const char *mangled)
{
@ -10638,7 +10700,7 @@ objc_demangle (const char *mangled)
if (cp == NULL)
{
free(demangled); /* not mangled name */
return mangled;
return NULL;
}
if (cp[1] == '_') /* easy case: no category name */
{
@ -10652,29 +10714,104 @@ objc_demangle (const char *mangled)
if (cp == 0)
{
free(demangled); /* not mangled name */
return mangled;
return NULL;
}
*cp++ = ')';
*cp++ = ' '; /* overwriting 1st char of method name... */
strcpy(cp, mangled + (cp - demangled)); /* get it back */
}
/* Now we have the method name. We need to generally replace
'_' with ':' but trying to preserve '_' if it could only have
been in the mangled string because it was already in the
original name. In cases where it's ambiguous, we assume that
any '_' originated from a ':'. */
/* Initial '_'s in method name can't have been generating by
converting ':'s. Skip them. */
while (*cp && *cp == '_')
cp++; /* skip any initial underbars in method name */
for (; *cp; cp++)
if (*cp == '_')
*cp = ':'; /* replace remaining '_' with ':' */
cp++;
/* If the method name does not end with '_', then it has no
arguments and there was no replacement of ':'s with '_'s
during mangling. Check for that case, and skip any
replacement if so. This at least guarantees that methods
with no arguments are always demangled correctly (unless the
original name ends with '_'). */
if (*(mangled + strlen (mangled) - 1) != '_')
{
/* Skip to the end. */
for (; *cp; cp++)
;
}
else
{
/* Replace remaining '_' with ':'. This may get it wrong if
there were '_'s in the original name. In most cases it
is impossible to disambiguate. */
for (; *cp; cp++)
if (*cp == '_')
*cp = ':';
}
*cp++ = ']'; /* closing right brace */
*cp++ = 0; /* string terminator */
return demangled;
}
else
return mangled; /* not an objc mangled name */
return NULL; /* not an objc mangled name */
}
/* Try to pretty-print a decl. If the 'decl' is an Objective-C
specific decl, return the printable name for it. If not, return
NULL. */
const char *
objc_printable_name (tree decl, int kind ATTRIBUTE_UNUSED)
objc_maybe_printable_name (tree decl, int v ATTRIBUTE_UNUSED)
{
return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
const char *decl_name = IDENTIFIER_POINTER (DECL_NAME (decl));
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
return objc_demangle (decl_name);
break;
/* This unusual case (INSTANCE_METHOD_DECL and
CLASS_METHOD_DECL) seems to happen only in ObjC++ and to be a
by-product of the method attribute changes. It would be nice
to be able to print "-[NSObject autorelease] is deprecated",
but to do that, we'd need to store the class and method name
in the method decl, which we currently don't do. For now,
just return the name of the method. We don't return NULL,
because that may trigger further attempts to pretty-print the
decl in C/C++, but they wouldn't know how to pretty-print
it. */
case INSTANCE_METHOD_DECL:
case CLASS_METHOD_DECL:
return decl_name;
break;
default:
return NULL;
break;
}
}
/* Return a printable name for 'decl'. This first tries
objc_maybe_printable_name(), and if that fails, it hands it back to
C/C++. 'v' is the verbosity level, as this is a
LANG_HOOKS_DECL_PRINTABLE_NAME. */
const char *
objc_printable_name (tree decl, int v)
{
const char *demangled_name = objc_maybe_printable_name (decl, v);
if (demangled_name != NULL)
return demangled_name;
else
{
#ifdef OBJCPLUS
return cxx_printable_name (decl, v);
#else
return IDENTIFIER_POINTER (DECL_NAME (decl));
#endif
}
}
static void

View File

@ -1,3 +1,10 @@
2010-10-23 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/demangle-1.m: New test.
* obj-c++.dg/demangle-1.mm: New test.
* obj-c++.dg/demangle-2.mm: New test.
* obj-c++.dg/demangle-3.mm: New test.
2010-10-23 Ian Lance Taylor <iant@google.com>
* gcc.c-torture/execute/20101011-1.c: New test.

View File

@ -0,0 +1,35 @@
/* Test demangling a C++ function. */
/* { dg-do run } */
#include <cstring>
#include <cstdlib>
#include <iostream>
class demangle_test
{
public:
/* Return 0 if the demangling test succeeds. */
static int test_function1 ()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
return std::strcmp (__PRETTY_FUNCTION__, "static int demangle_test::test_function1()");
}
/* Return 0 if the demangling test succeeds. */
static int test_function2 (int ignored)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
return std::strcmp (__PRETTY_FUNCTION__, "static int demangle_test::test_function2(int)");
}
};
int main ()
{
if (demangle_test::test_function1 () != 0)
abort ();
if (demangle_test::test_function2 (0) != 0)
abort ();
return 0;
}

View File

@ -0,0 +1,50 @@
/* Test demangling an Objective-C method. */
/* { dg-do run } */
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <objc/objc.h>
@interface DemangleTest
{
Class isa;
}
+ (int) testFunction1;
+ (int) test_function2;
+ (int) __testFunction3: (int)unused andArgument: (char)unused2;
@end
@implementation DemangleTest
+ (int) testFunction1
{
std::cout << __PRETTY_FUNCTION__ << "\n";
return std::strcmp (__PRETTY_FUNCTION__, "+[DemangleTest testFunction1]");
}
+ (int) test_function2
{
std::cout << __PRETTY_FUNCTION__ << "\n";
return std::strcmp (__PRETTY_FUNCTION__, "+[DemangleTest test_function2]");
}
+ (int) __testFunction3: (int)unused andArgument: (char)unused2
{
std::cout << __PRETTY_FUNCTION__ << "\n";
return std::strcmp (__PRETTY_FUNCTION__, "+[DemangleTest __testFunction3:andArgument:]");
}
@end
int main ()
{
if ([DemangleTest testFunction1] != 0)
abort ();
if ([DemangleTest test_function2] != 0)
abort ();
if ([DemangleTest __testFunction3:0 andArgument: 'c'] != 0)
abort ();
return 0;
}

View File

@ -0,0 +1,21 @@
/* Test demangling an Objective-C method in error messages. */
/* { dg-do compile } */
#include <objc/objc.h>
@interface DemangleTest
{
Class isa;
}
+ (int) testFunction1;
@end
@implementation DemangleTest
+ (int) testFunction1
{
/* TODO: Hack the testsuite so we can test that we get
dg-error "In function .+[DemangleTest testFunction1]."
At the moment, the message is filtered out. */
z; /* { dg-error "was not declared" } */
}
@end

View File

@ -0,0 +1,56 @@
/* Test demangling an Objective-C method. */
/* { dg-do run } */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <objc/objc.h>
@interface DemangleTest
{
Class isa;
}
+ (int) testFunction1;
+ (int) test_function2;
+ (int) __testFunction3: (int)unused andArgument: (char)unused2;
@end
@implementation DemangleTest
+ (int) testFunction1
{
printf ("%s\n", __PRETTY_FUNCTION__);
return strcmp (__PRETTY_FUNCTION__, "+[DemangleTest testFunction1]");
}
/* Note that in general, due to how mangling is done, it's impossible
to get the demangling right for all functions containing '_' in the
name. But at least we should be able to get that right for single
argument ones that don't end with '_', such as the following
one. */
+ (int) test_function2
{
printf ("%s\n", __PRETTY_FUNCTION__);
return strcmp (__PRETTY_FUNCTION__, "+[DemangleTest test_function2]");
}
+ (int) __testFunction3: (int)unused andArgument: (char)unused2
{
printf ("%s\n", __PRETTY_FUNCTION__);
return strcmp (__PRETTY_FUNCTION__, "+[DemangleTest __testFunction3:andArgument:]");
}
@end
int main ()
{
if ([DemangleTest testFunction1] != 0)
abort ();
if ([DemangleTest test_function2] != 0)
abort ();
if ([DemangleTest __testFunction3:0 andArgument: 'c'] != 0)
abort ();
return 0;
}