I have a macro in my C++ code, macro has an unused variable. I am getting warning for that variable
the macro is to print the class and method name
#define LOG_ENTER(func_name, message) \
LOG_SET_METHOD(#func_name) \
LOG_MOD_INTERNAL(TC_TAG(ENTER) << message)
#define LOG_SET_METHOD(name) static const char LOG__METHOD__[] = "::" name "() ";
We are using gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC).
"warning: unused variable "LOG__METHOD__" "
How to suppress this warning? It causing more noise!!
The usual way of silencing this warning is to use the variable in a dummy expression :
int main() {
int i;
i;
}
However, this triggers "Warning : statement has no effect", because i has no side effect and its value is not used. To silence this one, we explicitly ignore the value :
int main() {
int i;
(void)i;
}
And there goes the warning.
A way to disable warning:
template <typename T>
void UnusedVar(const T&) {}
And then use:
UnusedVar(my_var);
Casting to void is also a common way (but doesn't work for all compiler):
(void) my_var; // or static_cast<void>(my_var)
Related
Which of the following C++ lambdas/statements are supposed to work according to the latest C++ specification?
Context in case this is relevant: see here.
I tested the following code snippets with -std=c++17 on Fedora 33 with clang 11.0.0 and gcc 10.2.1.
Update: Replace __PRETTY_FUNCTION__ with __func__ for standard compliance. The same behavior can be observed.
Update2: Example using const char * s = __func__ as default argument to verify that it should be valid within a function scope (thanks to #BenVoigt).
1. LLVM __func__ within lambda default argument
void clang() {
[](const char* c = __func__) {std::cout << c << std::endl;}();
}
Expected behavior (CLANG):
Print out clang\n (void clang() for __PRETTY_FUNCTION__)
Observed behavior (CLANG):
Compiler warning: warning: predefined identifier is only valid inside function [-Wpredefined-identifier-outside-function]
Print out \n (top level() for __PRETTY_FUNCTION__)
2. GCC ignores statements
template <typename L>
constexpr std::string_view methodName(L l) { return l(); }
#define __METHOD_NAME__ (\
__func__, /* needed for pointer to work */ \
methodName([](const char* c = __func__) {return std::string_view(c);}) \
)
void gcc1() {
std::cout << [](const char* c = __func__) { return c; }() << std::endl; // GCC: This statement doesn't do anything
std::cout << [](const char* c = __func__) { return c; }("gcc") << std::endl;
std::cout << __METHOD_NAME__ << std::endl; // GCC: This statement somehow conflicts with the statements above
}
void gcc2() {
std::cout << __METHOD_NAME__ << std::endl; // GCC: This statement itself works
}
Expected output (GCC):
gcc1
gcc
gcc1
gcc2
Observed output (GCC):
gcc
gcc2
3. GCC Compile error
void gcc3() {
std::string_view s = [](const char* c = __func__) { return std::string_view(c); }();
std::cout << s << std::endl;
}
Expected behavior (GCC): Compiles without problems.
Observed behavior (GCC): error: internal compiler error: in finish_expr_stmt
[class.local] The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function. [Note: A declaration in a local class cannot odr-use (6.2) a local entity from an enclosing scope. — end note]
A lambda is a local class, and as such it cannot use variables from the enclosing scope (e.g. __func__) other than in its capture clause.
If I have
namespace foo {
inline int bar() {
return 1119;
}
}
__attribute__((deprecated)) inline int bar() {
return 138;
}
in header.h and
#include "header.h"
#include <iostream>
int main() {
int x = bar();
int y = foo::bar();
std::cout << x << std::endl;
std::cout << y << std::endl;
}
in source.cpp, then
g++ source.cpp -o deprecated-test
results in
source.cpp: In function ‘int main()’:
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
^~~
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
int x = bar();
^
In file included from source.cpp:1:
header.h:7:40: note: declared here
__attribute__((deprecated)) int bar() {
(on Ubuntu 18.10 with g++ 8.2.0).
Why does the deprecated warning print twice?
Heading off some suggestions that would be unhelpful:
[[deprecated]]:
I know with C++14 on you can use the [[deprecated]] attribute, but I need to work with C++11.
Declaration vs. definition: The docs seem to imply it should be used with function declaration rather than definition, but
I need to define the functions inline in a header rather than declare in the header and define in source files; and
Trying this approach didn't stop the warning from printing twice anyway.
As per the documentation of GCC 8.2.0:
The deprecated attribute results in a warning if the function is used anywhere
in the source file. This is useful when identifying functions that are expected
to be removed in a future version of a program. The warning also includes the
location of the declaration of the deprecated function, to enable users to easily
find further information about why the function is deprecated, or what they
should do instead. Note that the warnings only occurs for uses...
There should be only one warning and not two. So this is a bug in GCC.
There is a related bug for Type attributes (rather than Function attributes) titled: C/C++ __attribute__((deprecated)) does not appear to wrap declarations as implied from the doc.
It has been confirmed as a bug.
#include <iostream>
struct Index {
constexpr operator int() const { return 666; }
};
template <int i> void foo() {
std::cout << i << std::endl;
}
void wrapper(Index index) {
foo<index>();
}
int main() {
Index index;
// foo<index>(); // error: the value of ‘index’ is not usable in a constant expression
wrapper(index);
}
Hello, everyone.
I'm using a constexpr conversion of a variable "index" to an int value, which is substituted to a "foo" templated function.
If I directly call foo<index>() from "main", I get a compiler error.
If the same call is done from the "wrapper", then everything compiles and works fine.
What am I missing there?
Compile command: g++ -std=c++14 main.tex with g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6).
A very similar error was reported here. It was first reported with GCC 4.9.0
In the analysis provided:
This is a GCC bug. It appears to be some sort of confusion in the way GCC handles internal linkage non-type template parameters of pointer type.
It has since been resolved.
If I use clang 3.8.1 to compile:
extern "C" {
int foo(int x) { register int y = x; return y; }
}
int main() { return foo(123); }
I get the warning:
a.cpp:3:18: warning: 'register' storage class specifier is deprecated and incompatible with C++1z [-Wdeprecated-register]
int foo(int x) { register int y = x; return y; }
^~~~~~~~~
... which I really shouldn't be getting this, since the inner function is C code. If I use GCC 6.3.1, even with -Wall, I don't get this warning.
Is this a clang bug or am I doing something wrong?
extern "C" does not mean "compile this code as C". It means "make this function (or functions) callable from C code", which typically means changing name mangling and, sometimes, calling convention.
Perhaps the error has nothing to do with the extern "C"? It looks like it says, not, "register is incompatible with C" but rather "register is incompatible with C++1z". (I assume C++1x means C++11/14/17.)
Presently, I am using the following function template to suppress unused variable warnings:
template<typename T>
void
unused(T const &) {
/* Do nothing. */
}
However, when porting to cygwin from Linux, I am now getting compiler errors on g++ 3.4.4 (On linux I am 3.4.6, so maybe this is a bug fix?):
Write.cpp: In member function `void* Write::initReadWrite()':
Write.cpp:516: error: invalid initialization of reference of type 'const volatile bool&' from expression of type 'volatile bool'
../../src/common/Assert.h:27: error: in passing argument 1 of `void unused(const T&) [with T = volatile bool]'
make[1]: *** [ARCH.cygwin/release/Write.o] Error 1
The argument to unused is a member variable declared as:
volatile bool readWriteActivated;
Is this a compiler bug or a bug in my code?
Here is the minimal test case:
template<typename T>
void unused(T const &) { }
int main() {
volatile bool x = false;
unused(!x); // type of "!x" is bool
}
The actual way of indicating you don't actually use a parameter is not giving it a name:
int f(int a, float) {
return a*2;
}
will compile everywhere with all warnings turned on, without warning about the unused float. Even if the argument does have a name in the prototype (e.g. int f(int a, float f);), it still won't complain.
I'm not 100% sure that this is portable, but this is the idiom I've usually used for suppressing warnings about unused variables. The context here is a signal handler that is only used to catch SIGINT and SIGTERM, so if the function is ever called I know it's time for the program to exit.
volatile bool app_killed = false;
int signal_handler(int signum)
{
(void)signum; // this suppresses the warnings
app_killed = true;
}
I tend to dislike cluttering up the parameter list with __attribute__((unused)), since the cast-to-void trick works without resorting to macros for Visual C++.
It is a compiler bug and there are no known work arounds:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42655
It is fixed in v4.4.
In GCC, you can define a macro as follows:
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*#unused#*/ x
#else
# define UNUSED(x) x
#endif
Any parameters marked with this macro will suppress the unused warning GCC emits (and renames the parameter with a prefix of UNUSED_). For Visual Studio, you can suppress warnings with a #pragma directive.
The answer proposed by haavee (amended by ur) is the one I would normally use:
int f(int a, float /*epsilon*/) {
return a*2;
}
The real problem happens when the argument is sometimes but not always used in the method, e.g.:
int f(int a, float epsilon) {
#ifdef LOGGING_ENABLED
LOG("f: a = %d, epsilon = %f\n", a, epsilon);
#endif
return a*2;
}
Now, I can't comment out the parameter name epsilon because that will break my logging build (I don't want to insert another #ifdef in the argument list because that makes the code much harder to read).
So I think the best solution would be to use Tom's suggestion:
int f(int a, float epsilon) {
(void) epsilon; // suppress compiler warning for possibly unused arg
#ifdef LOGGING_ENABLED
LOG("f: a = %d, epsilon = %f\n", a, epsilon);
#endif
return a*2;
}
My only worry would be that some compilers might warn about the "(void) epsilon;" statement, e.g. "statement has no effect" warning or some such - I guess I'll just have to test on all the compilers I'm likely to use...