This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Fix 13241


Mark,
this fixes PR 13241 where we were not correctly mangling an external
object used as a template argument. This reworks things so that
the old behaviour is preserved with -fabi-version=1 and the new
behaviour otherwise. -Wabi will give a warning.

booted & tested on i686-pc-linux-gnu, ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
         The voices in my head said this was stupid too
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2003-12-10  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/13241 C++ ABI change. Mangling of symbols in expressions.
	* mangle.c (write_mangled_name): Add top_level flag. Rework for
	nested and unnested mangling. Deal with abi version 1 and version
	2 differences.
	(write_expression): Adjust write_mangled_name call.
	(mangle_decl_string): Use write_mangled_name for all non-type decls.

Index: cp/mangle.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/mangle.c,v
retrieving revision 1.88
diff -c -3 -p -r1.88 mangle.c
*** cp/mangle.c	22 Oct 2003 02:08:45 -0000	1.88
--- cp/mangle.c	8 Dec 2003 12:42:55 -0000
*************** static void mangle_call_offset (const tr
*** 158,164 ****
  
  /* Functions for emitting mangled representations of things.  */
  
! static void write_mangled_name (const tree);
  static void write_encoding (const tree);
  static void write_name (tree, const int);
  static void write_unscoped_name (const tree);
--- 158,164 ----
  
  /* Functions for emitting mangled representations of things.  */
  
! static void write_mangled_name (const tree, bool);
  static void write_encoding (const tree);
  static void write_name (tree, const int);
  static void write_unscoped_name (const tree);
*************** find_substitution (tree node)
*** 602,628 ****
  }
  
  
! /*  <mangled-name>      ::= _Z <encoding>  */
  
  static inline void
! write_mangled_name (const tree decl)
  {
    MANGLE_TRACE_TREE ("mangled-name", decl);
  
!   if (DECL_LANG_SPECIFIC (decl)
!       && DECL_EXTERN_C_FUNCTION_P (decl)
!       && ! DECL_OVERLOADED_OPERATOR_P (decl))
!     /* The standard notes:
!          "The <encoding> of an extern "C" function is treated like
! 	 global-scope data, i.e. as its <source-name> without a type."
!        We cannot write overloaded operators that way though,
!        because it contains characters invalid in assembler.  */
!     write_source_name (DECL_NAME (decl));
    else
-     /* C++ name; needs to be mangled.  */
      {
        write_string ("_Z");
        write_encoding (decl);
      }
  }
  
--- 602,667 ----
  }
  
  
! /* TOP_LEVEL is true, if this is being called at outermost level of
!   mangling. It should be false when mangling a decl appearing in an
!   expression within some other mangling.
!   
!   <mangled-name>      ::= _Z <encoding>  */
  
  static inline void
! write_mangled_name (const tree decl, bool top_level)
  {
    MANGLE_TRACE_TREE ("mangled-name", decl);
  
!   if (/* The names of `extern "C"' functions are not mangled.  */
!       DECL_EXTERN_C_FUNCTION_P (decl)
!       /* But overloaded operator names *are* mangled.  */
!       && !DECL_OVERLOADED_OPERATOR_P (decl))
!     {
!     unmangled_name:;
!       
!       if (top_level)
! 	write_string (IDENTIFIER_POINTER (DECL_NAME (decl)));
!       else
! 	{
! 	  /* The standard notes: "The <encoding> of an extern "C"
!              function is treated like global-scope data, i.e. as its
!              <source-name> without a type."  We cannot write
!              overloaded operators that way though, because it contains
!              characters invalid in assembler.  */
! 	  if (abi_version_at_least (2))
! 	    write_string ("_Z");
! 	  else
! 	    G.need_abi_warning = true;
! 	  write_source_name (DECL_NAME (decl));
! 	}
!     }
!   else if (TREE_CODE (decl) == VAR_DECL
! 	   /* The names of global variables aren't mangled.  */
! 	   && (CP_DECL_CONTEXT (decl) == global_namespace
! 	       /* And neither are `extern "C"' variables.  */
! 	       || DECL_EXTERN_C_P (decl)))
!     {
!       if (top_level || abi_version_at_least (2))
! 	goto unmangled_name;
!       else
! 	{
! 	  G.need_abi_warning = true;
! 	  goto mangled_name;
! 	}
!     }
    else
      {
+     mangled_name:;
        write_string ("_Z");
        write_encoding (decl);
+       if (DECL_LANG_SPECIFIC (decl)
+ 	  && (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)
+ 	      || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)))
+ 	/* We need a distinct mangled name for these entities, but
+ 	   we should never actually output it.  So, we append some
+ 	   characters the assembler won't like.  */
+ 	write_string (" *INTERNAL* ");
      }
  }
  
*************** write_expression (tree expr)
*** 1893,1899 ****
        if (code == CONST_DECL)
  	G.need_abi_warning = 1;
        write_char ('L');
!       write_mangled_name (expr);
        write_char ('E');
      }
    else if (TREE_CODE (expr) == SIZEOF_EXPR 
--- 1932,1938 ----
        if (code == CONST_DECL)
  	G.need_abi_warning = 1;
        write_char ('L');
!       write_mangled_name (expr, false);
        write_char ('E');
      }
    else if (TREE_CODE (expr) == SIZEOF_EXPR 
*************** mangle_decl_string (const tree decl)
*** 2363,2391 ****
  
    if (TREE_CODE (decl) == TYPE_DECL)
      write_type (TREE_TYPE (decl));
-   else if (/* The names of `extern "C"' functions are not mangled.  */
- 	   (DECL_EXTERN_C_FUNCTION_P (decl)
- 	    /* But overloaded operator names *are* mangled.  */
- 	    && !DECL_OVERLOADED_OPERATOR_P (decl))
- 	   /* The names of global variables aren't mangled either.  */
- 	   || (TREE_CODE (decl) == VAR_DECL
- 	       && CP_DECL_CONTEXT (decl) == global_namespace)
- 	   /* And neither are `extern "C"' variables.  */
- 	   || (TREE_CODE (decl) == VAR_DECL
- 	       && DECL_EXTERN_C_P (decl)))
-     write_string (IDENTIFIER_POINTER (DECL_NAME (decl)));
    else
!     {
!       write_mangled_name (decl);
!       if (DECL_LANG_SPECIFIC (decl)
! 	  && (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)
! 	      || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)))
! 	/* We need a distinct mangled name for these entities, but
! 	   we should never actually output it.  So, we append some
! 	   characters the assembler won't like.  */
! 	write_string (" *INTERNAL* ");
!     }
! 
    result = finish_mangling (/*warn=*/true);
    if (DEBUG_MANGLE)
      fprintf (stderr, "mangle_decl_string = '%s'\n\n", result);
--- 2402,2410 ----
  
    if (TREE_CODE (decl) == TYPE_DECL)
      write_type (TREE_TYPE (decl));
    else
!     write_mangled_name (decl, true);
!   
    result = finish_mangling (/*warn=*/true);
    if (DEBUG_MANGLE)
      fprintf (stderr, "mangle_decl_string = '%s'\n\n", result);
// { dg-do compile }
// { dg-options "-fabi-version=2" }

// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 30 Nov 2003 <nathan@codesourcery.com>

// PR 13241
// mangled template arguments that are external objects incorrectly

extern "C" void Foo ();
namespace NMS 
{
  extern "C" int V;
}

template <void (*)()> struct S {};
template <int *> struct T {};

void f (S<Foo>){}
// { dg-final { scan-assembler "\n_Z1f1SIXadL_Z3FooEEE:" } }

void g (T<&NMS::V>){}
// { dg-final { scan-assembler "\n_Z1g1TIXadL_Z1VEEE:" } }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]