cc
cc copied to clipboard
Advice needed
Hi,
I would like to use cc to parse data types and function definitions from header files but am running into what seems to be missing definitions that are part of the GNU libc The program below produces the following error message which I believe refers to __THROW
not being defined:
error: /usr/include/stdlib.h:100:45: unexpected identifier, expected one of ['(', ')', ',', ':', ';', '=', '[', '{', _Bool, _Complex, auto, char, const, double, enum, extern, float, inline, int, long, register, restrict, short, signed, static, struct, typedef, typedef name, typeof, union, unsigned, void, volatile]
... where line 100 in stdlib.h
contains:
extern size_t __ctype_get_mb_cur_max (void) __THROW __wur;
The system on which this happens is an amd64 Debian 9 system, the GCC version is gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
.
Am I missing something obvious?
package main
import (
"fmt"
"github.com/cznic/cc/v2"
)
func main() {
predef, includePaths, sysIncludePaths, err := cc.HostConfig("-std=c99")
fmt.Println(predef)
tu, err := cc.Translate(
&cc.Tweaks{
TrackExpand: func(s string) { fmt.Println("expand " + s) },
TrackIncludes: func(s string) { fmt.Println("include " + s) },
EnableAnonymousStructFields: true,
EnableEmptyStructs: true,
EnableImplicitBuiltins: true,
EnableOmitFuncDeclSpec: true,
EnableReturnExprInVoidFunc: true,
EnableUnionCasts: true,
InjectFinalNL: true,
},
includePaths, sysIncludePaths,
cc.NewStringSource("<predef>", predef),
cc.NewStringSource("<incl-stdint>", "#include <stdlib.h>"),
cc.NewStringSource("<main>", "int main () {}"),
)
if err != nil {
fmt.Printf("error: %v\n", err)
return
}
fmt.Printf("&#v\n", tu)
}
The program below produces the following error message which I believe refers to __THROW not being defined:
I think so as well. However, it should not be defined as it is a C++ thing. Please share your full stdlib.h
, I think it may be a bug in the ccgo preprocessor.
Additionally, you may want to try the ccgo
command:
$ ccgo -o foo.go your-source.c your-source2.c
and use the definitions from the .go file.
Link to ccgo at godoc.org.
I have put the relevant header files into https://gist.github.com/hillu/3a0be9ad08d9cf3722a307604b1996c6. /usr/include/x86_64-linux-gnu/sys/cdefs.h
is responsible for the __THROW
macro -- and I am sure that it is included, as my TrackIncludes
function showed.
Here's the relevant bit of cdefs.h
:
#ifdef __GNUC__
/* All functions, except those with callbacks or those that
synchronize memory, are leaf functions. */
# if __GNUC_PREREQ (4, 6) && !defined _LIBC
# define __LEAF , __leaf__
# define __LEAF_ATTR __attribute__ ((__leaf__))
# else
# define __LEAF
# define __LEAF_ATTR
# endif
/* GCC can always grok prototypes. For C++ programs we add throw()
to help it optimize the function calls. But this works only with
gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions
as non-throwing using a function attribute since programs can use
the -fexceptions options for C code as well. */
# if !defined __cplusplus && __GNUC_PREREQ (3, 3)
# define __THROW __attribute__ ((__nothrow__ __LEAF))
# define __THROWNL __attribute__ ((__nothrow__))
# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
# else
# if defined __cplusplus && __GNUC_PREREQ (2,8)
# define __THROW throw ()
# define __THROWNL throw ()
# define __NTH(fct) __LEAF_ATTR fct throw ()
# else
# define __THROW
# define __THROWNL
# define __NTH(fct) fct
# endif
# endif
#else /* Not GCC. */
# define __inline /* No inline functions. */
# define __THROW
# define __THROWNL
# define __NTH(fct) fct
#endif /* GCC. */
ccgo -o foo.go foo.c
works just fine -- where foo.c
contains
#include <stdlib.h>
int main () {}
Thanks for the info. The world of system headers is a mess. I think some of the condition compilation directive in https://github.com/cznic/cc/issues/105#issuecomment-408597265 is not evaluated correctly by cc
. Please try to look around in cpp.go if you can find the bug. I'll not have time for that in the near future.
Wrt ccgo
, I've already planned to add some --ccgo-defs
option that will produce Go versions from things declared in headers. It's good to know ccgo
can process the header, but it will spit out only defined things ATM. I don't know when this feture may be possibly added. It may take a long time.