cc icon indicating copy to clipboard operation
cc copied to clipboard

Advice needed

Open hillu opened this issue 6 years ago • 5 comments

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)
}

hillu avatar Jul 27 '18 19:07 hillu

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.

cznic avatar Jul 28 '18 07:07 cznic

Link to ccgo at godoc.org.

cznic avatar Jul 28 '18 07:07 cznic

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.  */

hillu avatar Jul 28 '18 10:07 hillu

ccgo -o foo.go foo.c works just fine -- where foo.c contains

#include <stdlib.h>
int main () {}

hillu avatar Jul 28 '18 10:07 hillu

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.

cznic avatar Jul 28 '18 11:07 cznic