How to get only function declaration from clang AST? - c

I want AST for my C program and want represent in json format. To do so I used clang -Xclang -ast-dump=json -fSyntax-only main.c command. It gave a AST. but the AST contains typeDecl, Value declaration etc. along with function declaration.
I want only a function declaration form my code in JSON form. How can achieve this?
Here is an alternative clang-check -ast-dump -ast-dump-filter=main main.c but this cant give the result in JSON form. and when I execute this got some error messages along with output for this simple code
#include <stdio.h>
int main() {
printf("Hello from C!");
return 0;
}
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "main.c"
No compilation database found in /home/..../src or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.

It is a well-known issue connected to the differences between clang frontend and clang driver. It is even covered in docs.
So, run clang -### main.c, copy all -internal-isystem and -internal-externc-isystem options and add them to the command that you run to get AST.
I hope this information will be helpful!

Related

"undefined reference" error after adding function to a C project

I've added a new function wiringPiVersion() to wiringPi, but after I build and install the shared library, when I attempt to compile a small C program around it, I get:
wpi_ver.c:(.text+0xc): undefined reference to `wiringPiVersion'
However, when I include it in an XS based Perl module, all works well. I don't know enough about C to figure out what's going wrong here, and I've been searching for the better part of two hours trying different things to no avail.
Here's my small C program to test the new function:
#include <stdio.h>
#include <wiringPi.h>
int main (){
char * ver = wiringPiVersion();
printf("wiringPi version: %s\n", ver);
return 0;
}
Compilation that throws the error:
gcc -o ver wpi_ver.c -lwiringPi
The addition to wiringPi's header file:
extern char * wiringPiVersion(void);
The wiringPi's .c file addition:
#define WPI_VERSION "2.36"
char * wiringPiVersion(void){
return WPI_VERSION;
}
In my Perl module's XS file, I have:
char *
wiringPiVersion()
...and my Perl module's Makefile.PL
LIBS => ['-lwiringPi'],
...and after re-installing the Perl module, I can access the function without any issues in a test script.
I'm hoping this is something simple I'm overlooking which someone may be able to point out. My question is, how do I rectify this?
So it turned out that there were two .so files generated when I rebuilt wiringPi... one in the wiringPi's build directory way under my home directory, and the other in /usr/local/lib.
After a tip in comments, I added the library path explicitly:
gcc -o ver wpi_ver.c -L/usr/local/lib -lwiringPi
...and it all fell together and works as expected:
$ ./ver
wiringPi version: 2.36
Note: I have sent Gordon the patch in hopes it gets included in the next wiringPi cut.
Update: I received an email back from Gordon and he stated that currently, only the gpio application has the ability to report the version, so he advised that he's going to add something similar to my patch in a future release.
Although already solved, I added this answer to show what gave me the hint.
Error message "undefined reference" points to a linker error (cf. answer on SO), so its about checking if the correct library is drawn.

Unable to run C program through cmd

Hello everyone I'm learning C and am trying to figure out how to run it through the command console cmd. I have eclipse installed along with Mingw and added these to the path:
C:\MinGW\bin\;C:\MinGW\msys\1.0\bin
I wrote this program on notepad++ for a quick test run and save it to C:\test.c and also under a folder C:\Users\Pikachu\Music\C code while I was trying to figure it out:
#include <stdio.h>
int main()
{
printf("Hey, Buddy!\n");
return 0;
}
On the cmd console I typed:
c:\>gcc test.c
and got the error message:
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/id.exe: cannot ope
n output file a.exe: Invalid argument
collect2.exe: error: ld returned 1 exit status
When I typed:
c:\>cd c:\Users\Pikachu\Music\c code
and then:
gcc test.c
it just skipped a line as if nothing happened and went back to square one:
c:\Users\Pikachu\Music\c code>gcc test.c
c:\Users\Pikachu\Music\c code>
I was wondering if anyone knows what's going on and could help me out, I'd be so happy if I could see "Hey, Buddy" from cmd! Does anyone also know why I get the error message running it from c:\ and nothing when I run it from the Music\c code\test.c folder even though I'm supposedly running the same file test.c?
I've tried searching around and have picked up references on how the computer can't link to the proper dll's however I'm not sure how to implement this to my specific problem.
Oh and curiously enough when I tried to save another file in c:\ I got a message saying that I didn't have permission to do that even though 5 minutes prior I had done just this. Any insights?
Thanks for your help!
When you run gcc on your C source file, all that it will do it generate an executable file. I believe its called a.exe by default but I would recommend naming it with the -o option:
gcc text.c -o test.exe
Once your file is successfully compiled, run the executable to say hello to the worls:
c:\Users\Pikachu\Music\c code> .\test.exe
As for the first error you got, maybe it has to do with gcc not being able to create the output executable on the root c: folder. I would recommend doing your coding some folder your user owns instead of on a system folder for this reason.
By the way, gcc supports many other options. I highly recommend using -Wall to turn on warnings and choosing what version of the C standard to follow (-std=c99 or -ansi, together with the -pedantic flag).

How to link two source files properly? undefined reference error

Ok so I am doing a final project for one of my classes and trying to do a bit extra and create multiple files to work with. I am coding inside of CodeBlocks. So far I have a main.c, levels.c, and levels.h for my files. Inside of the levels.c levelOne function, I put the printf statement as a test to make sure I could have the two files work with each other before I went forward in my coding. I got a "undefined reference to 'levelOne' when I compiled and ran the program.
Inside my main.c file:
#include <stdio.h>
#include <stdlib.h>
#include "levels.h"
int main()
{
levelOne();
return 0;
}
Inside my levels.h file:
#ifndef LEVELS_H_INCLUDED
#define LEVELS_H_INCLUDED
void levelSelect(char c);
void levelOne();
void levelTwo();
void levelThree();
void levelCustom(int difficulty);
#endif // LEVELS_H_INCLUDED
Inside my levels.c file:
void levelOne()
{
//level scope of 1 to 10
srand(time(NULL));
int randomNum = (rand() % 9)+1);
printf("the random number is: %i\n", randomNum);
}
levels.c is not getting passed into the compiler, are you sure you have included levels.c in the whole project? If not it will not link. You need a project if you want to compile multiple files. In CodeBlocks, the sources and the settings for the build process are stored in a project file <name>.cbp
Here is the User Manual
gcc levels.c main.c should link successfully. gcc main.c will only compile one file and try and link to create final executable and levelOne() will not be found. since it is in file levels.c
You need to include levels.h in levels.c as well or if a function (physically) above levelOne calls it, it is undefined.
Then compile it with gcc -Wall *.c -o myapp to compile and link all of the c files in that directory into myapp (or you can name them individually) with (almost) all warnings enabled. This is provided you have it in its own directory.
Once you get into larger projects with more code, you can compile individual .c files into .o object files with gcc -Wall -c somecode.c and then link all the objects with gcc *.o -o myapp. If it gets really large, you'll want a build system to help with rebuilding objects only when its code (or dependent code) changes (such as Makefiles, waf, and dare I say autotools).
I had this exact same problem, the solution is easy. Right click on levels.c and select properties. A properties window should come up select the "Build" tab tick compile file, link file, and in the box check debug and release. This should fix your problem.
Don't make the mistake of doing this with a header file because it will give you a "...h.gch: file not recognized: File format not recognized.." error.

Combine C and TCL using Swig

I have been following a tutorial to combine C with TCL using Swig. The tutorial seemed to be properly working but at the end I ran into an error that I cannot solve. The situation is as follows:
The tutorial I was following is:
http://www.swig.org/tutorial.html.
I have a file named test.c:
char *HelloWorld()
{
return "hello world";
}
and another named test.i:
%module test
%{
/* Put header files here or function declarations like below */
extern char *HelloWorld();
%}
extern char *HelloWorld();
I then used the following command line arguments to ready the correct files:
gcc -c test.c -o test.o
swig -tcl test.i
gcc -c test_wrap.c -o test_wrap.o
gcc -dynamiclib -framework Tcl test.o test_wrap.o -o test.so
And finally I tried to load it using:
tclsh
% load test.so test
This is the point where I received the following error:
dlsym(0x100600090, Test_Unload): symbol not founddlsym(0x100600090, Test_SafeUnload): symbol not found
As far as I know I did not stray from the tutorial. Can anyone tell me how it is that I got this error and more importantly how to get rid of it?
Thanks in advance!
Are those error messages stopping the load from working? They shouldn't; they're reporting that the low-level API for supporting unloading of the extension isn't present, but that's OK (lots of extensions can't be unloaded; it's tricky to write code that supports it).
You don't mention exactly which version of Tcl you are using — but it must be at least 8.5 for those symbols to be even searched for in the first place — so it is a little hard to guess what the exact underlying issue is. (The message should simply not be reported.) I advise filing a bug report on this; make sure you include all exact versions in your report.
It's a long time since I used SWIG, so I'm not sure whether it gives you sufficient control over the code it generates for you to be able to apply this fix. Glossing over that detail, I can reproduce (and fix) the issue with the following:
In 'ext.c':
#include <tcl.h>
int DLLEXPORT Ext_Init(Tcl_Interp *interp) {
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if (Tcl_PkgProvide(interp, "Ext", "0.0") == TCL_ERROR) {
return TCL_ERROR;
}
return TCL_OK;
}
Build, run tclsh, load extension:
$ gcc -dynamiclib -framework Tcl ext.c -o ext.so
$ tclsh8.5
% load ./ext.so
dlsym(0x400000, Ext_SafeInit): symbol not found
dlsym(0x400000, Ext_Unload): symbol not found
dlsym(0x400000, Ext_SafeUnload): symbol not found
Something internal to the library loading code is putting that error message into the interpreters result. To stop the message ever surfacing, set or reset the result so that the _Init() function ends with one or other of:
// Set the result to a message of your choosing
Tcl_SetObjResult(interp, Tcl_NewStringObj("ok", -1));
// Or clear out the result altogether
Tcl_ResetResult(interp);
return TCL_OK;
}
The init block feature of swig might insert code in the right place to achieve the same thing:
%init %{
Tcl_ResetResult(interp);
%}

Using SWIG to create Octave file

I'm trying to use SWIG to create a Octave function. But even the most basic example code seems to fail before I even get the chance to get it into octave. I am not sure if I should be concerned that swig creates a extension type for the C++ source file (.cxx) it generates that mkoctfile doesn't recognize (it only takes .C .cpp .cc, which seems like allot for swig to mess up that much and create what seems like the ONE extension for C++ it doesn't support).
Any help from someone with more experience with this would be greatly appreciated!
The steps I have done are as follows:
swig -octave swig_test.i
mv swig_test_wrap.cxx swig_test_wrap.cpp <--- This is necessary because mkoctfile doesn't recognize the cxx type c++ code that swig generates
mkoctfile swig_test_wrap.cpp
This results in 4 errors consistantly:
swig_test_wrap.cpp:1449:24: error: invalid covariant return type for 'virtual Octave_map octave_swig_type::map_value() const'
/usr/include/octave-3.4.0/octave/../octave/ov-base.h:560:22: error: overriding 'virtual octave_map octave_base_value::map_value() const'
swig_test_wrap.cpp:1657:24: error: invalid covariant return type for 'virtual Octave_map octave_swig_ref::map_value() const'
/usr/include/octave-3.4.0/octave/../octave/ov-base.h:560:22: error: overriding 'virtual octave_map octave_base_value::map_value() const'
The source code of my outlandishly basic swig_test.c
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
int my_mod(int x, int y) {
return (x%y);
}
Then the code of my wrapper inteface file swig_test.i
%module swig_test
%{
extern int fact(int n);
extern int my_mod(int x, int y);
%}
extern int fact(int n);
extern int my_mod(int x, int y);
___________________________________________________
UPDATE: May 9th 2011
So I still have not found a solution to this, and am starting to wonder if maybe these programs are out of date? The documentation most certainly is. Just as an example: the instructions say
swig -octave swig_test.i -o swig_test_wrap.cxx
now that will certainly not work regardless, because mkoctfile wont take type cxx as stated before. Also, this command just is physically written wrong. As typed above, it returns the error.
swig error : unrecognized option example.i
use swig -help for available options
The command SHOULD be entered as:
swig -octave -o swig_test_wrap.cpp swig_test.i
That WILL generate the swig_test_wrap.cpp file just as advertised. I would have thought there would be a -i option for input file in the argv of swig, but hey, now that I know that order matters here, someone must have just not updated the documentation when they changed something about how the function works.
So now, after running this command I have my swig_test_wrap.cpp file. Next I take that and try to execute
mkoctfile swig_test_wrap.cpp swig_test.c
Again, I get the same error as above: "invalid covariant return type" etc, however I also DO get a file swig_test.o out of the process. Just for fun, I then ran
mkoctfile swig_test.o
And lo and behold, this DOES generate a file called swig_test.oct. However when I went into octave and tried to load the file by running
octave:1>swig_test
I get the response error: 'swig_test' undefined near line 1 column 1
So as far as I can tell, I'm right back to square one. Anyone have any ideas?
So it turns out that this issue is related to the version of octave that I was using. Octave version 3.4.0 doesn't seem to work with swig yet. I got help on source-forge and once i downgraded to version 3.2.4-r3 it works perfectly.
And it is a known bug that you have to use:
swig -octave -o WRAPFILE.cpp INPUT.i
and its a problem with mkoctfile that you have to use the .cpp extension, since they SHOULD accept the .cxx extension as it is a valid extension for C++ files.
Try:
$ swig -octave -c++ swig_test.i -o swig_test_wrap.cxx
$ mkoctfile swig_test_wrap.cxx swig_test.c
as described here.

Resources