Clang: Do not optimize a specific function - c

For a long time i used gcc to compile C code. Sometimes i had to use the optimize("O0") attribute to disable optimizations for a specific function. Now i like to do this with clang.
Assume the following code:
#include <stdio.h>
void __attribute__((optimize("O0"))) blabla(void) {
}
int main(void) {
blabla();
return 0;
}
If i compile it with clang i get this error:
test2.c:3:21: warning: unknown attribute 'optimize' ignored [-Wattributes]
void __attribute__((optimize("O0"))) blabla(void) {
^
1 warning generated.
Then i used google (and also) stackoverflow to find out what attribute is required for clang, because many of them are not in the standard (as soon as i know).
I found this thread:
In clang, how do you use per-function optimization attributes?
If i try the attribute optimize("0") i get this error:
test2.c:3:21: warning: unknown attribute 'optimize' ignored [-Wattributes]
void __attribute__((optimize("0"))) blabla(void) {
^
1 warning generated.
And if i try the attribute optnone i get this error:
test2.c:3:21: warning: unknown attribute 'optnone' ignored [-Wattributes]
void __attribute__((optnone)) blabla(void) {
^
1 warning generated.
I also tried to move the attribute after the function name, but it doesn't work (for some reason there is a warning about GCC?!):
test2.c:3:34: warning: GCC does not allow optnone attribute in this position on a function definition [-Wgcc-compat]
void blabla(void) __attribute__((optnone)) {
^
test2.c:3:34: warning: unknown attribute 'optnone' ignored [-Wattributes]
2 warnings generated.
Another test with the following code:
#include <stdio.h>
[[clang::optnone]]
void blabla(void) {
}
int main(void) {
blabla();
return 0;
}
It produces:
user#ubuntu:/tmp/optxx$ clang test2.c
test2.c:3:1: error: expected identifier or '('
[[clang::optnone]]
^
test2.c:3:2: error: expected expression
[[clang::optnone]]
^
test2.c:8:5: warning: implicit declaration of function 'blabla' is invalid in C99 [-Wimplicit-function-declaration]
blabla();
^
1 warning and 2 errors generated.
Probably i do something wrong, but i cannot see what.
-edit-
clang version:
user#ubuntu:/tmp/optxx$ clang -v
Ubuntu clang version 3.3-16ubuntu1 (branches/release_33) (based on LLVM 3.3)
Target: x86_64-pc-linux-gnu
Thread model: posix

Try the following, clang-style attribute specification:
[[clang::optnone]]
void blabla(void);
EDIT: Clang 3.3 is pretty outdated. Use a more recent version, and your original ((optnone)) code will work.

Related

How to force Werror=declaration-after-statement with -std=c99 in clang

I would like to have compiler throw an error every time there is a declaration after statement because that is the coding style I want to enforce, but I also want to compile with -std=c99 since I use some of the specific c99 features.
The problem is that in c99 declarations are allowed anywhere in the code, not just at the beginning of a block.
Take a look at the following program:
// prog.c
#include <stdio.h>
int main(void)
{
printf("hello world\n");
int i = 0;
return 0;
}
If I compile this code with gcc like this:
gcc -std=c99 -Werror=declaration-after-statement prog.c
it throws the following error:
prog.c: In function ‘main’:
prog.c:6:9: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
6 | int i = 0;
| ^~~
cc1: some warnings being treated as errors
This is the behavior I would like to have when compiling with clang, but clang behaves differently.
If I compile the same code with clang like this:
clang -std=c99 -Werror=declaration-after-statement prog.c
it throws no errors.
Only if I compile the code with clang like this it throws the error I want:
clang -std=c90 -Werror=declaration-after-statement prog.c
prog.c:6:6: error: ISO C90 forbids mixing declarations and code [-Werror,-Wdeclaration-after-statement]
int i = 0;
^
1 error generated.
But this is not good for me because I need to use -std=c99.
Is it possible to force -Werror=declaration-after-statement along with -std=c99 when compiling with clang?
Looking at the source code of clang it seems like not supported.
The diagnostic is defined in clang/include/clang/Basic/DiagnosticSemaKind.td
def ext_mixed_decls_code : Extension<
"ISO C90 forbids mixing declarations and code">,
InGroup<DiagGroup<"declaration-after-statement">>;
And its only usage is in clang/lib/Sema/SemaStmt.cpp
StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr) {
const unsigned NumElts = Elts.size();
// If we're in C89 mode, check that we don't have any decls after stmts. If
// so, emit an extension diagnostic.
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {
// Note that __extension__ can be around a decl.
unsigned i = 0;
// Skip over all declarations.
for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i)
/*empty*/;
// We found the end of the list or a statement. Scan for another declstmt.
for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i)
/*empty*/;
if (i != NumElts) {
Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin();
Diag(D->getLocation(), diag::ext_mixed_decls_code); // <-- here
}
}
...
Note the !getLangOpts().C99 in the if. The diagnose code will never execute with a standard above c90.
Well one thing you can surely try is build clang by yourself and delete that part of the if so end up with if (!getLangOpts().CPlusPlus).
I tried and it worked for me.
You can configure the clang build with cmake -G "Ninja" -DCMAKE_BUILD_TYPE="Release" -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_C_COMPILER="/usr/bin/gcc" -DCMAKE_CXX_COMPILER="/usr/bin/g++" -DLLVM_PARALLEL_LINK_JOBS=2 -DLLVM_OPTIMIZED_TABLEGEN=ON path/to/llvm-project/llvm

Clang parameter -Wno-conditional-type-mismatch and GCC

The following simple C example program correctly emits a compile warning:
#include <stdio.h>
int main(int argc, char *argv[])
{
int *p = NULL;
int q = 1;
if(1 == 2 ? p : q) { printf("Info\n"); }
return(0);
}
The warning emitted is "warning: pointer/integer type mismatch in conditional expression".
In clang, the parameter "-Wno-conditional-type-mismatch" works in such a way that no warnings appear for the example code.
In GCC, I was looking for a similar option. The best I could find was the parameter "-fcond-mismatch", which would allow the example code. From the man page:
Allow conditional expressions with mismatched types in the second and third arguments. The
value of such an expression is void. This option is not supported for C++.
But when using this option, GCC keeps complaining:
# gcc -fcond-mismatch -c example.c
example.c: In function 'main':
example.c:8:17: warning: pointer/integer type mismatch in conditional expression
8 | if(1 == 2 ? p : q) { printf("Info\n"); }
Using GCC 10.3.0, would there be a GCC option or compiler flag to suppress the warning, in a similar way as clang does?
I don't think there is any such flag. GCC's manual says, under -Werror=, "The warning message for each controllable warning includes the option that controls the warning."
Since this message does not mention such an option, this suggests it is not controllable.

ccosl undeclared when trying to use cos(double) from tgmath.h on arm-none-eabi-gcc

Consider the following test code:
#include <tgmath.h>
void test()
{
double x=cos(4.5);
}
Compiling it as with
arm-none-eabi-gcc test.c -c
on Ubuntu 18.04 (gcc 6.3.1, newlib 2.4.0) works fine, but on Ubuntu 20.04 (gcc 9.2.1, newlib 3.3.0) I get the following errors:
In file included from test.c:1:
test.c: In function 'test':
test.c:5:14: error: 'ccosl' undeclared (first use in this function); did you mean 'ccosh'?
5 | double x=cos(4.5);
| ^~~
test.c:5:14: note: each undeclared identifier is reported only once for each function it appears in
test.c:5:14: error: argument 6 of '__builtin_tgmath' is not a function pointer
Apparently, the definition of cos has somehow changed, so that it now mentions ccosl which is not declared anywhere.
If I change from tgmath.h to math.h, the error no longer appears. This is of course just a workaround, not a fix, since this way I lose the type genericity for float vs double.
My question is: how do I make it work properly? Do I have to add some compilation option, or is it just a bug in the toolchain?
It appears that the difference between the versions of the toolchains is in the GCC implementation of tgmath cos macro in different versions. Namely, compiling with -E option for gcc yields the following (cleaned up) expansion of double x=cos(4.5) in 6.3.1:
double x=__builtin_choose_expr(__builtin_classify_type(4.5) == 9,
__builtin_choose_expr(__builtin_types_compatible_p(__typeof__(__real__(4.5)), long double),
ccosl(4.5),
__builtin_choose_expr(__builtin_types_compatible_p(__typeof__(__real__(4.5)), double) || __builtin_classify_type(__real__(4.5)) == 1,
ccos(4.5),
ccosf(4.5))
),
__builtin_choose_expr(__builtin_types_compatible_p(__typeof__(4.5), long double),
cosl(4.5),
__builtin_choose_expr(__builtin_types_compatible_p(__typeof__(4.5), double) || __builtin_classify_type(4.5) == 1,
cos(4.5),
cosf(4.5))
)
);
while in GCC 9.3.0 the expansion is as a simple function call:
double x=__builtin_tgmath (cosf, cos, cosl, ccosf, ccos, ccosl, 4.5);
The main difference between the two is that __builtin_choose_expr doesn't evaluate the expression that is not chosen (as said in the docs), while __builtin_tgmath is a function, which needs all the arguments to be valid.
And it looks like newlib has never had ccosl in its complex.h, so it appears incompatible with the newer version of GCC.

How to enforce the usage of return values in C

I'm searching for a compiler flag for gcc and if possible for clang and the Microsoft compilers as well, that triggers a warning (error with -Werror) if a non-void function is called without using the return value like this:
int test() {
return 4;
}
int main(void) {
test(); //should trigger a warning
int number = test(); //shouldn't trigger the warning
return 0;
}
If there is no such compiler flag, maybe some way to tell the clang static analyzer to complain about it.
EDIT: To clarify my original question: I actually meant using the return value, not only assigning it.
I never used it myself (do you really need it?), you can try
defining the function with warn_unused_result attribute
enabling -Wunused-result flag with gcc.
This will tell you about any unused value from the function return.
In case, any doubts, SEE IT LIVE or SEE IT LIVE AGAIN Thanks to M.M for the link in the comment
Or:
#include <stdio.h>
extern int func1(void) __attribute__((warn_unused_result));
extern int func2(void);
int main(void)
{
func1();
int rc1 = func1();
int rc2 = func1();
func2();
printf("%d\n", rc1);
return 0;
}
Compilation (GCC 5.1.0 on Mac OS X 10.10.5):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c warn.c
warn.c: In function ‘main’:
warn.c:10:9: error: unused variable ‘rc2’ [-Werror=unused-variable]
int rc2 = func1();
^
warn.c:8:5: error: ignoring return value of ‘func1’, declared with attribute warn_unused_result [-Werror=unused-result]
func1();
^
cc1: all warnings being treated as errors
$
Some static code analyzers like splint can check for these kind of things:
$ splint check.c
Splint 3.1.2 --- 03 May 2009
check.c: (in function main)
check.c:6:5: Return value (type int) ignored: test()
Result returned by function call is not used. If this is intended, can cast
result to (void) to eliminate message. (Use -retvalint to inhibit warning)
Unlike #Sourav's answer, this does not require a specific __attribute__ annotation on the target function, but on the other hand possibly emits many warnings. Its usually possible to suppress the warnings for specific functions or function calls by using annotations (like /*#alt void#*/).

Linking a library in g++ doesn't work

I am trying to compile a .cpp-file which uses a matrix-library. The library-files libnewmat.a and libnewmat.so are in the path /usr/lib64 . The include-files are in path /usr/include/newmat , so I tried (several ways) to compile i.e. with:
g++ -I/usr/include -L/usr/lib64 -lnewmat new.cpp -o new3
but the compiler doesn't find the library. The content of the .cpp is:
#include <iostream>
#include <newmat/newmat.h>
#include <newmat/newmatio.h>
using namespace std;
int main()
{
Matrix A(2,2);
Real b[] = {1,2,3,4};
A << b;
cout << A << endl;
return 0;
}
The compiler says:
test.cpp: In function ‘int main()’:
test.cpp:9: error: ‘Matrix’ was not declared in this scope
test.cpp:9: error: expected ‘;’ before ‘A’
test.cpp:10: error: ‘Real’ was not declared in this scope
test.cpp:10: error: expected ‘;’ before ‘b’
test.cpp:11: error: ‘A’ was not declared in this scope
test.cpp:11: error: ‘b’ was not declared in
this scope
Could You provide me with the correct c++ code, or the correct command line instruction?
Thanks, Kepler
If you recently installed this library yourself you probably need to run sudo ldconfig to load the so into the linker cache.
EDIT: As Kevin said not a linking error that you're getting.
Perhaps it's a name space issue?
using namespace NEWMAT;
according to this: http://www.robertnz.net/nm10.htm#namesp
This isn't a library problem - it's a compiler problem - it can't find any definition for Matrix (probably in your include files, but we can't determine that with the information given)
[edit]
Ascertain if your classes in the include files are being referenced correctly
[/edit]

Resources