C++ Name mangling

I was compiling the wxWidgets 2.6.3 source and ran into a problem when linking a program against it. They have a wxString class that has the public method

int PrintfV(const wxChar *format, va_list args).

In the wxString source, the symbol is: PrintfV__8wxStringFPCcP5__C11.

In another source file, there is a function with external linkage (not attached to a class) defined as follows:

void wxVLogStatus(wxFrame *pFrame,const wxChar *szFormat,va_list argptr)
{
wxString msg.

msg.PrintfV(szFormat,argptr);
}

This PrintfV symbol reference is: PrintfV__8wxStringFPCcP4__C1.

Why do these not match?

pgCC version 6.1-4 64-bit target on x86-64 Linux.

If you try to compile the source, I had to edit src/unix/dir.cpp and change the dirent *de = (dirent *)NULL; to dirent64 de = (dirent64)NULL; in function wxDirData::Read.

Hi Chris,

I’ve downloaded wxWidgits and have been able to recreate the issue. I think it’s more a configuration problem rather than a true compiler bug, but I’m still investigating. I appears that the definition for “va_list” is being interpreted slightly different for string.cpp and logg.cpp. However, I’m not yet sure as to the cause.

We’ll continue to investigate and hopefully have an answer soon.

Thanks,
Mat

Yeah, I don’t know where the problemn lies. I wasn’t hinting a compiler bug necessarily. I’m more of a C guy and couldn’t figure out the C++ name mangling. Thanks for looking into it!

While looking into it, do you have any clues on the dirent problem I mentioned? I couldn’t figure out why enough preprocessor flags were set to define readdir to readdir64, but not dirent to dirent64?

Chris

Hi Chris,

I’ve found a work around a was able to successfully compile and run the wxWidgets sample programs. The problem is that when given an un-tagged struct (in this case PGI’s version of va_list), it’s assigned a temorary name for use in the C++ name mangler. Unfortunately when string.cpp and logg.cpp are compiled, the temporary names given are slightly different. I tried unsuccessfully to get the compiler to use the same temp name so decided that the simplest action was to tag the va_list struct. For the work around, update your PGI installation’s “$PGI/linux86-64/6.1/include/va_list.h” header file and add “_pgi_va_list_t” to the va_list struct name. Although I normally don’t advise users to modify the default header files, this is a safe change for a unique case.

From:

typedef struct {
    unsigned int gp_offset;
    unsigned int fp_offset;
    char * overflow_arg_area;   /* Address of memory args area. */
    char * reg_save_area;       /* Address of where we stored the regs. */
} __pgi_va_list[1];

Change to :

typedef struct _pgi_va_list_t {
    unsigned int gp_offset;
    unsigned int fp_offset;
    char * overflow_arg_area;   /* Address of memory args area. */
    char * reg_save_area;       /* Address of where we stored the regs. */
} __pgi_va_list[1];

I’ll submitt a problem report to have this issue addressed in a future release.

As for “dirent”, the problem here is that the linux header file “/usr/include/dirent.h” defines “readdir” to be “readdir64” which has a return data type of “dirent64”.

From “/usr/include/dirent.h”

#ifndef __USE_FILE_OFFSET64
extern struct dirent *readdir (DIR *__dirp) __nonnull ((1));
#else
# ifdef __REDIRECT
extern struct dirent *__REDIRECT (readdir, (DIR *__dirp), readdir64)
     __nonnull ((1));
# else
#  define readdir readdir64
# endif
#endif

#ifdef __USE_LARGEFILE64
extern struct dirent64 *readdir64 (DIR *__dirp) __nonnull ((1));
#endif
  • Mat