warning switch for condition function as a variable - gcc

I have errornously forgotten to put the parameter List after the call to a function, and the gcc did not intercept (because he believes it is a TRUTH-value). Is there a gcc warning/error switch, which helps me to locate those places? example:
short function(short arg);
main() {
if (function) { // I wanted to write function(arg)
//do something
}
}
The Version of the gcc I am using is 3.2.1.

Looking at the GCC man page, it seems that what you need is -Waddress.
-Waddress
Warn about suspicious uses of memory addresses. These include using the address of a function in a conditional
expression, such as "void func(void); if (func)", and comparisons against the memory address of a string literal, such as
"if (x == "abc")". Such uses typically indicate a programmer error: the address of a function always evaluates to true,
so their use in a conditional usually indicate that the programmer forgot the parentheses in a function call; and
comparisons against string literals result in unspecified behavior and are not portable in C, so they usually indicate
that the programmer intended to use "strcmp". This warning is enabled by -Wall.
As stated there, you can enable this flag with -Wall too.

Use "-Wall" option with gcc. This option force gcc to show all kinds of warnings at compilation.
You may get following warning when you compile your code by 'gcc -Wall' command.
`function' undeclared (first use in this function)

Related

How does the scanf_s function work on MinGW GCC?

#include <stdio.h>
int main (void) {
char str[100];
scanf_s ("%[^\n]", str);
printf ("%s\n", str);
return 0;
}
This code can be successfully compiled without any errors or warnings by MinGW GCC 11.3.0, and the exe file runs properly without any exception. Different from the function with the same name in MSVC, function scanf_s in MinGW GCC does not require a third argument when being used to input string. How does the function scanf_s work in MinGW GCC?
Both the ISO C version and the Microsoft version of scanf_s require that for every use of the %s conversion format specifier, an additional argument is provided which specifies the size of the buffer. The same probably also applies for the library that your version of MinGW is using.
By not providing the required number of arguments to scanf_s, your code has undefined behavior. The fact that your program may compile and even run properly does not change the fact that your code has undefined behavior, i.e. that anything may happen, including the possibility that it may work as intended. You cannot rely on this behavior.

GCC: __atomic_always_lock_free compiles with -O3, but not with -O0

Sample code:
int *s;
int foo(void)
{
return 4;
}
int bar(void)
{
return __atomic_always_lock_free(foo(), s);
}
Invocations:
$ gcc t0.c -O3 -c
<nothing>
$ gcc t0.c -O0 -c
t0.c:10:10: error: non-constant argument 1 to '__atomic_always_lock_free'
Any ideas?
Relevant: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html.
This doesn't seem surprising. The documentation you linked says that "size must resolve to a compile-time constant" and so it's to be expected that you might get an error when passing foo(). However, it's typical that if GCC is able to determine the value of an expression at compile time, then it will treat it as a compile-time constant, even if it doesn't meet the language's basic definition of a constant expression. This may be considered an extension and is explicitly allowed by the C17 standard at 6.6p10.
The optimization level is relevant to what the compiler tries in attempting to evaluate an expression at compile time. With optimizations off, it does little more than the basic constant folding that the standard requires (e.g. 2*4). With optimizations on, you get the benefit of its full constant propagation pass, as well as function inlining.
So in essence, under -O0, the compiler doesn't notice that foo() always returns the same value, because you've disabled the optimizations that would allow it to reach that conclusion. With -O3 it does and so it accepts it as a constant.

Getting "cannot find symbol .... while executing load ..." error when trying to run Hello World as a C extension (dll) example

I have used the C code from the following verbatim: https://wiki.tcl-lang.org/page/Hello+World+as+a+C+extension
/*
* hello.c -- A minimal Tcl C extension.
*/
#include <tcl.h>
static int
Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1));
return TCL_OK;
}
/*
* Hello_Init -- Called when Tcl loads your extension.
*/
int DLLEXPORT
Hello_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
/* changed this to check for an error - GPS */
if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "hello", Hello_Cmd, NULL, NULL);
return TCL_OK;
}
My command for compiling is nearly verbatim except for the last character, indicating Tcl version 8.6 rather than 8.4, and it compiles without error:
gcc -shared -o hello.dll -DUSE_TCL_STUBS -I$TCLINC -L$TCLLIB -ltclstub86
Then I created the following Tcl program:
load hello.dll Hello
puts "got here"
But when running it with tclsh get the following error:
cannot find symbol "Hello_Init"
while executing
"load ./hello.dll Hello"
(file "hello.tcl" line 1)
So I am essentially following a couple of suggestions from Donal Fellows answer here: cannot find symbol "Embeddedrcall_Init" The OP there however commented that, like me, the suggestion(s) hadn't resolved their issue. One thing that I didn't try from that answer was "You should have an exported (extern "C") function symbol in your library" -- could that be the difference maker? Shouldn't it have been in the example all along then?
At the suggestion of somebody on comp.lang.tcl I found "DLL Export Viewer" but when I run it against the DLL it reports 0 functions found :( What am I doing wrong?
Could it be an issue with MinGW/gcc on Windows, and I need to bite the bullet and do this with Visual Studio? That's overkill I'd like to avoid if possible.
The core of the problem is that your function Hello_Init is not ending up in the global symbol table exported by the resulting DLL. (Some linkers would put such things in as _Hello_Init instead of Hello_Init; Tcl adapts to them transparently.) The symbol must be there for Tcl's load command to work: without it, there's simply no consistent way to tell your extension code what the Tcl_Interp context handle is (which allows it to make commands, variables, etc.)
(If you'd been working with C++, one of the possible problem is a missing extern "C" whose actual meaning is to turn off name mangling. That's probably not the problem here.)
Since you are on Windows — going by the symbols in your DLL, such as EnterCriticalSection and GetLastError — the problem is probably linked to exactly how you are linking. I'm guessing that Tcl is defining your function to have __declspec(dllexport) (assuming you've not defined STATIC_BUILD, which absolutely should not be used when building a DLL) and yet that's not getting respected. Assuming you're using a modern-enough version of GCC… which you probably are.
I'm also going through the process of how to build tcl extensions in C and had exactly the same problem when working though this same example using tcl 8.6.
i.e. I was compiling using MinGW GCC (64-bit), and used the following:
gcc -shared -o hello.dll -DUSE_TCL_STUBS "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\lib" -ltclstub86
And like the OP I got no compile error, but when loading the dll at a tclsh prompt tcl complained :
'cannot find symbol "Hello_Init"'
I can't say that I understand, but I was able to find a solution that works thanks to some trial and error, and some information on the tcl wiki here
https://wiki.tcl-lang.org/page/Building+Tcl+DLL%27s+for+Windows
In my case I had to adjust the compiler statement to the following
gcc -shared -o hello.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
Obviously those file paths are specific to my system, but basically
I had to add an explicit reference to the .c file
I had to include the tcl86t dll library from the tcl bin directory
I had to remove the -DUSE_TCL_STUBS flag ( meaning that the references -LC:\\ActiveTcl\\lib and -ltclstub86 could also be removed)
(attempting to use the -DUSE_TCL_STUBS flag caused the compiler to complain with C:\ActiveTcl\lib/tclstub86.lib: error adding symbols: File format not recognized )
This successfully compiled a dll that I could load, and then call the hello function to print my 'Hello World' message.
Something else I stumbled over, and which wasn't immediately obvious:
reading https://www.tcl.tk/man/tcl8.6/TclCmd/load.htm, tcl epxects to find an 'init' function based on a certain naming convention.
if the C extension does not define a package name then the name of that init function will be derived from the dll filename.
This caused a few problems for me (when compiling via Eclipse IDE), as the dll name was being automatically determined from the eclipse projet name.
For example, if I recompile the same example, but call the .dll something else, eg.
gcc -shared -o helloWorldExenstion.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
Then at tclsh prompt:
% load helloWorldExtension
cannot find symbol "Helloworldextension_Init"

Detect compiler and use compiler-specific flags when invoking

I'm handed a variable CC which contains the executable that refers to the compiler on the system. I need to take this executable and eventually call it with some compiler-specific link arguments.
My current approach seems very fragile:
def guess_compiler(cc):
out = subprocess.check_output((cc, '--version'))
for possible in (b'clang', b'gcc'):
if possible in out:
return possible.decode()
else:
# Fall back to gcc
return 'gcc'
From this I'm using a mapping of the specific linker arguments I care about:
return {
'clang': '-Wl,-undefined,dynamic_lookup',
'gcc': '-Wl,--unresolved-symbols=ignore-all',
}[cc]
In short, I'm hoping there's a better (less fragile) way to do what I've accomplished.
For those looking for why I want something like this, it's mostly for portability in a project I'm implementing.
I'd rather call a compiler with some dummy code and these flags passed in. This is also what tools like Autotools and CMake do.
The problem with your current approach is that text string you see in --version output can actually be arbitrary. For instance, when clang wasn't that popular, FreeBSD's cc --version have been giving
GCC 4.2.1 -compatible Clang bla bla
So, just call the compiler with each flag you are interested in and then look at exit code.
An example of how to do this:
for flag in FLAGS:
try:
subprocess.check_call((cc, 'test.c', flag), cwd=tmpdir)
return flag
except subprocess.CalledProcessError:
pass
else:
# wellp, none of them worked, fall back to gcc and they'll get a
# hopefully reasonable error message
return FLAG_GCC

gcc:how to remove undefined symbol that is not used?

here is some C++ test code:
__attribute__((visibility("hidden"))) void foo()
{
int fd = fopen("data1", "rb");
printf ("%d", fd);
}
And all other code don't call function 'foo' and function 'fopen'
Then I use gcc option -ffunction-sections to compile the code to a so file.
As I think, the function foo symbol and foo binary code has't inlcuded in the so file.
But The problem is, I think the symbol 'fopen' should not be symbol table.
ps:I can make sure that only function 'foo' has use 'fopen'.
And it actually is not, when I use command nm, I found 'U' type symbol of 'fopen'.
How is the gcc work?
And has gcc other compile option to found that, symbol 'fopen' is not use, and remove 'fopen' symbol.
The problem is, that the compiler does not know, wheter the symbols are used later.
You can tell at compile time that you gave him the whole program, so that if your program isnt calling the function, nobody would.
The compiling option is -fwhole-program.

Resources