Zero as a function name - c++

The following example compiles (VS2010 C++ compiler issues a warning C4353 though) and expression (*) evaluates to 0:
#include <iostream>
#include <string>
int main()
{
0(1, "test"); // (*) - any number and type of arguments allowed
int n = 0(1, "test"); // 0
std::string str(0(1, "test")); // Debug assertion fails - 0 pointer passed
}
Is using 0 as a function name allowed/regulated by C++ standard or its resolution is compiler-specific? I was looking in the N3242 draft but could not find anything related to this. Microsoft compiler obviously resolves such construct (or one with __noop) as an integer with value 0.
warning C4353:
warning C4353: nonstandard extension used: constant 0 as function
expression. Use __noop function intrinsic instead

A function name is an identifier and an identifier needs to start with a non-digit (§2.11):
identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit

I don't know the answer, but I believe we can find it by a little googling...
Looking at the MSDN, I found two links:
C4353 : http://msdn.microsoft.com/en-us/library/2a68558f.aspx
__noop : http://msdn.microsoft.com/en-us/library/s6btaxcs.aspx
The second link explains the __noop
The __noop intrinsic specifies that a function should be ignored and the argument list be parsed but no code be generated for the arguments. It is intended for use in global debug functions that take a variable number of arguments.
Th example shows the __noop can be very interesting indeed for debug code:
#if DEBUG
#define PRINT printf_s
#else
#define PRINT __noop
#endif
int main() { PRINT("\nhello\n"); }
Another comment on the same page gives an historical hint on the 0 function:
The compiler converts the __noop intrinsic to 0 at compile time.
I guess that, once upon a time, this extension was called 0, not __noop, and that later, Microsoft created the __noop keyword because it was easier to search for, more readable, less "strange" than this 0 thing, and clearly marked as an extension (because of the two leading underscores, like MSVC's __declspec or gcc's __attribute__).
Conclusion: What about 0?
This is an extension (as per the warning message)
This is an historical, deprecated extension
Its use is deprecated in favor of __noop
It was deprecated at least at the VC++2003 time (if not before)

Related

What are "extern char condition tricks"?

I was reading the GCC documentation on C and C++ function attributes. In the description of the error and warning attributes, the documentation casually mentions the following "trick":
error ("message")
warning ("message")
If the error or warning attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, an error or warning (respectively) that includes message is diagnosed. This is useful for compile-time checking, especially together with __builtin_constant_p and inline functions where checking the inline function arguments is not possible through extern char [(condition) ? 1 : -1]; tricks.
While it is possible to leave the function undefined and thus invoke a link failure (to define the function with a message in .gnu.warning* section), when using these attributes the problem is diagnosed earlier and with exact location of the call even in presence of inline functions or when not emitting debugging information.
There's no further explanation. Perhaps it's obvious to programmers immersed in the environment, but it's not at all obvious to me, and I could not find any explanation online. What is this technique and when might I use it?
I believe the premise is to have a compile time assert functionality. Suppose that you wrote
extern char a[(condition) ? 1 : -1];
If condition is true, nothing happens and the line compiles to nothing. The extern makes sure that a doesn't use any memory. However, if condition is false, a is declared as an array of negative length, and you get a compile time error.
You probably wrap it in a macro and have something similar to static_assert
#define STATIC_ASSERT(condition) extern char a[(condition) ? 1 : -1]

fatal error C1017: invalid integer constant expression when using "#if (false)"

Have following code which is working under Linux but gives error for MSVS
#if (false)
....
#endif
The error is: fatal error C1017: invalid integer constant expression
I found this report on Microsoft's web:
http://msdn.microsoft.com/en-us/library/h5sh3k99.aspx
While the info described there differs a little bit compared to my case as I didn't use the "#define"
So my question is:
Is there any way to make it working for MSVC without changing code ?
If the code must be updated, what's the best solution for this kind of case?
It looks like your version of MS compiler does not support false as a built-in constant. This is not surprising, because Microsoft has a spotty record of supporting standards for C and C++.
One way to make this work without changing the code is to pass command-line parameters to the compiler to define false as 0 and true as 1:
-Dfalse=0 -Dtrue=1
Is there any way to make it working for MSVC without changing code ?
Not really. Defining a macro for false is forbidden by the standard for good reasons, [macro.names]/2:
A translation unit shall not #define or #undef names lexically
identical to keywords, to the identifiers listed in Table 3, or to the
attribute-tokens described in 7.6.
And I don't see any other way.
If the code must be updated, what's the best solution for this kind of
case?
Substitute 0 for false.

gcc inlined assembly jmp address; Naked functions

I can jmp to an address using Visual Studio 2012.. When it comes to gcc/mingw, I cannot tell if my jump is correct.
How can I jump to an address in gcc?
I tried:
__declspec(naked) void DXHook_D3DPERF_BeginEvent()
{
#ifdef _MSC_VER //If using visual studio..
__asm{jmp[Addr]} //Jump to: Address stored in Addr.
#else //else using gcc..
__asm("jmp *%0"
: /*No Outputs*/
: "r" (Addr)
: "%eax");
#endif
}
Is this correct? Also, is there a way to get gcc to stop bothering me about:
warning: 'naked' attribute directive ignored.
Why does it ignore my naked attribute?
TL;DR In GCC, this is only available on: ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU ports
It is NOT available on x86.
Workaround (proposed by Brendon in the comments).
Full answer
(The rest of this answer assumes you are using a supported target)
That is because you are using the Windows attribute syntax, __declspec with GCC.
Quote from the MSDN reference on __declspec:
The extended attribute syntax simplifies and standardizes Microsoft-specific extensions to the C and C++ languages.
You should use the GCC function attribute syntax instead or in parallel.
Please also note the following quote from this GCC article:
Note: The semantics are not the same between Windows and this GCC
feature - for example, __declspec(dllexport) void (*foo)(void) and
void (__declspec(dllexport) *foo)(void) mean quite different things
whereas this generates a warning about not being able to apply
attributes to non-types on GCC.
So there could also be an issue with the way you are using the __declspec syntax in GCC (if it even supports it).
You should also note that the only __declspec attribute that GCC states it supports is the __declspec(dllexport) (as stated in the already mentioned GCC attribute syntax link).
So let's look for a generic solution to your problem but first we will need to read about the actual GCC attribute syntax and find the following:
An attribute specifier list may appear immediately before a declarator
(other than the first) in a comma-separated list of declarators in a
declaration of more than one identifier using a single list of
specifiers and qualifiers. Such attribute specifiers apply only to the
identifier before whose declarator they appear. For example, in
__attribute__((noreturn)) void d0 (void),
__attribute__((format(printf, 1, 2))) d1 (const char *, ...),
d2 (void)
the noreturn attribute applies to all the functions declared; the
format attribute only applies to d1.
So the solution to your problem would be something like the following:
#ifdef __GNUC__
#define ATTRIBUTE_NAKED __attribute__((naked))
#else
#define ATTRIBUTE_NAKED __declspec(naked)
#endif
ATTRIBUTE_NAKED void DXHook_D3DPERF_BeginEvent()
{
#ifdef _MSC_VER //If using visual studio..
__asm{jmp[Addr]} //Jump to: Address stored in Addr.
#else //else using gcc..
__asm("jmp *%0"
: /*No Outputs*/
: "r" (Addr)
: "%eax");
#endif
}
Edit:
It is important to note that this attribute is platform specific. And I quote:
naked
This attribute is available on the ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU ports. It allows the compiler to construct the
requisite function declaration, while allowing the body of the
function to be assembly code. The specified function will not have
prologue/epilogue sequences generated by the compiler. Only basic asm
statements can safely be included in naked functions (see Basic Asm).
While using extended asm or a mixture of basic asm and C code may
appear to work, they cannot be depended upon to work reliably and are
not supported.
Quoted from the GCC documentation on function attributes.
Side note
Possible further reading on clang attributes could help (mostly compatible with GCC) but these comments seem to suggest a desire to match GCC behavior.
To do the equivalent of the Visual C++ code, implement it entirely in assembly either in a separate file or in a top level (not in a function) asm statement.

Is it possible to define another preprocessor directive?

I've been looking through code golf and got an idea to try this code:
#define D #define after adding this line, everything worked fine, however I expanded it into this:
#define D #define
D VALUE
And here I got 5 compilation error. If I change D into #define everything is fine, can someone explain, why this code is illegal?
NOTE: I used VS2008 compiler.
EDIT: After some answers I see that I needed to give compilations error list:
error C2121: '#' : invalid character : possibly the result of a macro expansion
error C2146: syntax error : missing ';' before identifier 'VALUE'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2144: syntax error : 'void' should be preceded by ';'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
First error shows that D is not just define but also includes #.
C 2011 (N1570) 6.10.3.4 3: “The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one,…”
C++ 2010 (N3092) 16.3.4 [cpp.rescan] 3 has exactly the same text.
This code is illegal because language specification says it is illegal. According to C and C++ preprocessor specification, whatever code you build using preprocessor will never be interpreted as another preprocessor directive. In short, you cannot build preprocessor directives using preprocessor. Period.
(Also, you cannot build comments using preprocessor.)
It does look like your preprocessor is making the substitution you want, but you likely wouldn't get the behaviour you want - the preprocessor is normally just a single pass operation. Example (with clang, but you should be able to reproduce by using the appropriate VS2008 flags):
$ cat example.c
#define D #define
D VALUE
$ cc -P -E example.c
#define VALUE
That #define VALUE is going straight through to the compiler, which won't know what to do with it - it's a preprocessor directive, after all. Clang's error, for reference, is similar to yours:
$ cc -c example.c
example.c:2:1: error: expected identifier or '('
D VALUE
^
example.c:1:11: note: expanded from macro 'D'
#define D #define
^
1 error generated.
That won't work because preprocessing is performed in a single pass. For example, consider the next code :
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
int main() {
return 0;
}
After preprocessing, your code will looks like :
#define N 6
int main() {
return 0;
}
and "#define" is not a valid syntax on C or C++. Also, since the resulting preprocessor directive is not going to be processed, it won't resolve subsequent references to the "N" macro in your code.
Just for fun, you can call the preprocesor twice from the command line using g++/gcc. Consider the next code (define.cpp) :
#include <iostream>
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
using namespace std;
int main() {
cout << N << endl;
return 0;
}
Then you can do:
$ g++ -E define.cpp | g++ -o define -x c++ - && ./define
and will output:
6
Lines of code in the pre-processors eyes are either pre-processor statements (And thus don't have any replacements done on them) or normal text statements (And have replacements done). You can't have one be both, so once you have 'D' be replaced it's only going to look to see if there are any more macros to replace. Since there are none, it just leaves '#define' in the C++ code as it is and then the C++ compiler will error when it sees it (Since '#define' isn't valid C++ code).
So show my point more, this is invalid code for the pre-processor:
#define D define
#D value
Because the pre-processor doesn't do any macro replacement on pre-processor statements, and "#D" isn't a recognized pre-processor command. And this:
#define D #define
D value
Results in this C++ code:
#define value
Which is invalid because the pre-processor is already done being run.
Looking at the grammar in 16 [cpp] paragraph 1, a replacement-list consists of pp-tokens which may include the production # no-directive which is described in paragraph 2 of the same paragraph as
A non-directive shall not begin with any of the directive names appearing in the list.
That is, something of the form
#define NAME # define
happens to be illegal! Also note that the # in this context does not turn the next word into a string: the quoting following a # only happens shen the # is immediately followed by a macro parameter name in a function-style macro.

__attribute__((format(printf, 1, 2))) for MSVC?

With GCC, I can specify __attribute__((format(printf, 1, 2))) , telling the compiler that this function takes vararg parameters that are printf format specifiers.
This is very helpful in the cases where I wrap e.g. the vsprintf function family. I can have
extern void log_error(const char *format, ...) __attribute__((format(printf, 1, 2)));
And whenever I call this function, gcc will check that the types and number of arguments conform to the given format specifiers as it would for printf, and issue a warning if not.
Does the Microsoft C/C++ compiler have anything similar ?
Using SAL Annotations you can use _Printf_format_string_ (as of VS2k8 or VS2k10) or __format_string (for VS2k5):
#undef FORMAT_STRING
#if _MSC_VER >= 1400
# include <sal.h>
# if _MSC_VER > 1400
# define FORMAT_STRING(p) _Printf_format_string_ p
# else
# define FORMAT_STRING(p) __format_string p
# endif /* FORMAT_STRING */
#else
# define FORMAT_STRING(p) p
#endif /* _MSC_VER */
/* use /analyze or _USE_ATTRIBUTES_FOR_SAL for checking */
extern void log_error(FORMAT_STRING(const char* format), ...);
As previously mentioned by #RustyX printf format checking is now supported by default as of VC2015. That is without a /analyze static analysis pass. Regrettably there is not yet a mechanism for marking user-defined wrapper functions.
This suggest the obvious workaround of calling printf. That is defining a macro which invokes both the user-defined function as well as the printf itself. The latter on a dead path to be optimized out.
This has the added benefit of achieving some level of portability to other compilers.
int printf_wrapper_(const char *format, ...);
#define printf_wrapper(...) \
(printf || printf(__VA_ARGS__), printf_wrapper_(__VA_ARGS__))
The drawback is that VC2015 performs some rudimentary dead-code elimination prior to the format check, testing only the remaining live code.
Thus sizeof or constant conditional expressions will fail. As a rule of thumb if a debug build emits run-time code then you will get the warning, though later passes in release builds may still kill the call.
Alas this makes it something of a moving target liable to change in future compiler versions. Albeit a relatively benign one.
While GCC checks format specifiers when -Wformat is enabled, VC++ has no such checking, even for standard functions so there is no equivalent to this __attribute__ because there is no equivalent to -Wformat.
I think Microsoft's emphasis on C++ (evidenced by maintaining ISO compliance for C++ while only supporting C89) may be in part the reason why VC++ does not have format specifier checking; in C++ using <iostream> format specifiers are unnecessary.
There is an interesting article on the subject on Code Project:
"Using C++ Templates for Startup Validation"
by Alexander Gorobets
http://www.codeproject.com/KB/cpp/ValidateprintfFunction.aspx
I've modified it so that I have a macro PRINTF_VALIDATE(format, ...) that logs all format errors at program statup (there's no need to actually execute the code). It produces something like this:
test.cpp(147) : error : 'printf' format character 'f' at position 1 does not match parameter type INT
test.cpp(147) : error : 'printf' too many arguments (3 instead of 2)
One can use it for example like this:
#define LOG(fmt, ...) do { PRINTF_VALIDATE(fmt, __VA_ARGS__); WriteLog(fmt, __VA_ARGS__); } while(0)
This is not as useful as compiler support, but it works on Visual Studio 2005...
Workaround for MSVS, GCC and clang:
"If you’re using a macro to call your printf-like functions, you can use a helper-macro to get compile time format checks like this:
#define CHECK_FORMAT(...) \
do { \
char const dummy = sizeof(printf(__VA_ARGS__)); \
(void)dummy; \
} while (false)
#define MY_FMT(...) \
do { \
CHECK_FORMAT(__VA_ARGS__); \
MyFormatFunc(__FILE__, __LINE__, __VA_ARGS__); \
} while (false)
https://godbolt.org/z/38PaG5fx6
The printf call in the sizeof isn’t evaluated so it doesn’t generate code, but current versions of MSVC, GCC and Clang will still do the format-string check so you get the warning. The local dummy variable is also optimized away with -O2."
Source