summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrischka <grischka>2024-02-04 17:38:23 +0100
committergrischka <grischka>2024-02-04 18:18:40 +0100
commitda0d43903b2b31b935188847d6739306ab998e13 (patch)
tree2268afd4f0c01b8f08129fbe3f79fd66790be768
parent6426cc3384cf953d5f3b95cb2f7259a63e78b653 (diff)
review recent commits
tccpp.c: - revert "Preprocessor fix + new testcase" Fix was not a fix and nobody could understand the test. This reverts 6379f2ee76ac8d95c413f78b56e31a560e14ac6e - 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 08c777053cb3b7f4f5d33bb0beeb82787d30ebe0) - 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 7f0a28f6ca026a0b2b50282a2168346eef668651 tccelf.c: - rework "...make undefined global symbol STT_NOTYPE" (See f44060f8fcdfa9a21bb63476cf2758d497a053b9) - 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 6b967b1285704db13188895d86e7b3b34c3d2ff4) Makefile: - macOS version also - add cross searchpaths for packages build.yml: - disable codesign on macos-11 (doesn't seem to work)
-rw-r--r--.github/workflows/build.yml4
-rw-r--r--Makefile10
-rwxr-xr-xconfigure6
-rw-r--r--i386-asm.c6
-rw-r--r--include/tccdefs.h18
-rw-r--r--libtcc.c166
-rw-r--r--tcc.h9
-rw-r--r--tccasm.c4
-rw-r--r--tccelf.c134
-rw-r--r--tccgen.c168
-rw-r--r--tccpe.c2
-rw-r--r--tccpp.c24
-rw-r--r--tccrun.c5
-rw-r--r--tests/pp/18.c15
-rw-r--r--tests/pp/18.expect2
-rw-r--r--tests/pp/23.c117
-rw-r--r--tests/pp/23.expect3
-rw-r--r--tests/tcctest.c74
-rw-r--r--tests/tests2/06_case.c3
-rw-r--r--tests/tests2/120+_alias.c3
-rw-r--r--tests/tests2/120_alias.c14
-rw-r--r--tests/tests2/120_alias.expect6
-rw-r--r--tests/tests2/60_errors_and_warnings.expect2
-rw-r--r--x86_64-gen.c10
24 files changed, 360 insertions, 445 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e3c1b24..885b310 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -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
diff --git a/Makefile b/Makefile
index 98d65f6..e6404d5 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/configure b/configure
index 799973b..062d0e3 100755
--- a/configure
+++ b/configure
@@ -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";;
diff --git a/i386-asm.c b/i386-asm.c
index 3cc8d18..e134d80 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -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
+
}
}
diff --git a/include/tccdefs.h b/include/tccdefs.h
index 8c173f0..8ec6464 100644
--- a/include/tccdefs.h
+++ b/include/tccdefs.h
@@ -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__
diff --git a/libtcc.c b/libtcc.c
index 71b8d36..35002b6 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -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')
diff --git a/tcc.h b/tcc.h
index e417386..c36f2a6 100644
--- a/tcc.h
+++ b/tcc.h
@@ -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);
diff --git a/tccasm.c b/tccasm.c
index fcae05e..19f778d 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -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);
diff --git a/tccelf.c b/tccelf.c
index 8f1d964..93a46ba 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -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)
diff --git a/tccgen.c b/tccgen.c
index 688557e..fb19250 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -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)
diff --git a/tccpe.c b/tccpe.c
index 11ec6df..06d817d 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -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
diff --git a/tccpp.c b/tccpp.c
index dc68dc1..4c4f6e0 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -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) {
diff --git a/tccrun.c b/tccrun.c
index b102d82..3ad9a41 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -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 ... */
diff --git a/tests/pp/18.c b/tests/pp/18.c
index 0961426..de47790 100644
--- a/tests/pp/18.c
+++ b/tests/pp/18.c
@@ -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)
diff --git a/tests/pp/18.expect b/tests/pp/18.expect
index 447a9b2..a8d1a4c 100644
--- a/tests/pp/18.expect
+++ b/tests/pp/18.expect
@@ -1,3 +1,5 @@
X181 1
X182 0
X183 yeah
+ABC : a b c
+TEST : t e s t
diff --git a/tests/pp/23.c b/tests/pp/23.c
deleted file mode 100644
index 1df233f..0000000
--- a/tests/pp/23.c
+++ /dev/null
@@ -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 ) )
diff --git a/tests/pp/23.expect b/tests/pp/23.expect
deleted file mode 100644
index 303e410..0000000
--- a/tests/pp/23.expect
+++ /dev/null
@@ -1,3 +0,0 @@
- , USER
- , USER_COMP_CORE
- , USER_COMP_CORE
diff --git a/tests/tcctest.c b/tests/tcctest.c
index b81cf5a..f03a940 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -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");
-#else
- printf("res6 = %d\n", __builtin_constant_p(i && 0));
-#endif
- printf("res7 = %d\n", __builtin_constant_p(i && 1));
-#ifdef __clang__
- /* clang doesn't regard this as constant expression */
- printf("res8 = 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("res8 = %d\n", __builtin_constant_p(i && 0 ? i : 34));
+ /* 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("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);
diff --git a/tests/tests2/06_case.c b/tests/tests2/06_case.c
index 75b8d45..c0191e2 100644
--- a/tests/tests2/06_case.c
+++ b/tests/tests2/06_case.c
@@ -14,8 +14,7 @@ int main()
break;
case 2:
- int a = 2;
- printf("%d\n", a);
+ printf("%d\n", 2);
break;
default:
diff --git a/tests/tests2/120+_alias.c b/tests/tests2/120+_alias.c
index 8f29d8d..56db69d 100644
--- a/tests/tests2/120+_alias.c
+++ b/tests/tests2/120+_alias.c
@@ -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);
}
diff --git a/tests/tests2/120_alias.c b/tests/tests2/120_alias.c
index 5bead0f..35bd44f 100644
--- a/tests/tests2/120_alias.c
+++ b/tests/tests2/120_alias.c
@@ -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;
}
diff --git a/tests/tests2/120_alias.expect b/tests/tests2/120_alias.expect
index 021e3f0..52099d0 100644
--- a/tests/tests2/120_alias.expect
+++ b/tests/tests2/120_alias.expect
@@ -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
diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect
index 25a7624..18e8fc6 100644
--- a/tests/tests2/60_errors_and_warnings.expect
+++ b/tests/tests2/60_errors_and_warnings.expect
@@ -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 "{")
diff --git a/x86_64-gen.c b/x86_64-gen.c
index e04df10..4f46efc 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -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 */