Skip to content

STR2WSTR(__FUNCTION__) should work in microsoft mode #12161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nico opened this issue Jan 18, 2012 · 16 comments
Closed

STR2WSTR(__FUNCTION__) should work in microsoft mode #12161

nico opened this issue Jan 18, 2012 · 16 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla clang:frontend Language frontend issues, e.g. anything involving "Sema"

Comments

@nico
Copy link
Contributor

nico commented Jan 18, 2012

Bugzilla Link 11789
Resolution FIXED
Resolved on Sep 07, 2015 01:26
Version unspecified
OS Windows NT
Blocks llvm/llvm-bugzilla-archive#12477
CC @majnemer,@zmodem,@tritao

Extended Description

#include <stdio.h>

#define _FOO_STR2WSTR(s) L##s
#define FOO_STR2WSTR(s) _FOO_STR2WSTR(s)

int main() {
//const wchar_t* kFoo = L__FUNCTION__; // doesn't work in cl.exe
const wchar_t* kWFoo = FOO_STR2WSTR(FUNCTION); // works in cl
}

Both gcc and clang don't allow this, but cl.exe does. (gcc and clang support it for e.g. FILE.)

This is used in msvc's c++ standard headers.

@nico
Copy link
Contributor Author

nico commented Jan 18, 2012

assigned to @nico

@nico
Copy link
Contributor Author

nico commented Jan 18, 2012

(In xstddef, with _HAS_EXCEPTIONS defined to 0.)

@nico
Copy link
Contributor Author

nico commented Jan 18, 2012

Stupid -fsyntax-only workaround: change crtdefs.h to #define FUNCTIONW to e.g. _STR2WSTR(FILE) instead.

@llvmbot
Copy link
Member

llvmbot commented Feb 29, 2012

A little more information about this since I ran into the same issue, i.e. when including in VS2010:

See this link: http://blog.shuva.in/index.php?entry=entry080823-063456

Microsoft's compiler turns FOO_STR2WSTR(FUNCTION) into __LPREFIX(FUNCTION). __LPREFIX isn't a macro, it's a weird compiler intrinsic that does what the "L" prefix is meant to do. This seems to be specifically for handling FUNCTION, because FOO_STR2WSTR(ANYTHING_ELSE) just results in LANYTHING_ELSE. Here's my small test case:

// C++ file:
#define __STR2WSTR(str) L##str
#define _STR2WSTR(str) __STR2WSTR(str)
#define FUNCTIONW _STR2WSTR(FUNCTION)
#define UNDEF_TEST _STR2WSTR(NOTFUNCTION)

int main( int argc, char* argv[] ) {
(void)FUNCTIONW;
(void)UNDEF_TEST;
return 0;
}

// Preprocessed output from VC10:
int main( int argc, char* argv[] ) {
(void)LPREFIX( FUNCTION);
(void)L__NOTFUNCTION
;
return 0;
}

Maybe Microsoft's preprocessor specifically handles concatenating L ## FUNCTION?

@llvmbot
Copy link
Member

llvmbot commented Feb 29, 2012

I did some more testing. It looks like VC does a bunch of stuff to make it appear like FUNCTION is a macro. This isn't just for the case of the "L" prefix. Note that when prefixing with some garbage, "QWERTY", the preprocessor generates a result similar to the "L" case. It doesn't do anything special for strings though.

// C++ file:
#define __STR2WSTR(str) L##str
#define _STR2WSTR(str) __STR2WSTR(str)
#define FUNCTIONW _STR2WSTR(FUNCTION)
#define UNDEF_TEST _STR2WSTR(NOTFUNCTION)

#define __OTHER_PREFIX(str) QWERTY##str
#define _OTHER_PREFIX(str) __OTHER_PREFIX(str)
#define OTHER_PREFIX _OTHER_PREFIX(FUNCTION)

#define __STRING_PREFIX(str) "a string" str
#define _STRING_PREFIX(str) __STRING_PREFIX(str)
#define STRING_PREFIX _STRING_PREFIX(FUNCTION)

int main( int argc, char* argv[] ) {
(void)FUNCTIONW;
(void)UNDEF_TEST;
(void)OTHER_PREFIX;
(void)STRING_PREFIX;
return 0;
}

// Preprocessed output from VC10:
int main( int argc, char* argv[] ) {
(void)LPREFIX( FUNCTION);
(void)L__NOTFUNCTION
;
(void)QWERTY__FSTREXP FUNCTION ;
(void)"a string" FUNCTION ;
return 0;
}

@llvmbot
Copy link
Member

llvmbot commented Mar 1, 2012

So this appears to be something special to do with FUNCTION to make it look like a macro. I would expect this same behavior with FUNCSIG and FUNCDNAME, since they're all supposed to behave like macros, but really are implemented in the compiler and not the preprocessor. The preprocessor specially handles two things: L##FUNCTION, and ##FUNCTION ( representing any token). L##FUNCTION gets turned into __LPREFIX(FUNCTION). Something else, like QWERTY##FUNCTION gets turned into QWERTY__FSTREXP FUNCTION. One other rule is, whenever one of the arguments to the concatenation operator is FUNCTION, a space goes in between them.

I think this is reasonable to implement in the preprocessor. I'll have to do some more research into how the "FSTREXP" identifiers get treated in the compiler -- I want to see if they get turned into anything else there.

@nico
Copy link
Contributor Author

nico commented Mar 4, 2012

Does MSVC compile this program?:

void f() {
const char* f = "foo" FUNCTION;
}

One possible way to make this work would be to have the parser tell the preprocessor about the current function name every time it enters a function, and have the preprocessor handle FUNCTION like FILE (i.e. like a normal string) except expanding it to the current "current function name" it got from the parser.

This might get tricky with template functions, where the parameter types aren't known when that function is getting parsed.

What does FUNCTION expand to in template functions in msvc? Does msvc support PRETTY_FUNCTION? What does that expand to?

@llvmbot
Copy link
Member

llvmbot commented May 20, 2012

MSVC does compile that program, and the preprocessed output is the same as the input.

MSVC doesn't support PRETTY_FUNCTION. Here's a list of what the preprocessor does support: http://msdn.microsoft.com/library/b0084kay.aspx

I think we should handle this in the preprocessor, as the regular FUNCTION and equivalent macros are currently handled.

@llvmbot
Copy link
Member

llvmbot commented May 20, 2012

It looks like the FSTREXP cases aren't worth compiling:

#include
using namespace std;

const char* const QWERTY = "qwerty";

#define __OTHER_PREFIX(str) QWERTY##str
#define _OTHER_PREFIX(str) __OTHER_PREFIX(str)
#define OTHER_PREFIX _OTHER_PREFIX(FUNCTION)

#define __STRING_PREFIX(str) "a string" str
#define _STRING_PREFIX(str) __STRING_PREFIX(str)
#define STRING_PREFIX _STRING_PREFIX(FUNCTION)

int main() {
cout << OTHER_PREFIX << endl; // error here
cout << STRING_PREFIX << endl;
return 0;
}

As noted above, OTHER_PREFIX expands to QWERTY__FSTREXP FUNCTION. However, the compiler then complains that it doesn't recognize the identifier "QWERTY__FSTREXP". I'm not sure why the preprocessor emits this, then, maybe it's an internal implementation detail. Given this, I think it's only worth trying to implement the __LPREFIX thing.

@llvmbot
Copy link
Member

llvmbot commented Jun 21, 2012

I'm tackling the problem right now. I think easiest way would be to

  1. Support wchar_t variant of FUNCTION (I'm calling it FUNCTIONW as I didn't realize that MS defines a macro of that name. It actually works fine this way, still, it might be better to rename it to something that doesn't collide).
  2. In MS mode, predefine L__FUNCTION__ to FUNCTIONW.

The ability of MS compilers to paste string literals and predef variables would have to be handled separately.

I have a partial implementation of FUNCTIONW (without codegen, only for -fsyntax-only): https://github.com/avakar/clang/tree/bug11789

@tritao
Copy link
Mannequin

tritao mannequin commented Jun 21, 2012

Hi Martin.

There has been some patches and discussion regarding this in the list:

http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20120611/058838.html

@llvmbot
Copy link
Member

llvmbot commented Jun 21, 2012

If you see my discussion with Richard Smith about my patch, it sounds like he would prefer a very simple patch, rather than emulating the exact behavior of MSVC, which I can understand. Given that, it might make sense to not even bother #defining L__FUNCTION__ to FUNCTIONW or anything like that. Just add a predefined expression L__FUNCTION__ that is the wide string function name, only available in ms compatibility mode. Thoughts?

@llvmbot
Copy link
Member

llvmbot commented Jun 21, 2012

If you see my discussion with Richard Smith about my patch, it sounds like he
would prefer a very simple patch, rather than emulating the exact behavior of
MSVC,

Yes, I've seen your original patch submission and found it too complex as well.

Given that, it might make sense to not even
bother #defining L__FUNCTION__ to FUNCTIONW or anything like that. Just add
a predefined expression L__FUNCTION__ that is the wide string function name,
only available in ms compatibility mode. Thoughts?

It would be sufficient for compatibility's sake, however, there is currently no way to get wchar_t version of FUNCTION and since it will have to be supported for the sake of MS, I'd make it available for non-MS modes as well. And, of course, we wouldn't want it to be called L__FUNCTION__ there. That's why I went with FUNCTIONW and a predefined macro.

@nico
Copy link
Contributor Author

nico commented Jun 23, 2012

r159060

See http://thread.gmane.org/gmane.comp.compilers.clang.scm/52277 for discussion.

@timurrrr
Copy link
Contributor

mentioned in issue llvm/llvm-bugzilla-archive#12477

@rnk
Copy link
Collaborator

rnk commented Nov 26, 2021

mentioned in issue llvm/llvm-bugzilla-archive#20013

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla clang:frontend Language frontend issues, e.g. anything involving "Sema"
Projects
None yet
Development

No branches or pull requests

4 participants