review recent commits

tccpp.c:
 - revert "Preprocessor fix + new testcase"
   Fix was not a fix and nobody could understand the test.
   This reverts 6379f2ee76
 - better fix and add new test (pp/18.c)

tccgen.c:
 - remove global variables 'in_sizeof', 'constant_p'
 - rework comma expression (gexpr())
 - merge func/data 'alias_target' codes
   (See 08c777053c)
 - move call to do_Static_assert()
 - better error: "expression expected before '%s'"
 - fix "statement after label"
    - remove unnecessary second parameter to block()
    - remove unnecessary call to decl()
    - revert changes to old C89 test file
    See 7f0a28f6ca

tccelf.c:
 - rework "...make undefined global symbol STT_NOTYPE"
   (See f44060f8fc)
 - move tccelf_add_crtbegin() from libtcc.c

tcctest:
 - unfix K&R fix (keep old look of K&R functions)

tccrun.c:
 - exit(0) returns 0

libtcc.c:
 - move #defines for -dumpmachine
 - more explicit error "file not found"
   (as opposed to error while loading file)

tccpe.c, x86_64-gen.c, i386-asm.c, tccasm.c:
 - use R_X86_64_PLT32 for functions on x86_64-win32

tccdefs.h
 - empty #defines for _Nonnull, __has_builtin(), etc.

configure:
 - Simpler "macOS .dylib ... VERSION letters."
   (See 6b967b1285)

Makefile:
 - macOS version also
 - add cross searchpaths for packages

build.yml:
 - disable codesign on macos-11 (doesn't seem to work)
This commit is contained in:
grischka 2024-02-04 17:38:23 +01:00
parent 6426cc3384
commit da0d43903b
24 changed files with 360 additions and 445 deletions

View File

@ -1,4 +1,4 @@
name: build and run tests
name: build and test
on:
push:
@ -17,7 +17,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: make & test tcc
run: ./configure && make && make test -k
run: ./configure --config-codesign=no && make && make test -k
test-x86_64-win32:
runs-on: windows-2019

View File

@ -55,6 +55,8 @@ else
# `make test' when libtcc.dylib is used (configure --disable-static), so
# we bake a relative path into the binary. $libdir is used after install.
LINK_LIBTCC += -Wl,-rpath,"@executable_path/$(TOP)" -Wl,-rpath,"$(libdir)"
# -current/compatibility_version must not contain letters.
MACOS_DYLIB_VERSION := $(firstword $(subst rc, ,$(VERSION)))
DYLIBVER += -current_version $(MACOS_DYLIB_VERSION)
DYLIBVER += -compatibility_version $(MACOS_DYLIB_VERSION)
endif
@ -193,7 +195,6 @@ endif
# include custom configuration (see make help)
-include config-extra.mak
ifneq ($(X),)
ifneq ($(T),$(NATIVE_TARGET))
# assume support files for cross-targets in "/usr/<triplet>" by default
TRIPLET-i386 ?= i686-linux-gnu
@ -201,11 +202,12 @@ TRIPLET-x86_64 ?= x86_64-linux-gnu
TRIPLET-arm ?= arm-linux-gnueabi
TRIPLET-arm64 ?= aarch64-linux-gnu
TRIPLET-riscv64 ?= riscv64-linux-gnu
MARCH-i386 ?= i386-linux-gnu
MARCH-$T ?= $(TRIPLET-$T)
TR = $(if $(TRIPLET-$T),$T,ignored)
CRT-$(TR) ?= /usr/$(TRIPLET-$T)/lib
LIB-$(TR) ?= {B}:/usr/$(TRIPLET-$T)/lib
INC-$(TR) ?= {B}/include:/usr/$(TRIPLET-$T)/include
endif
LIB-$(TR) ?= {B}:/usr/$(TRIPLET-$T)/lib:/usr/lib/$(MARCH-$T)
INC-$(TR) ?= {B}/include:/usr/$(TRIPLET-$T)/include:/usr/include
endif
CORE_FILES = tcc.c tcctools.c libtcc.c tccpp.c tccgen.c tccdbg.c tccelf.c tccasm.c tccrun.c

6
configure vendored
View File

@ -603,12 +603,6 @@ echo "VERSION = $version" >> config.mak
echo "#define TCC_VERSION \"$version\"" >> $TMPH
echo "@set VERSION $version" > config.texi
if test "$targetos" = "Darwin"; then
# On macOS, -current_version and -compatibility_version must not contain letters.
macos_dylib_version=`echo $version | sed 's/[^0-9.]//g'`
echo "MACOS_DYLIB_VERSION = $macos_dylib_version" >> config.mak
fi
if test "$source_path_used" = "yes" ; then
case $source_path in
/*) echo "TOPSRC=$source_path";;

View File

@ -515,7 +515,13 @@ static void gen_disp32(ExprValue *pe)
sym->type.t = VT_FUNC;
sym->type.ref = NULL;
}
#ifdef TCC_TARGET_X86_64
greloca(cur_text_section, sym, ind, R_X86_64_PLT32, pe->v - 4);
gen_le32(0);
#else
gen_addrpc32(VT_SYM, sym, pe->v);
#endif
}
}

View File

@ -124,20 +124,16 @@
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
#define __FINITE_MATH_ONLY__ 1
#define _FORTIFY_SOURCE 0
#define __has_builtin(x) 0
//#define __has_builtin(x) 0
#elif defined __ANDROID__
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
#define __PRETTY_FUNCTION__ __FUNCTION__
#define __has_builtin(x) 0
#define __has_feature(x) 0
#define _Nonnull
#define _Nullable
#else
/* Linux */
#endif
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
#ifndef __NetBSD__
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
@ -152,6 +148,16 @@
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
#endif
/* not implemented */
#define __PRETTY_FUNCTION__ __FUNCTION__
#define __has_builtin(x) 0
#define __has_feature(x) 0
/* C23 Keywords */
#define _Nonnull
#define _Nullable
#define _Nullable_result
#define _Null_unspecified
/* skip __builtin... with -E */
#ifndef __TCC_PP__

166
libtcc.c
View File

@ -620,9 +620,9 @@ static void error1(int mode, const char *fmt, va_list ap)
f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));
} else if (s1->current_filename) {
cstr_printf(&cs, "%s: ", s1->current_filename);
}
if (0 == cs.size)
} else {
cstr_printf(&cs, "tcc: ");
}
cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
cstr_vprintf(&cs, fmt, ap);
if (!s1 || !s1->error_func) {
@ -930,17 +930,8 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
return 0;
}
/* add sections */
tccelf_new(s);
if (s->do_debug) {
/* add debug sections */
tcc_debug_new(s);
}
#ifdef CONFIG_TCC_BCHECK
if (s->do_bounds_check) {
/* if bound checking, then add corresponding sections */
tccelf_bounds_new(s);
}
#endif
if (output_type == TCC_OUTPUT_OBJ) {
/* always elf for objects */
@ -951,66 +942,21 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
#ifdef TCC_TARGET_PE
# ifdef _WIN32
# ifdef TCC_IS_NATIVE
/* allow linking with system dll's directly */
tcc_add_systemdir(s);
# endif
/* target PE has its own startup code in libtcc1.a */
return 0;
#elif defined TCC_TARGET_MACHO
# ifdef TCC_IS_NATIVE
tcc_add_macos_sdkpath(s);
# endif
/* Mach-O with LC_MAIN doesn't need any crt startup code. */
return 0;
#else
/* paths for crt objects */
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
/* add libc crt1/crti objects */
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib) {
#if TARGETOS_OpenBSD
if (output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s, "crt0.o");
if (output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s, "crtbeginS.o");
else
tcc_add_crt(s, "crtbegin.o");
#elif TARGETOS_FreeBSD
if (output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s, "crt1.o");
tcc_add_crt(s, "crti.o");
if (s->static_link)
tcc_add_crt(s, "crtbeginT.o");
else if (output_type & TCC_OUTPUT_DYN)
tcc_add_crt(s, "crtbeginS.o");
else
tcc_add_crt(s, "crtbegin.o");
#elif TARGETOS_NetBSD
if (output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s, "crt0.o");
tcc_add_crt(s, "crti.o");
if (s->static_link)
tcc_add_crt(s, "crtbeginT.o");
else if (output_type & TCC_OUTPUT_DYN)
tcc_add_crt(s, "crtbeginS.o");
else
tcc_add_crt(s, "crtbegin.o");
#elif defined TARGETOS_ANDROID
if (output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s, "crtbegin_dynamic.o");
else
tcc_add_crt(s, "crtbegin_so.o");
#else
if (output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s, "crt1.o");
tcc_add_crt(s, "crti.o");
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib)
tccelf_add_crtbegin(s);
#endif
}
return 0;
#endif
}
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
@ -1096,7 +1042,7 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
if (fd < 0) {
if (flags & AFF_PRINT_ERROR)
tcc_error_noabort("file '%s' not found", filename);
return ret;
return FILE_NOT_FOUND;
}
s1->current_filename = filename;
@ -1226,18 +1172,21 @@ LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
return 0;
}
static int tcc_add_library_internal(TCCState *s, const char *fmt,
static int tcc_add_library_internal(TCCState *s1, const char *fmt,
const char *filename, int flags, char **paths, int nb_paths)
{
char buf[1024];
int i;
int i, ret;
for(i = 0; i < nb_paths; i++) {
snprintf(buf, sizeof(buf), fmt, paths[i], filename);
if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0)
return 0;
ret = tcc_add_file_internal(s1, buf, (flags & ~AFF_PRINT_ERROR) | AFF_TYPE_BIN);
if (ret != FILE_NOT_FOUND)
return ret;
}
return -1;
if (flags & AFF_PRINT_ERROR)
tcc_error_noabort("file '%s' not found", filename);
return FILE_NOT_FOUND;
}
/* find and load a dll. Return non zero if not found */
@ -1253,17 +1202,14 @@ ST_FUNC void tcc_add_support(TCCState *s1, const char *filename)
char buf[100];
if (CONFIG_TCC_CROSSPREFIX[0])
filename = strcat(strcpy(buf, CONFIG_TCC_CROSSPREFIX), filename);
if (tcc_add_dll(s1, filename, 0) < 0)
tcc_error_noabort("%s not found", filename);
tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
}
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
{
if (-1 == tcc_add_library_internal(s1, "%s/%s",
filename, 0, s1->crt_paths, s1->nb_crt_paths))
return tcc_error_noabort("file '%s' not found", filename);
return 0;
return tcc_add_library_internal(s1, "%s/%s",
filename, AFF_PRINT_ERROR, s1->crt_paths, s1->nb_crt_paths);
}
#endif
@ -1285,18 +1231,19 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
#endif
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
while (*pp) {
if (0 == tcc_add_library_internal(s, *pp,
libraryname, flags, s->library_paths, s->nb_library_paths))
return 0;
int ret = tcc_add_library_internal(s, *pp,
libraryname, flags, s->library_paths, s->nb_library_paths);
if (ret != FILE_NOT_FOUND)
return ret;
++pp;
}
return -1;
return FILE_NOT_FOUND;
}
PUB_FUNC int tcc_add_library_err(TCCState *s1, const char *libname)
{
int ret = tcc_add_library(s1, libname);
if (ret < 0)
if (ret == FILE_NOT_FOUND)
tcc_error_noabort("library '%s' not found", libname);
return ret;
}
@ -1790,6 +1737,37 @@ static int set_flag(TCCState *s, const FlagDef *flags, const char *name)
return ret;
}
static const char dumpmachine_str[] =
/* this is a best guess, please refine as necessary */
#ifdef TCC_TARGET_I386
"i386-pc"
#elif defined TCC_TARGET_X86_64
"x86_64-pc"
#elif defined TCC_TARGET_C67
"c67"
#elif defined TCC_TARGET_ARM
"arm"
#elif defined TCC_TARGET_ARM64
"aarch64"
#elif defined TCC_TARGET_RISCV64
"riscv64"
#endif
"-"
#ifdef TCC_TARGET_PE
"mingw32"
#elif defined(TCC_TARGET_MACHO)
"apple-darwin"
#elif TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
"freebsd"
#elif TARGETOS_OpenBSD
"openbsd"
#elif TARGETOS_NetBSD
"netbsd"
#else
"linux-gnu"
#endif
;
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
{
int ret = 0, q, c;
@ -2140,43 +2118,11 @@ dorun:
s->gen_phony_deps = 1;
break;
case TCC_OPTION_dumpmachine:
/* this is a best guess, please refine as necessary */
printf("%s",
#ifdef TCC_TARGET_I386
"i386-pc"
#elif defined TCC_TARGET_X86_64
"x86_64-pc"
#elif defined TCC_TARGET_C67
"c67"
#elif defined TCC_TARGET_ARM
"arm"
#elif defined TCC_TARGET_ARM64
"aarch64"
#elif defined TCC_TARGET_RISCV64
"riscv64"
#endif
"-"
#ifdef TCC_TARGET_PE
"mingw32"
#elif defined(TCC_TARGET_MACHO)
"apple-darwin"
#elif TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
"freebsd"
#elif TARGETOS_OpenBSD
"openbsd"
#elif TARGETOS_NetBSD
"netbsd"
#else
"linux-gnu"
#endif
"\n"
);
printf("%s\n", dumpmachine_str);
exit(0);
break;
case TCC_OPTION_dumpversion:
printf ("%s\n", TCC_VERSION);
exit(0);
break;
case TCC_OPTION_x:
x = 0;
if (*optarg == 'c')

9
tcc.h
View File

@ -1155,6 +1155,7 @@ struct filespec {
#define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */
#define TOK_NOSUBST 0xa5 /* means following token has already been pp'd */
#define TOK_PPJOIN 0xa6 /* A '##' in the right position to mean pasting */
#define TOK_SOTYPE 0xa7 /* alias of '(' for parsing sizeof (type) */
/* assignment operators */
#define TOK_A_ADD 0xb0
@ -1291,6 +1292,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
#define AFF_BINTYPE_AR 3
#define AFF_BINTYPE_C67 4
/* return value of tcc_add_file_internal(): 0, -1, or FILE_NOT_FOUND */
#define FILE_NOT_FOUND -2
#ifndef ELF_OBJ_ONLY
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
#endif
@ -1532,9 +1536,6 @@ ST_FUNC void tccelf_new(TCCState *s);
ST_FUNC void tccelf_delete(TCCState *s);
ST_FUNC void tccelf_begin_file(TCCState *s1);
ST_FUNC void tccelf_end_file(TCCState *s1);
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void tccelf_bounds_new(TCCState *s);
#endif
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
@ -1575,6 +1576,8 @@ ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t
#ifndef ELF_OBJ_ONLY
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
ST_FUNC void tccelf_add_crtbegin(TCCState *s1);
ST_FUNC void tccelf_add_crtend(TCCState *s1);
#endif
#ifndef TCC_TARGET_PE
ST_FUNC void tcc_add_runtime(TCCState *s1);

View File

@ -834,6 +834,10 @@ static void asm_parse_directive(TCCState *s1, int global)
if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
if (sym->c) {
ElfSym *esym = elfsym(sym);
esym->st_info = ELFW(ST_INFO)(ELFW(ST_BIND)(esym->st_info), STT_FUNC);
}
} else
tcc_warning_c(warn_unsupported)("change type of '%s' from 0x%x to '%s' ignored",
get_tok_str(sym->v, NULL), sym->type.t, newtype);

134
tccelf.c
View File

@ -83,17 +83,21 @@ ST_FUNC void tccelf_new(TCCState *s)
".dynstrtab",
".dynhashtab", SHF_PRIVATE);
get_sym_attr(s, 0, 1);
}
if (s->do_debug) {
/* add debug sections */
tcc_debug_new(s);
}
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void tccelf_bounds_new(TCCState *s)
{
TCCState *s1 = s;
/* create bounds sections (make ro after relocation done with GNU_RELRO) */
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
}
if (s->do_bounds_check) {
/* if bound checking, then add corresponding sections */
/* (make ro after relocation done with GNU_RELRO) */
bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
}
#endif
}
static void free_section(Section *s)
{
@ -173,16 +177,22 @@ ST_FUNC void tccelf_end_file(TCCState *s1)
for (i = 0; i < nb_syms; ++i) {
ElfSym *sym = (ElfSym*)s->data + first_sym + i;
if (sym->st_shndx == SHN_UNDEF
&& ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info));
if (sym->st_shndx == SHN_UNDEF) {
int sym_bind = ELFW(ST_BIND)(sym->st_info);
int sym_type = ELFW(ST_TYPE)(sym->st_info);
if (sym_bind == STB_LOCAL)
sym_bind = STB_GLOBAL;
#ifndef TCC_TARGET_PE
/* An ELF relocatable file should have the types of its undefined global symbol set
to STT_NOTYPE or it will confuse binutils bfd */
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF && s1->output_type == TCC_OUTPUT_OBJ)
if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL)
sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(STT_NOTYPE));
if (sym_bind == STB_GLOBAL && s1->output_type == TCC_OUTPUT_OBJ) {
/* undefined symbols with STT_FUNC are confusing gnu ld when
linking statically to STT_GNU_IFUNC */
sym_type = STT_NOTYPE;
}
#endif
sym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
}
tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info,
sym->st_other, sym->st_shndx, (char*)s->link->data + sym->st_name);
}
@ -1666,6 +1676,67 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename)
set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0);
}
#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
/* add libc crt1/crti objects */
ST_FUNC void tccelf_add_crtbegin(TCCState *s1)
{
#if TARGETOS_OpenBSD
if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crt0.o");
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtbeginS.o");
else
tcc_add_crt(s1, "crtbegin.o");
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
if (s1->output_type != TCC_OUTPUT_DLL)
#if TARGETOS_FreeBSD
tcc_add_crt(s1, "crt1.o");
#else
tcc_add_crt(s1, "crt0.o");
#endif
tcc_add_crt(s1, "crti.o");
if (s1->static_link)
tcc_add_crt(s1, "crtbeginT.o");
else if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtbeginS.o");
else
tcc_add_crt(s1, "crtbegin.o");
#elif TARGETOS_ANDROID
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtbegin_so.o");
else
tcc_add_crt(s1, "crtbegin_dynamic.o");
#else
if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crt1.o");
tcc_add_crt(s1, "crti.o");
#endif
}
ST_FUNC void tccelf_add_crtend(TCCState *s1)
{
#if TARGETOS_OpenBSD
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtendS.o");
else
tcc_add_crt(s1, "crtend.o");
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtendS.o");
else
tcc_add_crt(s1, "crtend.o");
tcc_add_crt(s1, "crtn.o");
#elif TARGETOS_ANDROID
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtend_so.o");
else
tcc_add_crt(s1, "crtend_android.o");
#else
tcc_add_crt(s1, "crtn.o");
#endif
}
#endif /* !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO */
#ifndef TCC_TARGET_PE
/* add tcc runtime libraries */
ST_FUNC void tcc_add_runtime(TCCState *s1)
@ -1708,7 +1779,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
if (TCC_LIBGCC[0] == '/')
tcc_add_file(s1, TCC_LIBGCC);
else
tcc_add_dll(s1, TCC_LIBGCC, 0);
tcc_add_dll(s1, TCC_LIBGCC, AFF_PRINT_ERROR);
}
#endif
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
@ -1716,31 +1787,10 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
#endif
if (TCC_LIBTCC1[0])
tcc_add_support(s1, TCC_LIBTCC1);
/* add crt end if not memory output */
if (s1->output_type != TCC_OUTPUT_MEMORY) {
#if defined TCC_TARGET_MACHO
/* nothing to do */
#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
if (s1->output_type & TCC_OUTPUT_DYN)
tcc_add_crt(s1, "crtendS.o");
else
tcc_add_crt(s1, "crtend.o");
tcc_add_crt(s1, "crtn.o");
#elif TARGETOS_OpenBSD
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtendS.o");
else
tcc_add_crt(s1, "crtend.o");
#elif TARGETOS_ANDROID
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_crt(s1, "crtend_so.o");
else
tcc_add_crt(s1, "crtend_android.o");
#else
tcc_add_crt(s1, "crtn.o");
#ifndef TCC_TARGET_MACHO
if (s1->output_type != TCC_OUTPUT_MEMORY)
tccelf_add_crtend(s1);
#endif
}
}
}
#endif /* ndef TCC_TARGET_PE */
@ -3834,7 +3884,7 @@ static int ld_add_file(TCCState *s1, const char filename[])
return 0;
filename = tcc_basename(filename);
}
return tcc_add_dll(s1, filename, 0);
return tcc_add_dll(s1, filename, AFF_PRINT_ERROR);
}
static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)

168
tccgen.c
View File

@ -43,8 +43,6 @@ static int nb_sym_pools;
static Sym *all_cleanups, *pending_gotos;
static int local_scope;
static int in_sizeof;
static int constant_p;
ST_DATA char debug_modes;
ST_DATA SValue *vtop;
@ -130,6 +128,10 @@ typedef struct {
static void init_prec(void);
#endif
static void block(int flags);
#define STMT_EXPR 1
#define STMT_COMPOUND 2
static void gen_cast(CType *type);
static void gen_cast_s(int t);
static inline CType *pointed_type(CType *type);
@ -139,7 +141,6 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
static void parse_expr_type(CType *type);
static void init_putv(init_params *p, CType *type, unsigned long c);
static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags);
static void block(int is_expr, int allow_decl);
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
static int decl(int l);
static void expr_eq(void);
@ -3466,11 +3467,7 @@ static void vpush_type_size(CType *type, int *a)
int size = type_size(type, a);
if (size < 0)
tcc_error("unknown type size");
#if PTR_SIZE == 8
vpushll(size);
#else
vpushi(size);
#endif
vpushs(size);
}
}
@ -4433,11 +4430,11 @@ do_decl:
c = 0;
flexible = 0;
while (tok != '}') {
if (tok == TOK_STATIC_ASSERT) {
do_Static_assert();
continue;
}
if (!parse_btype(&btype, &ad1, 0)) {
if (tok == TOK_STATIC_ASSERT) {
do_Static_assert();
continue;
}
skip(';');
continue;
}
@ -4844,7 +4841,7 @@ static inline void convert_parameter_type(CType *pt)
to indicate a const function parameter */
pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
/* array must be transformed to pointer according to ANSI C */
pt->t &= ~VT_ARRAY;
pt->t &= ~(VT_ARRAY | VT_VLA);
if ((pt->t & VT_BTYPE) == VT_FUNC) {
mk_pointer(pt);
}
@ -5069,7 +5066,8 @@ check:
type->ref = s;
if (vla_array_str) {
if (t1 & VT_VLA)
/* for function args, the top dimension is converted to pointer */
if ((t1 & VT_VLA) && (td & TYPE_NEST))
s->vla_array_str = vla_array_str;
else
tok_str_free_str(vla_array_str);
@ -5435,7 +5433,7 @@ static void parse_atomic(int atok)
ST_FUNC void unary(void)
{
int n, t, align, size, r, sizeof_caller;
int n, t, align, size, r;
CType type;
Sym *s;
AttributeDef ad;
@ -5444,8 +5442,6 @@ ST_FUNC void unary(void)
if (debug_modes)
tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
sizeof_caller = in_sizeof;
in_sizeof = 0;
type.ref = NULL;
/* XXX: GCC 2.95.3 does not generate a table although it should be
better here */
@ -5527,7 +5523,9 @@ ST_FUNC void unary(void)
ad.section = rodata_section;
decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
break;
case TOK_SOTYPE:
case '(':
t = tok;
next();
/* cast ? */
if (parse_btype(&type, &ad, 0)) {
@ -5545,11 +5543,10 @@ ST_FUNC void unary(void)
r |= VT_LVAL;
memset(&ad, 0, sizeof(AttributeDef));
decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
} else if (t == TOK_SOTYPE) { /* from sizeof/alignof (...) */
vpush(&type);
return;
} else {
if (sizeof_caller) {
vpush(&type);
return;
}
unary();
gen_cast(&type);
}
@ -5566,7 +5563,7 @@ ST_FUNC void unary(void)
as statement expressions can't ever be entered from the
outside, so any reactivation of code emission (from labels
or loop heads) can be disabled again after the end of it. */
block(1, 0);
block(STMT_EXPR);
/* If the statement expr can be entered, then we retain the current
nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr).
If it can't be entered then the state is that from before the
@ -5630,8 +5627,9 @@ ST_FUNC void unary(void)
case TOK_ALIGNOF3:
t = tok;
next();
in_sizeof++;
expr_type(&type, unary); /* Perform a in_sizeof = 0; */
if (tok == '(')
tok = TOK_SOTYPE;
expr_type(&type, unary);
if (t == TOK_SIZEOF) {
vpush_type_size(&type, &align);
gen_cast_s(VT_SIZE_T);
@ -5687,11 +5685,12 @@ ST_FUNC void unary(void)
}
break;
case TOK_builtin_constant_p:
constant_p = 1;
parse_builtin_params(1, "e");
n = constant_p &&
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
!((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
n = 1;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
|| ((vtop->r & VT_SYM) && vtop->sym->a.addrtaken)
)
n = 0;
vtop--;
vpushi(n);
break;
@ -5947,10 +5946,10 @@ special_math_val:
default:
tok_identifier:
if (tok < TOK_UIDENT)
tcc_error("expression expected before '%s'", get_tok_str(tok, &tokc));
t = tok;
next();
if (t < TOK_UIDENT)
expect("identifier");
s = sym_find(t);
if (!s || IS_ASM_SYM(s)) {
const char *name = get_tok_str(t, NULL);
@ -6546,13 +6545,19 @@ static void expr_eq(void)
ST_FUNC void gexpr(void)
{
expr_eq();
while (tok == ',') {
constant_p &= (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
!((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
vpop();
next();
expr_eq();
convert_parameter_type (&vtop->type);
if (tok == ',') {
do {
vpop();
next();
expr_eq();
} while (tok == ',');
/* convert array & function to pointer */
convert_parameter_type(&vtop->type);
/* make builtin_constant_p((1,2)) return 0 (like on gcc) */
if ((vtop->r & VT_VALMASK) == VT_CONST && nocode_wanted && !CONST_WANTED)
gv(RC_TYPE(vtop->type.t));
}
}
@ -6908,7 +6913,7 @@ static void lblock(int *bsym, int *csym)
loop_scope = co;
}
co->bsym = bsym;
block(0, 0);
block(0);
co->bsym = b;
if (csym) {
co->csym = c;
@ -6916,13 +6921,13 @@ static void lblock(int *bsym, int *csym)
}
}
static void block(int is_expr, int allow_decl)
static void block(int flags)
{
int a, b, c, d, e, t;
struct scope o;
Sym *s;
if (is_expr) {
if (flags & STMT_EXPR) {
/* default return value is (void) */
vpushi(0);
vtop->type.t = VT_VOID;
@ -6945,12 +6950,12 @@ again:
gexpr();
skip(')');
a = gvtst(1, 0);
block(0, 0);
block(0);
if (tok == TOK_ELSE) {
d = gjmp(0);
gsym(a);
next();
block(0, 0);
block(0);
gsym(d); /* patch else jmp */
} else {
gsym(a);
@ -6991,13 +6996,13 @@ again:
while (tok != '}') {
decl(VT_LOCAL);
if (tok != '}') {
if (is_expr)
if (flags & STMT_EXPR)
vpop();
block(is_expr, 1);
block(flags | STMT_COMPOUND);
}
}
prev_scope(&o, is_expr);
prev_scope(&o, flags & STMT_EXPR);
if (debug_modes)
tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
if (local_scope)
@ -7168,7 +7173,6 @@ again:
cr->sym = gind();
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
skip(':');
is_expr = 0;
goto block_after_label;
} else if (t == TOK_DEFAULT) {
@ -7178,7 +7182,6 @@ again:
tcc_error("too many 'default'");
cur_switch->def_sym = cur_switch->nocode_wanted ? 1 : gind();
skip(':');
is_expr = 0;
goto block_after_label;
} else if (t == TOK_GOTO) {
@ -7253,20 +7256,21 @@ again:
if (debug_modes)
tcc_tcov_reset_ind(tcc_state);
vla_restore(cur_scope->vla.loc);
/* c23 declaration after label */
if (allow_decl && tok != ';')
decl(VT_LOCAL);
if (tok != '}')
goto again;
/* we accept this, but it is a mistake */
tcc_warning_c(warn_all)("deprecated use of label at end of compound statement");
if (tok != '}') {
if (0 == (flags & STMT_COMPOUND))
goto again;
/* C23: insert implicit null-statement whithin compound statement */
} else {
/* we accept this, but it is a mistake */
tcc_warning_c(warn_all)("deprecated use of label at end of compound statement");
}
} else {
/* expression case */
if (t != ';') {
unget_tok(t);
expr:
if (is_expr) {
if (flags & STMT_EXPR) {
vpop();
gexpr();
} else {
@ -8271,8 +8275,8 @@ static void func_vla_arg(Sym *sym)
Sym *arg;
for (arg = sym->type.ref->next; arg; arg = arg->next)
if (arg->type.t & VT_VLA)
func_vla_arg_code(arg);
if ((arg->type.t & VT_BTYPE) == VT_PTR && (arg->type.ref->type.t & VT_VLA))
func_vla_arg_code(arg->type.ref);
}
/* parse a function defined by symbol 'sym' and generate its code in
@ -8316,7 +8320,7 @@ static void gen_function(Sym *sym)
rsym = 0;
clear_temp_local_var_list();
func_vla_arg(sym);
block(0, 0);
block(0);
gsym(rsym);
nocode_wanted = 0;
@ -8424,11 +8428,6 @@ static int decl(int l)
while (1) {
if (tok == TOK_STATIC_ASSERT) {
do_Static_assert();
continue;
}
oldint = 0;
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
if (l == VT_JMP)
@ -8438,6 +8437,10 @@ static int decl(int l)
next();
continue;
}
if (tok == TOK_STATIC_ASSERT) {
do_Static_assert();
continue;
}
if (l != VT_CONST)
break;
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
@ -8633,6 +8636,7 @@ static int decl(int l)
has_init = (tok == '=');
if (has_init && (type.t & VT_VLA))
tcc_error("variable length array cannot be initialized");
if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST))
|| (type.t & VT_BTYPE) == VT_FUNC
/* as with GCC, uninitialized global arrays with no size
@ -8643,20 +8647,6 @@ static int decl(int l)
/* external variable or function */
type.t |= VT_EXTERN;
sym = external_sym(v, &type, r, &ad);
if (ad.alias_target) {
/* Aliases need to be emitted when their target
symbol is emitted, even if perhaps unreferenced.
We only support the case where the base is
already defined, otherwise we would need
deferring to emit the aliases until the end of
the compile unit. */
Sym *alias_target = sym_find(ad.alias_target);
ElfSym *esym = elfsym(alias_target);
if (!esym)
tcc_error("unsupported forward __alias__ attribute");
put_extern_sym2(sym, esym->st_shndx,
esym->st_value, esym->st_size, 1);
}
} else {
if (l == VT_CONST || (type.t & VT_STATIC))
r |= VT_CONST;
@ -8667,18 +8657,22 @@ static int decl(int l)
else if (l == VT_CONST)
/* uninitialized global variables may be overridden */
type.t |= VT_EXTERN;
if (ad.alias_target && 1) {
Sym *alias_target = sym_find(ad.alias_target);
ElfSym *esym = elfsym(alias_target);
if (!esym) tcc_error("unsupported forward __alias__ attribute");
sym = external_sym(v, &type, r, &ad);
put_extern_sym2(sym, esym->st_shndx,
esym->st_value, esym->st_size, 1);
}
decl_initializer_alloc(&type, &ad, r, has_init, v, l == VT_CONST);
}
if (ad.alias_target && l == VT_CONST) {
/* Aliases need to be emitted when their target symbol
is emitted, even if perhaps unreferenced.
We only support the case where the base is already
defined, otherwise we would need deferring to emit
the aliases until the end of the compile unit. */
Sym *alias_target = sym_find(ad.alias_target);
ElfSym *esym = elfsym(alias_target);
if (!esym)
tcc_error("unsupported forward __alias__ attribute");
put_extern_sym2(sym_find(v), esym->st_shndx,
esym->st_value, esym->st_size, 1);
}
}
if (tok != ',') {
if (l == VT_JMP)

View File

@ -35,7 +35,7 @@
# define REL_TYPE_DIRECT R_X86_64_64
# define R_XXX_THUNKFIX R_X86_64_PC32
# define R_XXX_RELATIVE R_X86_64_RELATIVE
# define R_XXX_FUNCCALL R_X86_64_PC32
# define R_XXX_FUNCCALL R_X86_64_PLT32
# define IMAGE_FILE_MACHINE 0x8664
# define RSRC_RELTYPE 3

24
tccpp.c
View File

@ -2960,8 +2960,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
spc = 0;
while (*st >= 0) {
TOK_GET(&t, &st, &cval);
if (t != TOK_PLCHLDR
&& t != TOK_NOSUBST
if (t != TOK_NOSUBST
&& 0 == check_space(t, &spc)) {
const char *s = get_tok_str(t, &cval);
while (*s) {
@ -3004,6 +3003,9 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
str.len--;
goto add_var;
}
} else {
if (*st <= 0) /* expanded to empty string */
tok_str_add(&str, TOK_PLCHLDR);
}
} else {
add_var:
@ -3021,11 +3023,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
}
st = s->next->d;
}
if (*st <= 0) {
/* expanded to empty string */
if (str.len)
tok_str_add(&str, TOK_PLCHLDR);
} else for (;;) {
for (;;) {
int t2;
TOK_GET(&t2, &st, &cval);
if (t2 <= 0)
@ -3135,7 +3133,8 @@ static inline int *macro_twosharps(const int *ptr0)
} else {
start_of_nosubsts = -1;
}
tok_str_add2(&macro_str1, t, &cval);
if (t != TOK_PLCHLDR)
tok_str_add2(&macro_str1, t, &cval);
}
tok_str_add(&macro_str1, 0);
//tok_print(" ###", macro_str1.str);
@ -3154,7 +3153,7 @@ static int next_argstream(Sym **nested_list, TokenString *ws_str)
if (macro_ptr) {
p = macro_ptr, t = *p;
if (ws_str) {
while (is_space(t) || TOK_LINEFEED == t || TOK_PLCHLDR == t)
while (is_space(t) || TOK_LINEFEED == t)
tok_str_add(ws_str, t), t = *++p;
}
if (t == 0) {
@ -3289,7 +3288,7 @@ static int macro_subst_tok(
}
do {
next_nomacro(); /* eat '(' */
} while (tok == TOK_PLCHLDR || is_space(tok));
} while (is_space(tok));
/* argument macro */
args = NULL;
@ -3298,8 +3297,7 @@ static int macro_subst_tok(
for(;;) {
do {
next_argstream(nested_list, NULL);
} while (tok == TOK_PLCHLDR || is_space(tok) ||
TOK_LINEFEED == tok);
} while (is_space(tok) || TOK_LINEFEED == tok);
empty_arg:
/* handle '()' case */
if (!args && !sa && tok == ')')
@ -3488,7 +3486,7 @@ ST_FUNC void next(void)
t = tok;
if (macro_ptr) {
if (!TOK_HAS_VALUE(t)) {
if (t == TOK_NOSUBST || t == TOK_PLCHLDR) {
if (t == TOK_NOSUBST) {
/* discard preprocessor markers */
goto redo;
} else if (t == 0) {

View File

@ -263,8 +263,11 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
/* These aren't C symbols, so don't need leading underscore handling. */
run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
if (!(ret = setjmp(rc->jb)))
ret = setjmp(rc->jb);
if (0 == ret)
ret = prog_main(argc, argv, envp);
else if (256 == ret)
ret = 0;
run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
run_on_exit(ret);
if (s1->dflag & 16 && ret) /* tcc -dt -run ... */

View File

@ -13,3 +13,18 @@
X181 M_EMPTYI_P_C1()
X182 M_EMPTYI_P_C1(x)
X183 usefnlike()
#define ABC(x) ABC : x
#define A(a,b,c) a ## b ## c
#define B(a,b,c) A(a,b,c)
#define C(a,b,c) a b c
B(
C(A,C(,,),),
C(B(,,),B,B(,,)),
C(B(,,),B(,,),C)
)/* */(a b c)
#define TEST(x) TEST : x
#define K(a,b) a ## b
#define L(a,b) K( TE a , b ST )
L(,)(t e s t)

View File

@ -1,3 +1,5 @@
X181 1
X182 0
X183 yeah
ABC : a b c
TEST : t e s t

View File

@ -1,117 +0,0 @@
#define M_DEFERRED_COMMA ,
#define M_EAT(...)
#define M_APPLY(a, ...) a (__VA_ARGS__)
#define M_ID(...) __VA_ARGS__
#define M_C2I(a, ...) a ## __VA_ARGS__
#define M_C(a, ...) M_C2I(a, __VA_ARGS__)
#define M_C3I(a, b, ...) a ## b ## __VA_ARGS__
#define M_C3(a, b, ...) M_C3I(a ,b, __VA_ARGS__)
#define M_C4I(a, b, c, ...) a ## b ## c ## __VA_ARGS__
#define M_C4(a, b, c, ...) M_C4I(a ,b, c, __VA_ARGS__)
#define M_INVI_0 1
#define M_INVI_1 0
#define M_INV(x) M_C(M_INVI_, x)
#define M_ANDI_00 0
#define M_ANDI_01 0
#define M_ANDI_10 0
#define M_ANDI_11 1
#define M_AND(x,y) M_C3(M_ANDI_, x, y)
#define M_ANDI_000 0
#define M_ANDI_001 0
#define M_ANDI_010 0
#define M_ANDI_011 0
#define M_ANDI_100 0
#define M_ANDI_101 0
#define M_ANDI_110 0
#define M_ANDI_111 1
#define M_AND3(x,y,z) M_C4(M_ANDI_, x, y, z)
#define M_ORI_00 0
#define M_ORI_01 1
#define M_ORI_10 1
#define M_ORI_11 1
#define M_OR(x,y) M_C3(M_ORI_, x, y)
#define M_ORI_000 0
#define M_ORI_001 1
#define M_ORI_010 1
#define M_ORI_011 1
#define M_ORI_100 1
#define M_ORI_101 1
#define M_ORI_110 1
#define M_ORI_111 1
#define M_OR3(x,y,z) M_C4(M_ORI_, x, y, z)
#define M_RETI_ARG2(_1, _2, ...) _2
#define M_RET_ARG2(...) M_RETI_ARG2(__VA_ARGS__,)
#define M_RETI_ARG4(_1, _2, _3, _4, ...) _4
#define M_RET_ARG4(...) M_RETI_ARG4(__VA_ARGS__,)
#define M_TOBOOLI_0 1, 0,
#define M_BOOL(x) M_RET_ARG2(M_C(M_TOBOOLI_, x), 1, useless)
#define M_IFI_0(true_c, ...) __VA_ARGS__
#define M_IFI_1(true_c, ...) true_c
#define M_IF(c) M_C(M_IFI_, M_BOOL(c))
#define M_NARGS(...) M_RET_ARG4(__VA_ARGS__, 3, 2, 1, useless)
#define M_MAP(...) M_MAP_0(__VA_ARGS__)
#define M_MAP_0(f, ...) M_C(M_MAP_, M_NARGS(__VA_ARGS__))(f, __VA_ARGS__)
#define M_MAP_1(f, _1) f(_1)
#define M_MAP_2(f, _1, _2) f(_1) f(_2)
#define M_MAP_3(f, _1, _2, _3) f(_1) f(_2) f(_3)
#define M_MAP2(...) M_MAP2I_0(__VA_ARGS__)
#define M_MAP2I_0(f, d, ...) M_C(M_MAP2I_, M_NARGS(__VA_ARGS__))(f, d, __VA_ARGS__)
#define M_MAP2I_1(f, d, _1) f(d, _1)
#define M_MAP2I_2(f, d, _1, _2) f(d, _1) f(d, _2)
#define M_MAP2I_3(f, d, _1, _2, _3) f(d, _1) f(d, _2) f(d, _3)
#define M_CROSS_MAP(f, alist, blist) M_CROSSI_MAP1(f, alist, blist)
#define M_CROSSI_MAP1(f, alist, blist) M_C(M_CROSSI_MAP1_, M_NARGS alist)(f, blist, M_ID alist)
#define M_CROSSI_MAP1_1(...) M_CROSSI_MAP1_1b(__VA_ARGS__)
#define M_CROSSI_MAP1_1b(f, blist, a1) M_MAP2(f, a1, M_ID blist)
#define M_CROSSI_MAP1_2(...) M_CROSSI_MAP1_2b(__VA_ARGS__)
#define M_CROSSI_MAP1_2b(f, blist, a1, a2) M_MAP2(f, a1, M_ID blist) M_MAP2(f, a2, M_ID blist)
#define M_CROSSI_MAP1_3(...) M_CROSSI_MAP1_3b(__VA_ARGS__)
#define M_CROSSI_MAP1_3b(f, blist, a1, a2, a3) M_MAP2(f, a1, M_ID blist) M_MAP2(f, a2, M_ID blist) M_MAP2(f, a3, M_ID blist)
#define M_COMMA_P(...) M_RETI_ARG4(__VA_ARGS__, 1, 1, 0, useless)
#define M_PARENTHESISI_DETECT1(...) ,
#define M_PARENTHESIS_P(...) \
M_AND3(M_COMMA_P(M_PARENTHESISI_DETECT1 __VA_ARGS__), \
M_INV(M_COMMA_P(__VA_ARGS__)), \
M_EMPTY_P(M_EAT __VA_ARGS__))
#define M_EMPTYI_DETECT(...) ,
#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ () )
#define M_EMPTYI_P_C2(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__)
#define M_EMPTYI_P_C3(...) M_COMMA_P(__VA_ARGS__ () )
#define M_EMPTY_P(...) M_AND(M_EMPTYI_P_C1(__VA_ARGS__), M_INV(M_OR3(M_EMPTYI_P_C2(__VA_ARGS__), M_COMMA_P(__VA_ARGS__),M_EMPTYI_P_C3(__VA_ARGS__))))
#define M_G3N_IS_PRESENT(num) \
M_IF(M_PARENTHESIS_P(M_C(M_GENERIC_ORG_, num)() ))(M_DEFERRED_COMMA M_ID M_C(M_GENERIC_ORG_, num)(), )
#define M_G3N_IS_PRESENT2(el1, num) \
M_IF(M_PARENTHESIS_P(M_C4(M_GENERIC_ORG_, el1, _COMP_, num)()))(M_DEFERRED_COMMA M_APPLY(M_C3, el1, _COMP_, M_ID M_C4(M_GENERIC_ORG_, el1, _COMP_, num)()), )
#define FLT1 (GENTYPE(float), TYPE(float) )
#define M_GENERIC_ORG_2() (USER)
#define M_GENERIC_ORG_USER_COMP_1() (CORE)
#define M_GENERIC_ORG_USER_COMP_CORE_OPLIST_6() FLT1
// Shall expand to ", USER"
M_MAP(M_G3N_IS_PRESENT, 1, 2, 3)
// Shall expand to ", USER_COMP_CORE"
M_CROSS_MAP(M_G3N_IS_PRESENT2, (MLIB , USER), ( 1, 2, 3 ) )
// Shall expand to ", USER_COMP_CORE" (composition of both) [fail]
M_CROSS_MAP(M_G3N_IS_PRESENT2, (MLIB M_MAP(M_G3N_IS_PRESENT, 1, 2, 3)), ( 1, 2, 3 ) )

View File

@ -1,3 +0,0 @@
, USER
, USER_COMP_CORE
, USER_COMP_CORE

View File

@ -140,11 +140,6 @@ static int onetwothree = 123;
#define B3 4
#endif
#ifdef __TINYC__
/* We try to handle this syntax. Make at least sure it doesn't segfault. */
char invalid_function_def()[] {return 0;}
#endif
#define __INT64_C(c) c ## LL
#define INT64_MIN (-__INT64_C(9223372036854775807)-1)
@ -341,18 +336,13 @@ static struct recursive_macro { int rm_field; } G;
WRAP((printf("rm_field = %d %d\n", rm_field, WRAP(rm_field))));
}
#if !defined(__TINYC__) && (__GNUC__ >= 14 || __clang_major__ >= 15)
#define IMPLICIT_INT int
#else
#define IMPLICIT_INT
#endif
int op(IMPLICIT_INT a, IMPLICIT_INT b)
#if __TINYC__
int op(a, b)
{
return a / b;
}
int ret(IMPLICIT_INT a)
int ret(a)
{
if (a == 2)
return 1;
@ -360,6 +350,7 @@ int ret(IMPLICIT_INT a)
return 2;
return 0;
}
#endif
#if !defined(__TINYC__) && (__GNUC__ >= 8)
/* Old GCCs don't regard "foo"[1] as constant, even in GNU dialect. */
@ -716,7 +707,7 @@ int tab2[3][2];
int g;
void f1(IMPLICIT_INT g)
void f1(int g)
{
printf("g1=%d\n", g);
}
@ -1511,25 +1502,35 @@ void compound_literal_test(void)
#endif
}
#if __TINYC__
/* K & R protos */
IMPLICIT_INT kr_func1(IMPLICIT_INT a, IMPLICIT_INT b)
kr_func1(a, b)
{
return a + b;
}
int kr_func2(IMPLICIT_INT a, IMPLICIT_INT b)
int kr_func2(a, b)
{
return a + b;
}
IMPLICIT_INT kr_test()
kr_test()
{
printf("func1=%d\n", kr_func1(3, 4));
printf("func2=%d\n", kr_func2(3, 4));
return 0;
}
/* We try to handle this syntax. Make at least sure it doesn't segfault. */
char invalid_function_def()[] {return 0;}
#else
# define kr_test() printf("func1=7\nfunc2=7\n")
#endif
void num(int n)
{
char *tab, *p;
@ -2058,7 +2059,7 @@ void c99_bool_test(void)
printf("b = %d\n", b);
b2 = 0;
printf("sizeof(x ? _Bool : _Bool) = %d (should be sizeof int)\n",
sizeof((volatile IMPLICIT_INT)a ? b : b2));
sizeof ((volatile int)a ? b : b2));
#endif
}
@ -3062,7 +3063,7 @@ void c99_vla_test_3d(int s, int arr[2][3][s])
void c99_vla_test_3e(int s, int arr[][3][--s])
{
printf ("%d %d\n", s, arr[1][2][3]);
printf ("%d %d %d\n", sizeof arr, s, arr[1][2][3]);
}
void c99_vla_test_3(void)
@ -3145,6 +3146,10 @@ void sizeof_test(void)
printf("sizeof(1 && 1) = %d\n", sizeof(1 && 1));
printf("sizeof(t || 1) = %d\n", sizeof(t || 1));
printf("sizeof(0 || 0) = %d\n", sizeof(0 || 0));
int arr[4], fn();
printf("sizeof(0, arr) = %d\n", sizeof(0, arr));
printf("sizeof(0, fn) = %d\n", sizeof(0, fn));
}
void typeof_test(void)
@ -3915,30 +3920,29 @@ void builtin_test(void)
COMPAT_TYPE(char *, unsigned char *);
COMPAT_TYPE(char *, signed char *);
COMPAT_TYPE(char *, char *);
/* space is needed because tcc preprocessor introduces a space between each token */
COMPAT_TYPE(char * *, void *);
COMPAT_TYPE(char **, void *);
#endif
printf("res1 = %d\n", __builtin_constant_p(1));
printf("res2 = %d\n", __builtin_constant_p(1 + 2));
printf("res3 = %d\n", __builtin_constant_p(&constant_p_var));
printf("res4 = %d\n", __builtin_constant_p(constant_p_var));
printf("res5 = %d\n", __builtin_constant_p(100000 / constant_p_var));
#ifdef __clang__
/* clang doesn't regard this as constant expression */
printf("res6 = 1\n");
printf("res6 = %d\n", __builtin_constant_p(i && 1));
printf("res7 = %d\n", __builtin_constant_p("hi"));
printf("res8 = %d\n", __builtin_constant_p(func()));
#ifndef __clang__
printf("res10 = %d\n", __builtin_constant_p(i && 0));
printf("res11 = %d\n", __builtin_constant_p(i * 0));
printf("res12 = %d\n", __builtin_constant_p(i && 0 ? i : 34));
printf("res13 = %d\n", __builtin_constant_p((1,7)));
#else
printf("res6 = %d\n", __builtin_constant_p(i && 0));
/* clang doesn't regard these as constant expression */
printf("res10 = 1\n");
printf("res11 = 1\n");
printf("res12 = 1\n");
printf("res13 = 0\n");
#endif
printf("res7 = %d\n", __builtin_constant_p(i && 1));
#ifdef __clang__
/* clang doesn't regard this as constant expression */
printf("res8 = 1\n");
#else
printf("res8 = %d\n", __builtin_constant_p(i && 0 ? i : 34));
#endif
printf("res9 = %d\n", __builtin_constant_p("hi"));
printf("res10 = %d\n", __builtin_constant_p(func()));
printf("res11 = %d\n", __builtin_constant_p((i++, 7)));
s = 1;
ll = 2;
i = __builtin_choose_expr (1 != 0, ll, s);

View File

@ -14,8 +14,7 @@ int main()
break;
case 2:
int a = 2;
printf("%d\n", a);
printf("%d\n", 2);
break;
default:

View File

@ -2,14 +2,17 @@ extern int printf (const char *, ...);
extern void target(void);
extern void alias_for_target(void);
extern void asm_for_target(void);
extern int g_int, alias_int;
void inunit2(void);
void inunit2(void)
{
printf("in unit2:\n");
target();
alias_for_target();
/* This symbol is not supposed to be available in this unit:
asm_for_target();
*/
printf("g_int = %d\nalias_int = %d\n", g_int, alias_int);
}

View File

@ -1,17 +1,24 @@
/* Check semantics of various constructs to generate renamed symbols. */
extern int printf (const char *, ...);
void target(void);
void target(void) {
printf("in target function\n");
}
void alias_for_target(void) __attribute__((alias("target")));
int g_int = 34;
int alias_int __attribute__((alias("g_int")));
#ifdef __leading_underscore
void asm_for_target(void) __asm__("_target");
# define _ "_"
#else
void asm_for_target(void) __asm__("target");
# define _
#endif
void asm_for_target(void) __asm__(_"target");
int asm_int __asm__(_"g_int");
/* This is not supposed to compile, alias targets must be defined in the
same unit. In TCC they even must be defined before the reference
void alias_for_undef(void) __attribute__((alias("undefined")));
@ -24,6 +31,7 @@ int main(void)
target();
alias_for_target();
asm_for_target();
printf("g_int = %d\nalias_int = %d\nasm_int = %d\n", g_int, alias_int, asm_int);
inunit2();
return 0;
}

View File

@ -1,5 +1,11 @@
in target function
in target function
in target function
g_int = 34
alias_int = 34
asm_int = 34
in unit2:
in target function
in target function
g_int = 34
alias_int = 34

View File

@ -68,7 +68,7 @@
60_errors_and_warnings.c:148: error: identifier expected
[test_invalid_1]
60_errors_and_warnings.c:153: error: identifier expected
60_errors_and_warnings.c:153: error: expression expected before ','
[test_invalid_2]
60_errors_and_warnings.c:156: error: ';' expected (got "{")

View File

@ -646,11 +646,7 @@ static void gcall_or_jmp(int is_jmp)
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) {
/* constant symbolic case -> simple relocation */
#ifdef TCC_TARGET_PE
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4));
#else
greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
#endif
oad(0xe8 + is_jmp, 0); /* call/jmp im */
} else {
/* otherwise, indirect call */
@ -668,11 +664,7 @@ static void gen_bounds_call(int v)
{
Sym *sym = external_helper_sym(v);
oad(0xe8, 0);
#ifdef TCC_TARGET_PE
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
#else
greloca(cur_text_section, sym, ind-4, R_X86_64_PLT32, -4);
#endif
}
#ifdef TCC_TARGET_PE
@ -1046,7 +1038,7 @@ void gfunc_epilog(void)
Sym *sym = external_helper_sym(TOK___chkstk);
oad(0xb8, v); /* mov stacksize, %eax */
oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
greloca(cur_text_section, sym, ind-4, R_X86_64_PLT32, -4);
o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
} else {
o(0xe5894855); /* push %rbp, mov %rsp, %rbp */