I have a function I will need to leave partially implemented for a variety of reasons and I want to prevent future users (read as me in the future when I have forgotten that I did this) to know the function is incomplete, buggy and untested.
Option n1 is merely adding a comment // Warning this thing is partially implemented and will break randomly
This however won't create compile time warnings so, I am not a fan.
Option n2 is to use [[deprecated("reason")]] which has the advantage of raising compile warnings but its misleading, the function wasn't deprecated it's actually the opposite of deprecation, it's a WIP and will perhaps one day be fully implemented.
Are there alternatives?
The [[deprecated]] attribute is exactly what this is for (emphasis mine) :
https://en.cppreference.com/w/cpp/language/attributes
[deprecated]
[deprecated("reason")]
indicates that the use of the name or entity declared with this attribute is allowed, but discouraged for some reason
You can still use the function, you just get a warning message that you shouldn't rely on its use.
Caveat: MSVC breaks the standard and emits a compiler error (due to SDL flag being turned on by default) instead of a warning.
The only thing in standard C++ for this is the [[deprecated("message")]] attribute.
GNU has a non-standard Function Attribute for warning messages:
warning ("message")
If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, a warning which will include message will be diagnosed. This is useful for compile time checking, especially together with __builtin_constant_p and inline functions. While it is possible to define the function with a message in .gnu.warning* section, when using this attribute the problem will be diagnosed earlier and with exact location of the call even in presence of inline functions or when not emitting debugging information.
Related
How can I force the inlining of a function, but define it in a C++ file ?
This is a question that's been asked in the past, for example here: Moving inline methods from a header file to a .cpp files
The answers there, in short, go as follows: "inline used to mean [remove function call overhead at the expense of .text size], now it means [relax ODR], so don't use inline for anything that's not ODR related, the compiler knows better".
I'm aware of that, however in my somewhat exotic case, I don't care about performance.
I'm programming an embedded device and, should someone break through the other layers of security, I want to make it as obnoxious as possible to reverse engineer this part of the code, and one thing this implies is that I don't want function calls (that aren't called numerous times anyway) to expose the function boundaries, which are natural delimitations of pieces of code that achieve something on their own.
However, I would also like to keep my code orderly and not have code in my header files.
I see that I can use __attribute((force_inline)) to force inlining, but then I get warnings if those functions don't have an inline attribute too: warning: always_inline function might not be inlinable [-Wattributes]
Suppressing the attributes warning is an option, but I'd rather only take it once I'm sure there are no clean way to do this.
Hence the question: how can I have a forcibly inlined function whose declaration is in a header, but definition is in a source file, without suppressing all attributes warnings ? Is that impossible ?
Inlining can only be asked. Sometimes a bit forcefully. But you can never guarantee that the function WILL be inlined finally - because reasons, sometimes quite obscure ones.
Here what's MSVC documentation says (I've highlighted the important parts):
The compiler treats the inline expansion options and keywords as suggestions. There's no guarantee that functions will be inlined. You can't force the compiler to inline a particular function, even with the __forceinline keyword. When compiling with /clr, the compiler won't inline a function if there are security attributes applied to the function.
C++ standard says:
No matter how you designate a function as inline, it is a request that the compiler is allowed to ignore: the compiler might inline-expand some, all, or none of the places where you call a function designated as inline.
GCC documentation is a bit less crystal-clear about non-inlinable functions, but cases exists anyway.
The only "real" way to force inlining is quite ugly, since it rely on inlining it before compilation... Yeah, old-style preprocessor macros. The Evil Itself. Or by using a dirty hack with a #include replacing the function call (and inserting C++ code instead)... It may be a bit safer than a macro, regarding double evaluations, but other side-effects can be even worse since it must rely on "global" variables to work.
Does it worth the pain? Probably not. In particular for "obfuscation", because it won't be as "secure" as you think it will be. Yes, an explicit function call is easier to trace. But it won't change anything: reverse engineering don't rely on that to be done. In fact, obfuscation is near never a good (or even working...) solution. I used to think that... a long, very long time ago. I proved to myself that it was near useless. On my own "secured" code. Breaking the code took me much less time than it took me to "protect" it...
Reading this blog post and its comments, I have noticed that it gives as an example the possibility of marking specific function parameters as deprecated, as in (exaple taken from the post):
// Deprecate a function parameter
int triple([[deprecated]] int x);
Now I was wondering, what is a good use case for such a feature? No one in the comments of that post or anywhere else I have searched seem to have a clue.
EDIT:
To see it in action, there is a compilable example on goldbolt
Say you had a function like this:
void* allocate(std::size_t sz, void* hint = nullptr) {
// if you give `hint` it *might* be more efficient
}
And then you decided that it is no longer worth the effort to do stuff based on hint. So you would do this:
void* allocate(std::size_t sz, [[deprecated]] void* hint = nullptr) {
// `hint` is ignored. The compiler warns me if I use it in the
// function body accidentally, and people reading the function
// signature can see that it is probably going to be ignored.
}
This allows the library to keep the same signature/ABI (So you don't need to recompile stuff that uses it and legacy code can still keep using it without doing any harm), and also prevents it from accidentally being used again when changing the function.
But this is mostly for developers of the function, not the users of the function, in the future so they know why a seemingly "useless" parameter is there.
I would also think that this would disable the "unused parameter" warning with the -Werror=unused-parameter flag in gcc/clang, but it doesn't. Using (void) deprecated_parameter also issues a warning about using a deprecated parameter, so this seems like a bug. If it did disable the unused param warning, that would be another use case for [[deprecated]].
The rule is that the attribute is valid on, amongst other things, variable declarations (broadly). It's not specifically permitted for such declarations found in function arguments.
The original proposal, N3394, doesn't mention such a use case, either, and neither does the documentation for the original feature in GCC (which regardless accepts the equivalent usage) or in VS (I didn't check Clang).
As such, I think it's an "accident" that this is permitted, not something that anyone really had in mind as being useful.
Could it be useful to document deprecated defaulted arguments, as Artyer explores? Yes, potentially, and vaguely. But as Artyer also found, mainstream compilers don't actually react to this usage in a helpful manner.
So, at the present time, it's not useful, and the language feature wasn't particularly designed to be useful in this case.
Imagine a library that is implemented, used and maintained for many years. This library is used in multiple projects.
If you would simply remove the parameter, all the projects would have to immediately adapt the source code to be able to compile again, after they upgraded to the new library version.
If a default value is added to the parameter, but the parameter not used anymore, the projects would still compile without any change, but nobody would note that something has changed at all, and maybe some behaviour/feature that was controlled by this parameter does not work anymore.
So, by marking the parameter as deprecated the projects can compile without a change, but they get a warning that something has changed and that they should change their source code, because sooner or later this parameter will disappear.
Could C++ standards gurus please enlighten me:
Since which C++ standard version has this statement failed because (v) seems to be equivalent to (*&v)?
I.e. for example the code:
#define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
...{...
register int v=1;
int r = DEC(v) ;
...}...
This now produces warnings under -std=c++17 like:
cannot take address of register variable
left hand side of operand must be lvalue
Many C macros enclose ALL macro parameters in parentheses, of which the above is meant only to be a representative example.
The actual macros that produce warnings are for instance
the RTA_* macros in /usr/include/linux/rtnetlink.h.
Short of not using/redefining these macros in C++, is there any workaround?
If you look at the revision summary of the latest C++1z draft, you'd see this in [diff.cpp14.dcl.dcl]
[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future
revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register
storage-class-specifier is ill-formed in this International Standard.
The specifier can simply be removed to retain the original meaning.
The warning may be due to that.
register is no longer a storage class specifier, you should remove it. Compilers may not be issuing the right error or warnings but your code should not have register to begin with
The following is a quote from the standard informing people about what they should do with regards to register in their code (relevant part emphasized), you probably have an old version of that file
C.1.6 Clause 10: declarations [diff.dcl]
Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Common.
Your worry is unwarranted since the file in question does not actually contain the register keyword:
grep "register" /usr/include/linux/rtnetlink.h
outputs nothing. Either way, you shouldn't be receiving the warning since:
System headers don't emit warnings by default, at least in GCC
It isn't wise to try to compile a file that belongs to a systems project like the linux kernel in C++ mode, as there may be subtle and nasty breaking changes
Just include the file normally or link the C code to your C++ binary. Report a bug if you really are getting a warning that should normally be suppressed to your compiler vendor.
Now "static_assert" is a keyword in C++0x I thought it would be logical to replace the C "assert" macro with an "assert" keyword too.
static_assert is interpreted at compile time so it has to be a keyword so the compiler can process it.
assert doesn't need to be a keyword, and it doesn't make much sense to make it one, since there are many ways a program might want to respond to assertion success or failure. Therefore, it makes more sense to implement it in a library, and it is typically implemented as a macro.
assert has no compile time meaning, except during Pre-processing. The preprocessor has no knowledge of the C++ language, so a keyword makes no sense.
By contrast, static_assert is evaluated at compile time. Making it a keyword makes more sense in that regard. The compiler cares about it's existence.
There are also historic reasons; it was not a keyword in C, and making it one in C++ would have rendered existing assert macros result in undefined behavior.
Basically, because it doesn't need it. Existing assertion mechanisms for run-time assertions are perfectly good and don't require language support.
The other answers give some possible answers to your question, but a recent proposal indicates that assert may indeed become a keyword in C++17: https://isocpp.org/files/papers/N4154.pdf
assert can be implemented in a library, static_assert cannot. So static_assert gets a keyword because it needs language support, and assert doesn't.
This can not be done for compatibility with the code already written in c which has assert as a variable name. And hence as oli mentioned we won't be able to compile as assert is no longer macro
In C++0x (from here):
In C++0x, static assertions can be declared to detect and diagnose common usage errors at compile time.
this is static_assert syntax:
>>-static_assert--(--constant-expression--,--string-literal----->
where constant-expression must be contextually converted to bool. If it converts to false, then the compiler will emit an error according the string-literal.
So, this is basically an extension of the language that needs a keyword. It is not a runtime mechanism.
Again from the document linked above:
The addition of static assertions to the C++ language has the following benefits:
Libraries can detect common usage errors at compile time.
Implementations of the C++ Standard Library can detect and diagnose common usage errors, improving usability.
You can use a static_assert declaration to check important program invariants at compile time.
I'm getting this warning on a stack variable:
warning: object.member may be used uninitialized in this function
In this case I do not wish to force initialization to just to get rid of the warning as it consumes CPU cycles. The variable is a POD structure so a memset on it is not zero cost. I can verify that the variable is never used uninitialized, so I'd just like to suppress the warning for it.
In general I do want the warning, just not on this particular variable in this particular scenario. How can I suppress the warning?
Looks like the pragma diagnostics are the correct way to go but they require quite a recent version of GCC (4.6)
No acceptable solution prior that version is known.
Try doing this:
#pragma GCC diagnostic ignored "-Wuninitialized"
foo(b); /* no diagnostic for this one */
This pragma comes in three interesting and helpful flavors : warning, error, ignored. See 6.56.10 Diagnostic Pragmas for their usages. The link says,
GCC allows the user to selectively
enable or disable certain types of
diagnostics, and change the kind of
the diagnostic. For example, a
project's policy might require that
all sources compile with -Werror but
certain files might have exceptions
allowing specific types of warnings.
Or, a project might selectively enable
diagnostics and treat them as errors
depending on which preprocessor macros
are defined.
The accepted answer has two big problems that requires more than a comment.
First, it deactivates the warning for the whole file. If that pragma resides in a header, probably for more. Warnings are useful and if it is indeed a false positive, one should disable the warning for a bunch of code as small as possible.
Then the warning in the OP is "maybe uninitialized" which is deactivated by -Wmaybe-uninitialized, as opposed to -Wuninitialized.
#pragma GCC diagnostic push // save the actual diag context
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // disable maybe warnings
function() or int variable; // impacted section of code
#pragma GCC diagnostic pop // restore previous diag context
GCC differentiates between uninitalised and self initalized, e.g. compiling:
int main() {
int i = i;
return i;
}
With gcc -Wall -Wextra gives no warnings, unless you explicitly added -Winit-self as well, yet it gets completely optimized out by my quick testing.
#Nawaz has answered the question as specifically asked, but have you considered that the fact that you need this may indicate you're declaring your struct too early/at a less nested scope than appropriate? It would generally be much preferred if you could declare your struct at a point where you can actually initialize it rather than declaring it earlier and filling it in various locations.
Also, even though you can verify that it's never used uninitialized right now, what if someone else adds a new code path in the future and it's not initialized properly? If you disable the warning then it'll silently compile and probably break in an unexpected way. Unless you can prove that the initialization is taking a measurable amount of your program's CPU it's probably better to just do the initialization up front.
Selectively disable GCC warnings for only part of a translation unit?