2

I have a C++ library that uses the predefined macro __FUNCTION__, by way of crtdefs.h. The macro is documented here. Here is my usage:

my.cpp

#include <crtdefs.h>
...
void f()
{
    L(__FUNCTIONW__ L" : A diagnostic message");
}

static void L(const wchar_t* format, ...)
{
    const size_t BUFFERLENGTH = 1024;
    wchar_t buf[BUFFERLENGTH] = { 0 };
    va_list args;
    va_start(args, format);
    int count = _vsnwprintf_s(buf, BUFFERLENGTH, _TRUNCATE, format, args);
    va_end(args);
    if (count != 0)
    {
        OutputDebugString(buf);
    }
}

crtdefs.h

#define __FUNCTIONW__ _STR2WSTR(__FUNCTION__) 

The library (which is compiled as a static library, if that matters) is consumed by another project in the same solution, a WPF app written in C#.

When I compile the lib, I get this error:

identifier "L__FUNCTION__" is undefined.

According to the docs, the macro isn't expanded if /P or /EP are passed to the compiler. I have verified that they are not. Are there other conditions where this macro is unavailable?

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
Justin R.
  • 23,435
  • 23
  • 108
  • 157
  • What is the minimum required to reproduce the problem? What is in the `...`? – James McNellis May 05 '14 at 21:37
  • This is probably not the issue here, but symbols starting with `__` are reserved for the compiler, so you should try to find another name for your `#define`. – zneak May 05 '14 at 21:43
  • The "..." is the rest of the class, a bunch of functions around D3D debugging. I can remove their bodies and nothing changes. – Justin R. May 05 '14 at 21:43
  • It's `__func__`, `__FUNCTION__` or `__PRETTY_FUNCTION__` Not sure if you can make it "wide" the same way you are attempting. Your macro for making it wide might not be right. – Brandon May 05 '14 at 21:44
  • @zneak I didn't write `__FUNCTIONW__`, that ships with the compiler in crtdefs.h. – Justin R. May 05 '14 at 21:44
  • I see. Your first paragraph mentions `__FUNCTION__` and not `__FUNCTIONW__`; I now realize that this is probably a typo. – zneak May 05 '14 at 21:45
  • @hvd, I should have pointed out that I have a function named L. I'll add that to the question, one sec. – Justin R. May 05 '14 at 21:46
  • @fatcat1111 That's at least part of your problem. [`L` is a predefined part of the language](http://stackoverflow.com/questions/13087219/what-exactly-is-the-l-prefix-in-c), and I *really* don't think you should be giving that name to a function. – cf- May 05 '14 at 21:48
  • _STR2WSTR is defined in crtdefs.h too: `#define _STR2WSTR(str) __STR2WSTR(str)`, and `#define __STR2WSTR(str) L##str`. – Justin R. May 05 '14 at 21:48
  • 1
    How odd, that does look correct. The error you're getting is a common one when that indirection through an additional helper macro is not present, but if the definitions you show are indeed the ones the preprocessor uses, that's not the problem. (I've deleted my previous comments, sorry for the noise.) –  May 05 '14 at 21:50
  • 2
    What version are you using? VS2013 [doesn't seem to have a problem with it](http://rise4fun.com/Vcpp/nsl6). – Oktalist May 05 '14 at 22:42

3 Answers3

1

You list the error as this:

identifier "L__FUNCTION__" is undefined.

Note it's saying "L__FUNCTION__" is not defined, not "__FUNCTION__".

Don't use __FUNCTIONW__ in your code. MS didn't document that in the page you linked, they documented __FUNCTION__. And you don't need to widen __FUNCTION__.

ETA: I also note that you're not assigning that string to anything or printing it in anyway in f().

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Rob K
  • 8,757
  • 2
  • 32
  • 36
  • I think that the error message is using the string literal identifier "L" here, not referencing my function of the same name. I'll rename the function to confirm. I'm widening `__FUNCTION__` as L() takes a wchar_t. It's true that the wide macro isn't documented but it's defined right alongside the narrow one, so I'm betting it's legal to use. Still, I'll switch to that and convert it to a wide string and see if that helps. I'm printing the expanded value in L(). – Justin R. May 05 '14 at 22:21
  • Yes, which is why I put it inside the double quotes, as part of the string literal. No, `__FUNCTIONW__` is not "legal to use". You'll get away with using it, until one day MS releases a compiler+library that doesn't define it and your code doesn't compile anymore. In that case, /maybe/ no big deal. In other cases of other things you found in header files, days of painful porting. Don't use things that are not documented. – Rob K May 06 '14 at 02:03
  • Fair point Rob. Using this now could be a setup for trouble later; better is to take the narrow version and widen it myself if needed. Thanks for your help with this. – Justin R. May 06 '14 at 17:53
0

Just use

L(__FUNCTION__    L" : A diagnostic message");

When adjacent string literals get combined, the result will be a wide string if any of the components were.

There's nothing immediately wrong with using L as the name of a function... it's rather meaningless however. Good variable and function identifiers should be descriptive in order to help the reader understand the code. But the compiler doesn't care.


Since your L function wraps vsprintf, you may also use:

L(L"%hs : A diagnostic message", __func__);

since __func__ is standardized as a narrow string, the %hs format specifier is appropriate.


The rule is found in 2.14.5p13:

In translation phase 6 (2.2), adjacent string literals are concatenated. If both string literals have the same encoding-prefix, the resulting concatenated string literal has that encoding-prefix. If one string literal has no encoding-prefix, it is treated as a string literal of the same encoding-prefix as the other operand. If a UTF-8 string literal token is adjacent to a wide string literal token, the program is ill-formed. Any other concatenations are conditionally-supported with implementation-defined behavior.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • This would only work if `__FUNCTION__` were a preprocessor macro to a string literal in fatcat1111's compiler, which I don't think it is. But it sure is worth a try! – Daniel Darabos May 05 '14 at 22:41
  • 1
    @DanielDarabos: [Well, it isn't standardized at all](http://stackoverflow.com/q/597078/103167) It's certain that `__func__` is a string, specifically a narrow string. But `__FUNCTION__` may or may not exist and may be a macro or a variable. – Ben Voigt May 05 '14 at 22:43
0

I think the definition of __FUNCTIONW__ is incorrect. (I know you did not write it.)

From: http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html

These identifiers are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used to initialize char arrays, and they could be concatenated with other string literals. GCC 3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ have always been variables.

At least in current GCC then you cannot prepend L to __FUNCTION__, because it is like trying to prepend L to a variable. There probably was a version of VC++ (like there was of GCC) where this would have worked, but you are not using that version.

Daniel Darabos
  • 26,991
  • 10
  • 102
  • 114
  • Well, he isn't using g++. – Ben Voigt May 05 '14 at 22:37
  • But his compiler is giving the same error message that I get from GCC, so I think it behaves the same way in this regard. One way to check how `__FUNCTION__` is implemented: `#ifdef __FUNCTION__ \ printf("it is a macro"); \ #endif` – Daniel Darabos May 05 '14 at 22:43