Lintering warning whereas compilation is ok - makefile

I have some variables defined in makefile.init:
MY_VARIABLE = some_value
In the preprocessor settings I have this -D switch:
-DUSE_MY_VAR=\"$(MY_VARIABLE)\"
And in a source file, I have this:
static const char* my_val = USE_MY_VAR;
So this my_val will get the value set in the makefile.init file.
It compiles just fine, but the indexer complains with a warning "Bad character sequence encountered: \". Is there a way to make it understand it or maybe make it ignore this specific variable?

Ok finally found something that make both compiler and indexer happy:
my -D switch becomes (removed the escaped quotes):
-DUSE_MY_VAR=$(MY_VARIABLE)
and in the source code (thanks to Expand macro inside string literal):
#define STRINGIFY2(X) #X
#define STRINGIFY(X) STRINGIFY2(X)
static const char* my_val = STRINGIFY(USE_MY_VAR);

Related

Want to define list of macros with same prefix

I have a bunch of macros to define with same prefix and I don't want to define them one by one.
Say, I want to define like:
static constexpr str_1 = "str_1";
static constexpr str_2 = "str_2";
....
static constexpr str_100 = "str_100";
I tried:
#define DECLARE_STR(variable_prefix, val_prefix, cur, max) do { \
if ((cur) < (max)) { \
static constexpr variable_prefix##cur = val_prefix#cur; \
DECLARE_STR(variable_prefix, val_prefix, cur+1 , max) \
} while(0)
But got errors: error: expected member name or ';' after declaration specifiers
Do I have a correct way to implement this?
There are two problems with your code.
First, the do/while(0) construct is useful to ensure that macros expand to a single statement. What you want to generate are variable definitions at the global namespace, for which statements are unsuited: just remove the do/while(0). The if won't be able to do anything about declaring variables either, it can only branch at runtime on values. But in any case...
The other issue is that you're trying to call the macro recursively. The C++ preprocessor is not able to perform such recursion: a macro cannot be expanded within its own expansion. Working around that requires a lot of boilerplate to generate iteration sequences up to a limit. Fortunately(?), Boost.Preprocessor has the boilerplate already done:
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/stringize.hpp>
#define DECLARE_ONE_STR(z, n, data) \
static constexpr BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(0, data), n) = BOOST_PP_TUPLE_ELEM(1, data) BOOST_PP_STRINGIZE(n);
#define DECLARE_STR(variable_prefix, val_prefix, max) \
BOOST_PP_REPEAT(max, DECLARE_ONE_STR, (variable_prefix, val_prefix))
See it live on Coliru

Macro expansion issue with gcc

In gcc, it appears that referencing the results of a macro expansion later inside that same expansion doesn't work. For example:
#define TESTMACRO(name) \
static int name##_func(int solNo) { \
return (solNo); \
}\
static int name##Thing = {0,##name##_func},NULL,{"", capInvSw##name}};
TESTMACRO(stuff)
This results in errors like this:
test.c:7:29: error: pasting "," and "stuff" does not give a valid preprocessing token
static int name##Thing = {0,##name##_func},NULL,{"", capInvSw##name`}};
^
test.c:9:1: note: in expansion of macro ‘TESTMACRO’
TESTMACRO(stuff)
I would expect to have a function called stuff_func created and passed into stuffThing. I believe that this works in other compilers. What is the equivalent way to do this in gcc?
You can try to run only the pre-processor on your code by passing the -E flag:
gcc -E foo.c
Which evaluates your macro to:
static int stuff_func(int solNo) { return (solNo); } static int stuffThing = {0,stuff_func},NULL,{"", capInvSwstuff`}};
That can be expanded for readability to:
static int stuff_func(int solNo) {
return (solNo);
}
static int stuffThing = {0,stuff_func},NULL,{"", capInvSwstuff`}};
And it appears that you have one extra/missing brackets } in your expanded macro.
Hope it helps.

Macro substitution in #include directive

I would like to use an #include directive with a file name that is passed as an externally defined macro.
E.g.
#include #FILE".h"
where FILE would be defined as the string MyFile (without quotes), resulting in
#include "MyFile.h"
The stringizing operator # cannot be used here as the symbol FILE is not a macro argument. I have tried other approaches, to no avail.
Do you see a solution ?
String literal concatenation happens two translation phases after #include-directives are resolved; your approach cannot work. Instead, try something along the lines of
#define STRINGIZE_(a) #a
#define STRINGIZE(a) STRINGIZE_(a)
#define MYFILE stdio
#include STRINGIZE(MYFILE.h)
int main() {
printf("asdf");
}
Demo.

GCC - display preprocessed value during preprocessing

Is there a way to make GCC display the value of some preprocessed value during preprocessing? In particular, if I run the equivalent of:
gcc input.c -E >/dev/null
Is there a way to obtain the actual value of an expanded macro? Consider this example:
#if defined(A)
#define B bar
#else
#define B foo
#endif
#define XSTR(x) STR(x)
#define STR(x) #x
int main() {
#pragma message "B is " XSTR(B)
#error DIE
B a = 2;
return 0;
}
I would like to find out that B is foo in this case.
In my actual setup, I do not have access to the entirely preprocessed file, and I cannot remove the -E flag.
Rationale: I have a complex file setup with lots of syntax errors due to incorrectly defined macros, and the fastest way to debug it would be to use this #pragma/#error combination to find out the actual value, stop compilation, manually fix it, and run GCC again to find out where the next error will occur.

GCC: Customizing printf for string output

GCC allows customization of printf specifiers. However, I don't see how I can "teach" it to accept my string class for %s specifier. My string class is a simple wrapper over char pointer and has exactly one member variable (char * data) and no virtual functions. So, it's kind of ok to pass it as-is to printf-like functions in place of regular char *. The problem is that on gcc static analyzer prevents me from doing so and I have to explicitly cast it to const char * to avoid warnings or errors.
My cstring looks something like this:
class cstring
{
cstring() : data(NULL){}
cstring(const char * str) : data(strdup(str)){}
cstring(const cstring & str) : data(strdup(str.data)){}
~cstring()
{
free(data);
}
...
const char * c_str() const
{
return data;
}
private:
char * data;
};
Example code that uses cstring:
cstring str("my string");
printf("str: '%s'", str);
On GCC I get this error:
error: cannot pass objects of non-trivially-copyable type 'class cstring' through '...'
error: format '%s' expects argument of type 'char*', but argument 1 has type 'cstring' [-Werror=format]
cc1plus.exe: all warnings being treated as errors
The C++ standard doesn't require compilers to support this sort of code, and not all versions of gcc support it. (https://gcc.gnu.org/onlinedocs/gcc/Conditionally-supported-behavior.html suggests that gcc-6.0 does, at least - an open question whether it will work with classes such as the one here.)
The relevant section in the C++11 standard is 5.2.2 section 7:
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg ...
Passing a potentially-evaluated argument of class type (Clause 9)
having a non-trivial copy constructor, a non-trivial move constructor,
or a non-trivial destructor, with no corresponding parameter, is
conditionally-supported with implementation-defined semantics.
(But look on the bright side: if you get into the habit of using c_str, then at least you won't get tripped up when/if you use std::string.)

Resources