To get rid of a static code analysis warning (QA-C), I need to provide a function prototype for __builtin_expect().
I am using the WindRiver Diab compiler for PowerPC.
In the compiler manual I have found the following information:
__builtin_expect(long exp, long c): ... exp is also the return value.
So, my prototype is as follows:
long __builtin_expect(long exp, long c);
However, it does not compile, I am getting the following error:
error (dcc:1701): invalid types on prototype to intrinsic __builtin_expect - when the intrinsic is enabled, optional user prototype must match
It seems like my prototype is not correct. What is the correct prototype for __builtin_expect?
The error message states that the user prototype is optional. So it should be possible to define it, right?
You need to somehow define __builtin_expect to make your static analyzer happy, because it doesn't know what that function is. But you need to use #ifdef to disable that definition when you are compiling your program normally, because your compiler will not like it if you try to define compiler builtins yourself. The builtins come with the compiler so they are not supposed to be defined in your program.
Something like this would work:
#ifdef _HEY_I_AM_RUNNING_STATIC_ANALYZER
#define __builtin_expect(e,c) (e)
#endif
I don't know the details of how your static analyzer works, so I don't know what the right macro is to test in the #ifdef. You can read the documentation of your static analyzer to find out if it defines any preprocessor symbols by default, or if you can tell it what preprocessor symbols to define when you run it.
You should carefully read the documentation of Other Builtins in GCC.
As a first approximation, you might replace __builtin_expect by (invocation _builtin_expect_replacement of) the macro below:
#define _builtin_expect_replacement(Exp,C) (Exp)
For most static analyzers that should be enough
Don't expect most GCC builtins to be definable as functions.
Related
Someone knows what does this error mean?
My piece of code is shown below:
// test.c
inline void fun() {
typedef struct {
int i;
} S;
}
GCC could compile without an error while clang (clang 12.0.0) claims an error:
root:~/test # clang -c test.c
test.c:2:19: error: unsupported: anonymous type given name for linkage purposes by typedef declaration after its linkage was computed; add a tag name here to establish linkage prior to definition
typedef struct {
^
S
test.c:4:7: note: type is given name 'S' for linkage purposes by this typedef declaration
} S;
^
1 error generated.
According to the error text from clang, it looks like I need to add a tag name for the anonymous typedef. After adding a tag name, it won’t show an error. However, this piece of code from a team work program in my department so I need a strong reason to modify it. Someone knows what’s this error mean?
UPDATE: In the comments below someone mentioned, The code could compile but fail to link with GCC. Actually that because the GCC optimization is not turned on. Use -O2 to compile and link will pass.
I mentioned this in a comment, but I think I might be able to expand it to a proper answer. The problem here is in how the inline keyword works in C. Quite frankly, I don't know what the C standards committee was smoking when they came up with this ridiculous concept, and it's probably best not to know. Don't ask why the rules are this way: I don't know.
There is an important difference between extern inline and static inline functions, as well as ones declared simply inline.
inline functions may be defined in a header and included in multiple compilation units. This is because they aren't considered "real" definitions. No symbol for them is emitted, thus there is no multiple-definition error. However, the compiler is not required to actually inline the function call. It may instead try to call it. Since no symbol exists, there will be an error at link time. Never use inline functions in C. They make no sense at all.
extern inline functions provide the definition for an inline function. If the above case happens, and the compiler tries to call the function, so long as some file includes an extern inline definition, there won't be an error because it emits a symbol. This making sense? No? Good.
static inline functions are the only one that make any sense whatsoever. Because they're static and therefore local, no symbol need exist. If the compiler decides to inline it, it does. If not, it calls the function. No problems. Declare your function static inline and it will compile.
But that wasn't your question. Why is clang complaining about the struct? Why doesn't gcc complain? The answer is "idunnoman". Best guess is that clang is taking the rules very seriously, in which case because there is no "real" definition for fun, there is also no real definition for your anonymous struct, and therefore can't be typedef'd.
But that would also be the case if it were a named struct. And why does the linker care whether the structure has a name? Once again, I can only guess it has to do with the fact that there can be numerous definitions for an inline function, and clang wants the structure to have a constant name between them. But different compilation units can have different structures with the same name, so that doesn't make sense either.
Ugh. I thought I had an answer for you but now I'm even more confused than when I started. I'll still post this but it probably ought to be downvoted. Oh well.
I am using compiler related assembly language function asm() in my PIC32 MCU C code. My code is compiled and working fine with just using asm("reset") function in my C code.When checking MISRA compliance I am getting following MISRA error:
function 'asm' undeclared, assumed to return int [MISRA 2012 Rule 17.3, mandatory]asm("reset");
asm("reset");
How can I resolve this MISRA error for this assembly language function? I also tried creating function macro to use it but still getting an error.
function 'asm' undeclared, assumed to return int [MISRA 2012 Rule 17.3, mandatory]ASM_RESET(void);
#define ASM_RESET(void) asm("reset")
ASM_RESET(void);
It looks like PC-Lint isn't recognizing asm as a keyword. It is treating it as a function which has no prototype.
You could try adding +rw(asm) to the options.
On the other hand, this forum post suggests that the legal way is to define a reset function in standalone file that includes only assembly, and show the C file a prototype for it.
reset.c:
void reset(void) {
asm("reset");
}
test.c:
#include "reset.h"
...
reset();
asm is a compiler extension keyword, not a function. Being compiler specific, it is not automatically recognised by your static analysis tool,and your compiler's inline assembly syntax is "function-like", so it applies the function prototyping rule.
You need to configure PC-Lint correctly using a configuration file or command line options that describe the implementation defined behaviour of your compiler. That may include a great many options, but in this case you should use:
-dasm()=
which will cause the analyser to ignore inline assembly code with the function-like syntax asm(...)
Alternatively you can ignore the inline assembler syntax during static analysis by conditionally defining a macro that hides all such directives:
#if defined _lint
#define asm( asmstr )
#endif
This however would hide other deviations from the checker, such as rules about encapsulation and isolation of in-line assembly. For that reason you should not use a macro or inline assembly mixed with C code lines, but rather define a wrapper function:
void reset(void)
{
asm("reset");
}
and place the reset() function defined above in a separate translation unit and simply omit that source code from the analysis - as if it were library code.
I recently learned that there are parameter-type-lists which can be empty in C:
int print();
int main() {
print("hallo"); // << valid but highly unintuitive
}
int print() {
}
In this code someone might just have forgotten to write print(void) (maybe a C++ developer) but someone else provides a parameter. Compilation does not show any warnings or errors:
$ make test -Wstrict-prototypes -Wimplicit -Wimplicit-function-declaration -Wall
cc test.c -o test
I didn't find a compiler flag which warns about empty parameter-type-lists, only about implicit function declaration.
Is there something I can do which helps me finding all uses of parameter-type-lists in a given code base?
E.g.
letting a C++ compiler compile the C code as C++ and solve type issues (C++ does not allow arguments if the declaration does not list them)
let the compiler list all function declarations (don't know if possible) and searching manually for empty braces
greping for parameter-type-lists (too complex for me :))
disabling parameter-type-lists via compiler switch (didn't find any)
With gcc, using -Wstrict-prototypes will achieve what you expect:
-Wstrict-prototypes (C and Objective-C only)
Warn if a function is declared or defined without specifying the argument types. (An old-style function definition is permitted without a warning if preceded by a declaration that specifies the argument types.)
With your example, it gives:
hallo.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
int print() {
^
However, you'll have to ensure that all non-strict function declarations in your existing code gets properly defined; in particular, functions without parameters should be declared with (void), like this:
int print(void);
Your example is not valid, neither in C nor in C++. Since your print() function does not accept any parameters -- which is well established from the function definition you provide (C2011, 6.7.6.3/14) -- it is non-conforming to call it with an argument, regardless of whether a prototype is visible at the point of the call (C2011, 6.5.2.2/6). If the call appears in a scope wherein neither the function definition nor any bona fide prototype is visible then the compiler might nevertheless accept the code, but that does not make it valid or guarantee that it will work.
Additionally, you seem to be using the wrong term, or possibly your idea is very wrong-headed. Parameter-type-lists are the modern way of declaring (and defining) functions, including function prototypes:
int my_func(int a, char *b);
// ^^^^^^^^^^^^^^----- parameter-type-list
You should not get rid of those, but I think you mean that you want to identify and fix K&R-style function definitions and also function declarations without parameter-type-lists. (The formal syntax's terms for the K&R style are "identifier list" and, if needed, an accompanying "declaration list".)
As for identifying the occurrences of K&R-style declarations automatically, that's a job for a C language parser, and the most common implementations of those are C compilers. Your compiler may have an option for just what you want. GCC, for example, has options -Wstrict-prototypes and -Wold-style-defintion, which, together, will signal both function declarations that are not prototypes and K&R-style function definitions. GCC has some other options that might be of interest to you too, such as -Wimplicit, -Wtraditional, and -Wc++-compat.
All you need to look for is () (with optional whitespace), followed by { (with optional whitespace, perhaps newline). And you can replace it with (void).
If you want an "industrial grade" solution you can use a compiler which emits something easier to parse, such as GCC-XML or Clang.
I recently got a snippet of code in Linux kernel:
static int
fb_mmap(struct file *file, struct vm_area_struct * vma)
__acquires(&info->lock)
__releases(&info->lock)
{
...
}
What confused me is the two __functions following static int fb_mmap() right before "{",
a).What is the purpose of the two __funtions?
b).Why in that position?
c).Why do they have the prefix "__"?
d).Are there other examples similar to this?
Not everything ending with a pair of parenthesis is a function (call). In this case they are parameterized macro expansions. The macros are defined as
#define __acquires(x) __attribute__((context(x,0,1)))
#define __releases(x) __attribute__((context(x,1,0)))
in file include/linux/compiler.h in the kernel build tree.
The purpose of those macros expanding into attribute definitions is to annotate the function symbols with information about which locking structures the function will acquire (i.e. lock) and release (i.e. unlock). The purpose of those in particular is debugging locking mechanisms (the Linux kernel contains some code that allows it to detect potential deadlock situations and report on this).
https://en.wikipedia.org/wiki/Sparse
__attribute__ is a keyword specific to the GCC compiler, that allows to assign, well, attributes to a given symbol
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#Function-Attributes
Since macros are expanded at the text level, before the compiler is even looking at it, the result for your particular snippet, that the actual compilers sees would be
static int
fb_mmap(struct file *file, struct vm_area_struct * vma)
__attribute__((context(&info->lock,0,1)))
__attribute__((context(&info->lock,1,0)))
{
…
}
Those macros start with a double underscore __ to indicate, that they are part of the compiler environment. All identifiers starting with one or two underscores are reserved for the compiler environment implementation. In the case of the Linux kernel, because Linux is a operating system kernel that does not (because it simply is not availible) use the standard library, it's natural for it, do define it's own compiler environment definitions, private to it. Hence the two underscores to indicate, that this is compiler environment/implementation specific stuff.
They're probably macros defined with #define. You should look for the definition of such macros and see what they expand to. They might expand to some pragma giving hints to the compiler; they might expand to nothing giving hints to the developers or some analysis tool. The meaning might vary
The __attribute__ these macros evaluate to are compiler-specific features. man gcc explains some of the uses.
The prefix __ typically is used to avoid name clashes; double underscore as prefix and postfix mark an identifier as being used by the compiler itself.
More on gcc attributes can be found here.
More on the kernel use of these can be found here.
Those are macro's defined as
# define __acquires(x) __attribute__((context(x,0,1)))
# define __releases(x) __attribute__((context(x,1,0)))
in Linux/include/linux/compiler.h
I have C code with lots of calls strcmp and strcpy that is causing all kinds of problems.
I want to migrate this to strncmp and strncpy but I can not update all the code right now. I want to add compiler warning where ever the functions is used.
The following forces the substitution #define strcmp(x,y) strncmp16(x,y,64) but the problem is still in the code.
Is there a way to add an #warning so that the code still compile but will give a warning for not using the sized functions.
It is a large code base and must compile in four different compilers (GCC, IAR, GHS and VC). It is our own C Library mainly used in embedded systems.
Edit: I am not looking to find all occurrences. There is thousands of tools that can be used to find and replace them. I want there to be a warning so the next time somebody looks at the code they would evaluate and fix the code.
Edit: Strncmp & strncpy have lots of issues and I am very aware of that. I am making an informed decision. These function is in our own C library not just the default functions from the compilers C library.
While you can use #define to force errors, there is no mechanism in the C99 standard (and probably none in C11 either) to force a warning.
If you are using gcc, you can use
__attribute_deprecated__
to mark a prototype as deprecated, e.g.:
int strcmp(const char *, const char *) __attribute_deprecated__;
For Visual Studio:
prefix the function prototype with __declspec(deprecated) as seen in MSDN
You'll need to raise the warning level to 3+.
Example:
#pragma deprecated(strcpy, strcmp)
This line will cause every call to either function to omit a C4995 warning.
These specific functions already emit a C4996 warning but you turn that warning off via a pragma:
#pragma warning(disable: 4996)