OSDN Git Service

In gcc/cp/:
authornicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 23 Oct 2010 18:40:39 +0000 (18:40 +0000)
committernicola <nicola@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 23 Oct 2010 18:40:39 +0000 (18:40 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165887 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/stub-objc.c
gcc/cp/ChangeLog
gcc/cp/tree.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/obj-c++.dg/demangle-1.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/demangle-2.mm [new file with mode: 0644]
gcc/testsuite/obj-c++.dg/demangle-3.mm [new file with mode: 0644]
gcc/testsuite/objc.dg/demangle-1.m [new file with mode: 0644]

index 93664f3..b73e45a 100644 (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>
 
index f882a8f..8031bb4 100644 (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++.  */
index 7ef4f1e..f808dc7 100644 (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))
 {
index 6a3d5c7..bf36e6f 100644 (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
index b8f76b0..26746f9 100644 (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
index de64a31..7720a9c 100644 (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.
index bc07910..97ac0e8 100644 (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
index 3ab40ac..137f965 100644 (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.
diff --git a/gcc/testsuite/obj-c++.dg/demangle-1.mm b/gcc/testsuite/obj-c++.dg/demangle-1.mm
new file mode 100644 (file)
index 0000000..015a3af
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/obj-c++.dg/demangle-2.mm b/gcc/testsuite/obj-c++.dg/demangle-2.mm
new file mode 100644 (file)
index 0000000..c58a4f8
--- /dev/null
@@ -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;
+}
+
+
diff --git a/gcc/testsuite/obj-c++.dg/demangle-3.mm b/gcc/testsuite/obj-c++.dg/demangle-3.mm
new file mode 100644 (file)
index 0000000..01e6c61
--- /dev/null
@@ -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
diff --git a/gcc/testsuite/objc.dg/demangle-1.m b/gcc/testsuite/objc.dg/demangle-1.m
new file mode 100644 (file)
index 0000000..0cee76b
--- /dev/null
@@ -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;
+}
+
+