mirror of
git://repo.or.cz/tinycc.git
synced 2026-11-04 21:26:36 +08:00
stdatomics: tidy & cleanup
- remove any error messages that were just for debugging the templates really - don't use c99 in tcc (array designators etc.) - remove memory model type (cannot be an own type really) and move memory model defines from built-in to stdatomics.h - apply normal casts to non-pointer atomic_function arguments - tidy the library support - add some tests for errors/warnings Also: - Makefile: move GIT_HASH stuff from CFLAGS to DEFINES and into main section (away from what is included by tests for example) - tccelf.c/tccgen.c: avoid some warnings with newer GCC
This commit is contained in:
parent
4bb3b3cec7
commit
48df89e10e
13
Makefile
13
Makefile
@ -24,13 +24,6 @@ CFLAGS += -I$(TOP)
|
|||||||
CFLAGS += $(CPPFLAGS)
|
CFLAGS += $(CPPFLAGS)
|
||||||
VPATH = $(TOPSRC)
|
VPATH = $(TOPSRC)
|
||||||
|
|
||||||
TCC_GIT_HASH=$(shell git rev-parse > /dev/null 2>&1 && git rev-parse --short HEAD || echo no)
|
|
||||||
|
|
||||||
ifneq ($(TCC_GIT_HASH),no)
|
|
||||||
MODIFIED = $(shell git diff | grep --quiet +++ && echo "modified ")
|
|
||||||
CFLAGS += -DTCC_GIT_HASH="\"$(MODIFIED)$(TCC_GIT_HASH)\""
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_WIN32
|
ifdef CONFIG_WIN32
|
||||||
CFG = -win
|
CFG = -win
|
||||||
ifneq ($(CONFIG_static),yes)
|
ifneq ($(CONFIG_static),yes)
|
||||||
@ -229,6 +222,12 @@ $(TCC_FILES) : DEFINES += -DONE_SOURCE=0
|
|||||||
$(X)tccpp.o : $(TCCDEFS_H)
|
$(X)tccpp.o : $(TCCDEFS_H)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
TCC_GIT_HASH=$(shell git rev-parse > /dev/null 2>&1 && git rev-parse --short HEAD || echo no)
|
||||||
|
ifneq ($(TCC_GIT_HASH),no)
|
||||||
|
MODIFIED = $(shell git diff | grep --quiet +++ && echo "modified ")
|
||||||
|
$(X)tcc.o : DEFINES += += -DTCC_GIT_HASH="\"$(MODIFIED)$(TCC_GIT_HASH)\""
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_debug),yes)
|
ifeq ($(CONFIG_debug),yes)
|
||||||
CFLAGS += -g
|
CFLAGS += -g
|
||||||
LDFLAGS += -g
|
LDFLAGS += -g
|
||||||
|
|||||||
@ -15,6 +15,13 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define __ATOMIC_RELAXED 0
|
||||||
|
#define __ATOMIC_CONSUME 1
|
||||||
|
#define __ATOMIC_ACQUIRE 2
|
||||||
|
#define __ATOMIC_RELEASE 3
|
||||||
|
#define __ATOMIC_ACQ_REL 4
|
||||||
|
#define __ATOMIC_SEQ_CST 5
|
||||||
|
|
||||||
/* Memory ordering */
|
/* Memory ordering */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
memory_order_relaxed = __ATOMIC_RELAXED,
|
memory_order_relaxed = __ATOMIC_RELAXED,
|
||||||
|
|||||||
@ -78,13 +78,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __ATOMIC_RELAXED 0
|
|
||||||
#define __ATOMIC_CONSUME 1
|
|
||||||
#define __ATOMIC_ACQUIRE 2
|
|
||||||
#define __ATOMIC_RELEASE 3
|
|
||||||
#define __ATOMIC_ACQ_REL 4
|
|
||||||
#define __ATOMIC_SEQ_CST 5
|
|
||||||
|
|
||||||
#if defined _WIN32
|
#if defined _WIN32
|
||||||
#define __declspec(x) __attribute__((x))
|
#define __declspec(x) __attribute__((x))
|
||||||
#define __cdecl
|
#define __cdecl
|
||||||
|
|||||||
@ -42,8 +42,8 @@ $(X)BT_O += tcov.o
|
|||||||
|
|
||||||
DSO_O = dsohandle.o
|
DSO_O = dsohandle.o
|
||||||
|
|
||||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) atomic-i386.o
|
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O) stdatomic.o
|
||||||
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) atomic-x86_64.o
|
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O) stdatomic.o
|
||||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o fetch_and_add_arm.o $(BT_O)
|
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o fetch_and_add_arm.o $(BT_O)
|
||||||
ARM64_O = lib-arm64.o fetch_and_add_arm64.o $(BT_O)
|
ARM64_O = lib-arm64.o fetch_and_add_arm64.o $(BT_O)
|
||||||
RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O)
|
RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O)
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
#include "atomic.h"
|
|
||||||
|
|
||||||
ATOMIC_EXCHANGE(uint8_t, 1)
|
|
||||||
ATOMIC_EXCHANGE(uint16_t, 2)
|
|
||||||
ATOMIC_EXCHANGE(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_ADD(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_ADD(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_ADD(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_SUB(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_SUB(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_SUB(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_AND(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_AND(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_AND(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_OR(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_OR(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_OR(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_FETCH_XOR(uint8_t, 1)
|
|
||||||
ATOMIC_FETCH_XOR(uint16_t, 2)
|
|
||||||
ATOMIC_FETCH_XOR(uint32_t, 4)
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
#include "atomic.h"
|
|
||||||
|
|
||||||
ATOMIC_EXCHANGE(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_ADD(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_SUB(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_AND(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_OR(uint64_t, 8)
|
|
||||||
ATOMIC_FETCH_XOR(uint64_t, 8)
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "atomic-x86.h"
|
|
||||||
|
|
||||||
ATOMIC_X86_STORE(uint8_t, 1)
|
|
||||||
ATOMIC_X86_STORE(uint16_t, 2)
|
|
||||||
ATOMIC_X86_STORE(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_X86_LOAD(uint8_t, 1)
|
|
||||||
ATOMIC_X86_LOAD(uint16_t, 2)
|
|
||||||
ATOMIC_X86_LOAD(uint32_t, 4)
|
|
||||||
|
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint8_t, 1, "b")
|
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint16_t, 2, "w")
|
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint32_t, 4, "l")
|
|
||||||
|
|
||||||
#include "atomic-gen32.c"
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define ATOMIC_X86_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
|
||||||
bool __atomic_compare_exchange_##MODE(_Atomic(TYPE) *atom, TYPE *ref, TYPE xchg) \
|
|
||||||
{ \
|
|
||||||
TYPE rv; \
|
|
||||||
TYPE cmp = *ref; \
|
|
||||||
asm volatile( \
|
|
||||||
"lock cmpxchg" SUFFIX " %2,%1\n" \
|
|
||||||
: "=a" (rv), "+m" (*atom) \
|
|
||||||
: "q" (xchg), "0" (cmp) \
|
|
||||||
: "memory" \
|
|
||||||
); \
|
|
||||||
*ref = rv; \
|
|
||||||
return (rv == cmp); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ATOMIC_X86_LOAD(TYPE, MODE) \
|
|
||||||
TYPE __atomic_load_##MODE(const _Atomic(TYPE) *atom) \
|
|
||||||
{ \
|
|
||||||
return *(volatile TYPE *)atom; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ATOMIC_X86_STORE(TYPE, MODE) \
|
|
||||||
void __atomic_store_##MODE(_Atomic(TYPE) *atom, TYPE value) \
|
|
||||||
{ \
|
|
||||||
*(volatile TYPE *)atom = value; \
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "atomic-x86.h"
|
|
||||||
#include "atomic-i386.c"
|
|
||||||
|
|
||||||
ATOMIC_X86_STORE(uint64_t, 8)
|
|
||||||
ATOMIC_X86_LOAD(uint64_t, 8)
|
|
||||||
ATOMIC_X86_COMPARE_EXCHANGE(uint64_t, 8, "q")
|
|
||||||
|
|
||||||
#include "atomic-gen64.c"
|
|
||||||
39
lib/atomic.h
39
lib/atomic.h
@ -1,39 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP) \
|
|
||||||
TYPE __atomic_##NAME##_##MODE(_Atomic(TYPE) *atom, TYPE value) \
|
|
||||||
{ \
|
|
||||||
TYPE xchg; \
|
|
||||||
TYPE cmp = __atomic_load(atom, __ATOMIC_RELAXED); \
|
|
||||||
do { \
|
|
||||||
xchg = (OP); \
|
|
||||||
} while (!__atomic_compare_exchange(atom, &cmp, xchg, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); \
|
|
||||||
return cmp; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ATOMIC_EXCHANGE
|
|
||||||
# define ATOMIC_EXCHANGE(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, exchange, value)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ATOMIC_FETCH_ADD
|
|
||||||
# define ATOMIC_FETCH_ADD(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_add, (cmp + value))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ATOMIC_FETCH_SUB
|
|
||||||
# define ATOMIC_FETCH_SUB(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_sub, (cmp - value))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ATOMIC_FETCH_AND
|
|
||||||
# define ATOMIC_FETCH_AND(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_and, (cmp & value))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ATOMIC_FETCH_OR
|
|
||||||
# define ATOMIC_FETCH_OR(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_or, (cmp | value))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ATOMIC_FETCH_XOR
|
|
||||||
# define ATOMIC_FETCH_XOR(TYPE, MODE) ATOMIC_GEN_OP(TYPE, MODE, fetch_xor, (cmp ^ value))
|
|
||||||
#endif
|
|
||||||
113
lib/stdatomic.c
Normal file
113
lib/stdatomic.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// for libtcc1, avoid including files that are not part of tcc
|
||||||
|
// #include <stdint.h>
|
||||||
|
#define uint8_t unsigned char
|
||||||
|
#define uint16_t unsigned short
|
||||||
|
#define uint32_t unsigned int
|
||||||
|
#define uint64_t unsigned long long
|
||||||
|
#define bool _Bool
|
||||||
|
#define true 1
|
||||||
|
#define __ATOMIC_RELAXED 0
|
||||||
|
#define __ATOMIC_CONSUME 1
|
||||||
|
#define __ATOMIC_ACQUIRE 2
|
||||||
|
#define __ATOMIC_RELEASE 3
|
||||||
|
#define __ATOMIC_ACQ_REL 4
|
||||||
|
#define __ATOMIC_SEQ_CST 5
|
||||||
|
|
||||||
|
#define ATOMIC_X86_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
|
||||||
|
bool __atomic_compare_exchange_##MODE(_Atomic(TYPE) *atom, TYPE *ref, TYPE xchg) \
|
||||||
|
{ \
|
||||||
|
TYPE rv; \
|
||||||
|
TYPE cmp = *ref; \
|
||||||
|
asm volatile( \
|
||||||
|
"lock cmpxchg" SUFFIX " %2,%1\n" \
|
||||||
|
: "=a" (rv), "+m" (*atom) \
|
||||||
|
: "q" (xchg), "0" (cmp) \
|
||||||
|
: "memory" \
|
||||||
|
); \
|
||||||
|
*ref = rv; \
|
||||||
|
return (rv == cmp); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ATOMIC_X86_LOAD(TYPE, MODE) \
|
||||||
|
TYPE __atomic_load_##MODE(const _Atomic(TYPE) *atom) \
|
||||||
|
{ \
|
||||||
|
return *(volatile TYPE *)atom; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ATOMIC_X86_STORE(TYPE, MODE) \
|
||||||
|
void __atomic_store_##MODE(_Atomic(TYPE) *atom, TYPE value) \
|
||||||
|
{ \
|
||||||
|
*(volatile TYPE *)atom = value; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP) \
|
||||||
|
TYPE __atomic_##NAME##_##MODE(_Atomic(TYPE) *atom, TYPE value) \
|
||||||
|
{ \
|
||||||
|
TYPE xchg; \
|
||||||
|
TYPE cmp = __atomic_load(atom, __ATOMIC_RELAXED); \
|
||||||
|
do { \
|
||||||
|
xchg = (OP); \
|
||||||
|
} while (!__atomic_compare_exchange(atom, &cmp, xchg, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); \
|
||||||
|
return cmp; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ATOMIC_EXCHANGE(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, exchange, value)
|
||||||
|
#define ATOMIC_FETCH_ADD(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_add, (cmp + value))
|
||||||
|
#define ATOMIC_FETCH_SUB(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_sub, (cmp - value))
|
||||||
|
#define ATOMIC_FETCH_AND(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_and, (cmp & value))
|
||||||
|
#define ATOMIC_FETCH_OR(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_or, (cmp | value))
|
||||||
|
#define ATOMIC_FETCH_XOR(TYPE, MODE) \
|
||||||
|
ATOMIC_GEN_OP(TYPE, MODE, fetch_xor, (cmp ^ value))
|
||||||
|
|
||||||
|
ATOMIC_X86_STORE(uint8_t, 1)
|
||||||
|
ATOMIC_X86_STORE(uint16_t, 2)
|
||||||
|
ATOMIC_X86_STORE(uint32_t, 4)
|
||||||
|
|
||||||
|
ATOMIC_X86_LOAD(uint8_t, 1)
|
||||||
|
ATOMIC_X86_LOAD(uint16_t, 2)
|
||||||
|
ATOMIC_X86_LOAD(uint32_t, 4)
|
||||||
|
|
||||||
|
ATOMIC_X86_COMPARE_EXCHANGE(uint8_t, 1, "b")
|
||||||
|
ATOMIC_X86_COMPARE_EXCHANGE(uint16_t, 2, "w")
|
||||||
|
ATOMIC_X86_COMPARE_EXCHANGE(uint32_t, 4, "l")
|
||||||
|
|
||||||
|
ATOMIC_EXCHANGE(uint8_t, 1)
|
||||||
|
ATOMIC_EXCHANGE(uint16_t, 2)
|
||||||
|
ATOMIC_EXCHANGE(uint32_t, 4)
|
||||||
|
|
||||||
|
ATOMIC_FETCH_ADD(uint8_t, 1)
|
||||||
|
ATOMIC_FETCH_ADD(uint16_t, 2)
|
||||||
|
ATOMIC_FETCH_ADD(uint32_t, 4)
|
||||||
|
|
||||||
|
ATOMIC_FETCH_SUB(uint8_t, 1)
|
||||||
|
ATOMIC_FETCH_SUB(uint16_t, 2)
|
||||||
|
ATOMIC_FETCH_SUB(uint32_t, 4)
|
||||||
|
|
||||||
|
ATOMIC_FETCH_AND(uint8_t, 1)
|
||||||
|
ATOMIC_FETCH_AND(uint16_t, 2)
|
||||||
|
ATOMIC_FETCH_AND(uint32_t, 4)
|
||||||
|
|
||||||
|
ATOMIC_FETCH_OR(uint8_t, 1)
|
||||||
|
ATOMIC_FETCH_OR(uint16_t, 2)
|
||||||
|
ATOMIC_FETCH_OR(uint32_t, 4)
|
||||||
|
|
||||||
|
ATOMIC_FETCH_XOR(uint8_t, 1)
|
||||||
|
ATOMIC_FETCH_XOR(uint16_t, 2)
|
||||||
|
ATOMIC_FETCH_XOR(uint32_t, 4)
|
||||||
|
|
||||||
|
#if defined __x86_64__
|
||||||
|
ATOMIC_X86_STORE(uint64_t, 8)
|
||||||
|
ATOMIC_X86_LOAD(uint64_t, 8)
|
||||||
|
ATOMIC_X86_COMPARE_EXCHANGE(uint64_t, 8, "q")
|
||||||
|
ATOMIC_EXCHANGE(uint64_t, 8)
|
||||||
|
ATOMIC_FETCH_ADD(uint64_t, 8)
|
||||||
|
ATOMIC_FETCH_SUB(uint64_t, 8)
|
||||||
|
ATOMIC_FETCH_AND(uint64_t, 8)
|
||||||
|
ATOMIC_FETCH_OR(uint64_t, 8)
|
||||||
|
ATOMIC_FETCH_XOR(uint64_t, 8)
|
||||||
|
#endif
|
||||||
2
tcc.h
2
tcc.h
@ -1049,7 +1049,6 @@ struct filespec {
|
|||||||
#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
|
#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
|
||||||
|
|
||||||
#define VT_ATOMIC VT_VOLATILE
|
#define VT_ATOMIC VT_VOLATILE
|
||||||
#define VT_MEMMODEL (VT_STATIC | VT_ENUM_VAL | VT_TYPEDEF)
|
|
||||||
|
|
||||||
/* type mask (except storage) */
|
/* type mask (except storage) */
|
||||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
|
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
|
||||||
@ -1418,7 +1417,6 @@ ST_FUNC void tccpp_delete(TCCState *s);
|
|||||||
ST_FUNC int tcc_preprocess(TCCState *s1);
|
ST_FUNC int tcc_preprocess(TCCState *s1);
|
||||||
ST_FUNC void skip(int c);
|
ST_FUNC void skip(int c);
|
||||||
ST_FUNC NORETURN void expect(const char *msg);
|
ST_FUNC NORETURN void expect(const char *msg);
|
||||||
ST_FUNC NORETURN void expect_arg(const char *msg, size_t arg);
|
|
||||||
|
|
||||||
/* space excluding newline */
|
/* space excluding newline */
|
||||||
static inline int is_space(int ch) {
|
static inline int is_space(int ch) {
|
||||||
|
|||||||
5
tccelf.c
5
tccelf.c
@ -1469,7 +1469,7 @@ static void tcc_tcov_add_file(TCCState *s1, const char *filename)
|
|||||||
cstr_printf (&cstr, "%s/%s.tcov", wd, filename);
|
cstr_printf (&cstr, "%s/%s.tcov", wd, filename);
|
||||||
}
|
}
|
||||||
ptr = section_ptr_add(tcov_section, cstr.size + 1);
|
ptr = section_ptr_add(tcov_section, cstr.size + 1);
|
||||||
strncpy((char *)ptr, cstr.data, cstr.size);
|
strcpy((char *)ptr, cstr.data);
|
||||||
unlink((char *)ptr);
|
unlink((char *)ptr);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
normalize_slashes((char *)ptr);
|
normalize_slashes((char *)ptr);
|
||||||
@ -2339,7 +2339,8 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
|
|||||||
ehdr.e_shstrndx = shnum - 1;
|
ehdr.e_shstrndx = shnum - 1;
|
||||||
|
|
||||||
fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
|
fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
|
||||||
fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
|
if (phdr)
|
||||||
|
fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
|
||||||
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
|
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
|
||||||
|
|
||||||
sort_syms(s1, symtab_section);
|
sort_syms(s1, symtab_section);
|
||||||
|
|||||||
178
tccgen.c
178
tccgen.c
@ -849,7 +849,7 @@ static void tcc_tcov_block_begin(void)
|
|||||||
cstr_printf (&cstr, "%s/%s", wd, file->true_filename);
|
cstr_printf (&cstr, "%s/%s", wd, file->true_filename);
|
||||||
}
|
}
|
||||||
ptr = section_ptr_add(tcov_section, cstr.size + 1);
|
ptr = section_ptr_add(tcov_section, cstr.size + 1);
|
||||||
strncpy((char *)ptr, cstr.data, cstr.size);
|
strcpy((char *)ptr, cstr.data);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
normalize_slashes((char *)ptr);
|
normalize_slashes((char *)ptr);
|
||||||
#endif
|
#endif
|
||||||
@ -865,7 +865,7 @@ static void tcc_tcov_block_begin(void)
|
|||||||
tcov_data.last_func_name = tcov_section->data_offset;
|
tcov_data.last_func_name = tcov_section->data_offset;
|
||||||
len = strlen (funcname);
|
len = strlen (funcname);
|
||||||
ptr = section_ptr_add(tcov_section, len + 1);
|
ptr = section_ptr_add(tcov_section, len + 1);
|
||||||
strncpy((char *)ptr, funcname, len);
|
strcpy((char *)ptr, funcname);
|
||||||
section_ptr_add(tcov_section, -tcov_section->data_offset & 7);
|
section_ptr_add(tcov_section, -tcov_section->data_offset & 7);
|
||||||
ptr = section_ptr_add(tcov_section, 8);
|
ptr = section_ptr_add(tcov_section, 8);
|
||||||
write64le (ptr, file->line_num);
|
write64le (ptr, file->line_num);
|
||||||
@ -5738,36 +5738,11 @@ static void parse_builtin_params(int nc, const char *args)
|
|||||||
nocode_wanted--;
|
nocode_wanted--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_memory_model(const SValue *sv)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* FIXME
|
|
||||||
* The memory models should better be backed by an enumeration.
|
|
||||||
*
|
|
||||||
* const int t = sv->type.t;
|
|
||||||
*
|
|
||||||
* if (!IS_ENUM_VAL(t))
|
|
||||||
* return 0;
|
|
||||||
*
|
|
||||||
* if (!(t & VT_STATIC))
|
|
||||||
* return 0;
|
|
||||||
*
|
|
||||||
* Ideally we should check whether the model matches 1:1.
|
|
||||||
* If it is possible, we should check by the name of the value.
|
|
||||||
*/
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ATOMIC_ID(ATOK) \
|
|
||||||
(ATOK - TOK___atomic_store)
|
|
||||||
|
|
||||||
static void parse_atomic(int atok)
|
static void parse_atomic(int atok)
|
||||||
{
|
{
|
||||||
int mode;
|
int size, align, arg;
|
||||||
size_t arg;
|
CType *atom, *atom_ptr, ct = {0};
|
||||||
SValue *call;
|
char buf[40];
|
||||||
CType rv;
|
|
||||||
CType atom;
|
|
||||||
static const char *const templates[] = {
|
static const char *const templates[] = {
|
||||||
/*
|
/*
|
||||||
* Each entry consists of callback and function template.
|
* Each entry consists of callback and function template.
|
||||||
@ -5781,124 +5756,85 @@ static void parse_atomic(int atok)
|
|||||||
* v value
|
* v value
|
||||||
* m memory model
|
* m memory model
|
||||||
*/
|
*/
|
||||||
[ATOMIC_ID(TOK___atomic_store)] = "avm?",
|
|
||||||
[ATOMIC_ID(TOK___atomic_load)] = "Amv",
|
/* keep in order of appearance in tcctok.h: */
|
||||||
[ATOMIC_ID(TOK___atomic_exchange)] = "avmv",
|
/* __atomic_store */ "avm.?",
|
||||||
[ATOMIC_ID(TOK___atomic_compare_exchange)] = "apvbmmb",
|
/* __atomic_load */ "Am.v",
|
||||||
[ATOMIC_ID(TOK___atomic_fetch_add)] = "avmv",
|
/* __atomic_exchange */ "avm.v",
|
||||||
[ATOMIC_ID(TOK___atomic_fetch_sub)] = "avmv",
|
/* __atomic_compare_exchange */ "apvbmm.b",
|
||||||
[ATOMIC_ID(TOK___atomic_fetch_or)] = "avmv",
|
/* __atomic_fetch_add */ "avm.v",
|
||||||
[ATOMIC_ID(TOK___atomic_fetch_xor)] = "avmv",
|
/* __atomic_fetch_sub */ "avm.v",
|
||||||
[ATOMIC_ID(TOK___atomic_fetch_and)] = "avmv",
|
/* __atomic_fetch_or */ "avm.v",
|
||||||
|
/* __atomic_fetch_xor */ "avm.v",
|
||||||
|
/* __atomic_fetch_and */ "avm.v"
|
||||||
};
|
};
|
||||||
const char *template = templates[ATOMIC_ID(atok)];
|
const char *template = templates[(atok - TOK___atomic_store)];
|
||||||
const size_t argc = (strlen(template) - 1);
|
|
||||||
|
|
||||||
|
atom = atom_ptr = NULL;
|
||||||
|
size = 0; /* pacify compiler */
|
||||||
next();
|
next();
|
||||||
|
|
||||||
memset(&rv, 0, sizeof(rv));
|
|
||||||
memset(&atom, 0, sizeof(atom));
|
|
||||||
mode = 0; /* pacify compiler */
|
|
||||||
vpush_helper_func(atok);
|
|
||||||
call = vtop;
|
|
||||||
|
|
||||||
skip('(');
|
skip('(');
|
||||||
if ((*template != 'a') && (*template != 'A'))
|
for (arg = 0;;) {
|
||||||
expect_arg("pointer to atomic", 0);
|
|
||||||
for (arg = 0; arg < argc; ++arg) {
|
|
||||||
expr_eq();
|
expr_eq();
|
||||||
|
|
||||||
switch (template[arg]) {
|
switch (template[arg]) {
|
||||||
case '?':
|
|
||||||
/* void makes sense only for return value. */
|
|
||||||
if (arg != (argc - 1))
|
|
||||||
tcc_error("illegal atomic built-in template");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'A':
|
case 'A':
|
||||||
if ((vtop->type.t & VT_BTYPE) != VT_PTR)
|
atom_ptr = &vtop->type;
|
||||||
expect_arg("pointer to atomic value", arg);
|
if ((atom_ptr->t & VT_BTYPE) != VT_PTR)
|
||||||
memcpy(&atom, pointed_type(&vtop->type), sizeof(CType));
|
expect("pointer");
|
||||||
if (!(atom.t & VT_ATOMIC))
|
atom = pointed_type(atom_ptr);
|
||||||
expect_arg("qualified pointer to atomic value", arg);
|
size = type_size(atom, &align);
|
||||||
if ((template[arg] == 'a') && (atom.t & VT_CONSTANT))
|
if (size > 8
|
||||||
expect_arg("pointer to writable atomic", arg);
|
|| (size & (size - 1))
|
||||||
switch (type_size(&atom, &(int){0})) {
|
|| (atok > TOK___atomic_compare_exchange
|
||||||
case 8: mode = 4; break;
|
&& (0 == btype_size(atom->t & VT_BTYPE)
|
||||||
case 4: mode = 3; break;
|
|| (atom->t & VT_BTYPE) == VT_PTR)))
|
||||||
case 2: mode = 2; break;
|
expect("integral or integer-sized pointer target type");
|
||||||
case 1: mode = 1; break;
|
/* GCC does not care either: */
|
||||||
default: tcc_error("only integer-sized types are supported");
|
/* if (!(atom->t & VT_ATOMIC))
|
||||||
}
|
tcc_warning("pointer target declaration is missing '_Atomic'"); */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (((vtop->type.t & VT_BTYPE) != VT_PTR)
|
if ((vtop->type.t & VT_BTYPE) != VT_PTR
|
||||||
|| !is_compatible_unqualified_types(&atom, pointed_type(&vtop->type)))
|
|| type_size(pointed_type(&vtop->type), &align) != size)
|
||||||
expect_arg("pointer to compatible type", arg);
|
tcc_error("pointer target type mismatch in argument %d", arg + 1);
|
||||||
|
gen_assign_cast(atom_ptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
if (atom.ref && is_integer_btype(vtop->type.t & VT_BTYPE)) {
|
gen_assign_cast(atom);
|
||||||
if ((tok != TOK___atomic_store) &&
|
|
||||||
(tok != TOK___atomic_load) &&
|
|
||||||
(tok != TOK___atomic_exchange) &&
|
|
||||||
(tok != TOK___atomic_compare_exchange))
|
|
||||||
expect_arg("integer type", arg);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
if (!is_memory_model(vtop))
|
gen_assign_cast(&int_type);
|
||||||
expect_arg("memory model", arg);
|
break;
|
||||||
vtop->type.t &= ~VT_MEMMODEL;
|
case 'b':
|
||||||
|
ct.t = VT_BOOL;
|
||||||
|
gen_assign_cast(&ct);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
tcc_error("unknown parameter type");
|
|
||||||
}
|
}
|
||||||
if (tok == ')')
|
if ('.' == template[++arg])
|
||||||
break;
|
break;
|
||||||
skip(',');
|
skip(',');
|
||||||
}
|
}
|
||||||
if (arg < (argc - 1))
|
|
||||||
expect("more parameters");
|
|
||||||
if (arg > (argc - 1))
|
|
||||||
expect("less parameters");
|
|
||||||
skip(')');
|
skip(')');
|
||||||
|
|
||||||
call->sym = external_helper_sym(atok + mode);
|
ct.t = VT_VOID;
|
||||||
gfunc_call(argc);
|
switch (template[arg + 1]) {
|
||||||
|
|
||||||
switch (template[argc]) {
|
|
||||||
case 'b':
|
case 'b':
|
||||||
vpushi(0);
|
ct.t = VT_BOOL;
|
||||||
PUT_R_RET(vtop, VT_BOOL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
|
||||||
vpushs(0);
|
|
||||||
PUT_R_RET(vtop, VT_SIZE_T);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
vpush(&atom);
|
ct = *atom;
|
||||||
PUT_R_RET(vtop, atom.t);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '?':
|
|
||||||
vpushi(0);
|
|
||||||
PUT_R_RET(vtop, VT_VOID);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
tcc_error("incorrect atomic template");
|
|
||||||
}
|
}
|
||||||
vtop->r2 = VT_CONST;
|
|
||||||
|
sprintf(buf, "%s_%d", get_tok_str(atok, 0), size);
|
||||||
|
vpush_helper_func(tok_alloc_const(buf));
|
||||||
|
vrott(arg + 1);
|
||||||
|
gfunc_call(arg);
|
||||||
|
|
||||||
|
vpush(&ct);
|
||||||
|
PUT_R_RET(vtop, ct.t);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void unary(void)
|
ST_FUNC void unary(void)
|
||||||
|
|||||||
5
tccpp.c
5
tccpp.c
@ -107,11 +107,6 @@ ST_FUNC void expect(const char *msg)
|
|||||||
tcc_error("%s expected", msg);
|
tcc_error("%s expected", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void expect_arg(const char *msg, size_t arg)
|
|
||||||
{
|
|
||||||
tcc_error("%s expected as arg #%zu", msg, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* Custom allocator for tiny objects */
|
/* Custom allocator for tiny objects */
|
||||||
|
|
||||||
|
|||||||
10
tcctok.h
10
tcctok.h
@ -175,13 +175,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* atomic operations */
|
/* atomic operations */
|
||||||
#define DEF_ATOMIC(ID) \
|
#define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID)
|
||||||
DEF(TOK_##__##ID, "__"#ID) \
|
|
||||||
DEF(TOK_##__##ID##_1, "__"#ID"_1") \
|
|
||||||
DEF(TOK_##__##ID##_2, "__"#ID"_2") \
|
|
||||||
DEF(TOK_##__##ID##_4, "__"#ID"_4") \
|
|
||||||
DEF(TOK_##__##ID##_8, "__"#ID"_8")
|
|
||||||
|
|
||||||
DEF_ATOMIC(atomic_store)
|
DEF_ATOMIC(atomic_store)
|
||||||
DEF_ATOMIC(atomic_load)
|
DEF_ATOMIC(atomic_load)
|
||||||
DEF_ATOMIC(atomic_exchange)
|
DEF_ATOMIC(atomic_exchange)
|
||||||
@ -192,8 +186,6 @@
|
|||||||
DEF_ATOMIC(atomic_fetch_xor)
|
DEF_ATOMIC(atomic_fetch_xor)
|
||||||
DEF_ATOMIC(atomic_fetch_and)
|
DEF_ATOMIC(atomic_fetch_and)
|
||||||
|
|
||||||
#undef DEF_ATOMIC
|
|
||||||
|
|
||||||
/* pragma */
|
/* pragma */
|
||||||
DEF(TOK_pack, "pack")
|
DEF(TOK_pack, "pack")
|
||||||
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
|
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
|
||||||
|
|||||||
108
tests/tests2/125_atomic_misc.c
Normal file
108
tests/tests2/125_atomic_misc.c
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include <stdatomic.h>
|
||||||
|
int printf(const char*,...);
|
||||||
|
|
||||||
|
#if defined test_atomic_compare_exchange
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
_Atomic int a = 12;
|
||||||
|
int b = 77;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
atomic_store(&a, b + 0);
|
||||||
|
r = atomic_compare_exchange_strong(&a, &b, 99);
|
||||||
|
printf("%d %d %d\n", r, a, b);
|
||||||
|
|
||||||
|
atomic_store(&a, b + 3);
|
||||||
|
r = atomic_compare_exchange_strong(&a, &b, 99);
|
||||||
|
printf("%d %d %d\n", r, a, b);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_store
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int _Atomic i;
|
||||||
|
int r;
|
||||||
|
atomic_store(&i, 12);
|
||||||
|
r = atomic_fetch_add(&i, i);
|
||||||
|
printf("r = %d, i = %d\n", r, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_store_pointer
|
||||||
|
typedef struct { char c[4]; } c4;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
int _Atomic *p = &i;
|
||||||
|
int k = 2;
|
||||||
|
atomic_store(&p, &k);
|
||||||
|
printf("*p = %d\n", *p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_store_struct
|
||||||
|
typedef struct { char c[4]; } c4;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
c4 _Atomic p;
|
||||||
|
c4 v = { 1,2,3,4 };
|
||||||
|
atomic_store(&p, v);
|
||||||
|
printf("%d %d %d %d\n", p.c[0], p.c[1], p.c[2], p.c[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_error_1
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int _Atomic i;
|
||||||
|
atomic_load(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_error_2
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct { char c[3]; } _Atomic c3;
|
||||||
|
atomic_load(&c3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_error_3
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
_Atomic int *p = 0;
|
||||||
|
atomic_fetch_add(&p, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_error_4
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int _Atomic i = 1;
|
||||||
|
char c = 2;
|
||||||
|
atomic_compare_exchange_strong(&i, &c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_warn_1
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int _Atomic i = 1;
|
||||||
|
/* assignment to integer from pointer */
|
||||||
|
atomic_store(&i, &i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_warn_2
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
char c = 2;
|
||||||
|
int _Atomic *p = &i;
|
||||||
|
/* assignment from incompatible pointer */
|
||||||
|
atomic_store(&p, &c);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined test_atomic_warn_3
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int const i = 1;
|
||||||
|
/* assignment to read-only -location */
|
||||||
|
atomic_fetch_add(&i, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
33
tests/tests2/125_atomic_misc.expect
Normal file
33
tests/tests2/125_atomic_misc.expect
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
[test_atomic_compare_exchange]
|
||||||
|
1 99 77
|
||||||
|
0 80 80
|
||||||
|
|
||||||
|
[test_atomic_store]
|
||||||
|
r = 12, i = 24
|
||||||
|
|
||||||
|
[test_atomic_store_pointer]
|
||||||
|
*p = 2
|
||||||
|
|
||||||
|
[test_atomic_store_struct]
|
||||||
|
1 2 3 4
|
||||||
|
|
||||||
|
[test_atomic_error_1]
|
||||||
|
125_atomic_misc.c:57: error: pointer expected
|
||||||
|
|
||||||
|
[test_atomic_error_2]
|
||||||
|
125_atomic_misc.c:64: error: integral or integer-sized pointer target type expected
|
||||||
|
|
||||||
|
[test_atomic_error_3]
|
||||||
|
125_atomic_misc.c:71: error: integral or integer-sized pointer target type expected
|
||||||
|
|
||||||
|
[test_atomic_error_4]
|
||||||
|
125_atomic_misc.c:79: error: pointer target type mismatch in argument 2
|
||||||
|
|
||||||
|
[test_atomic_warn_1]
|
||||||
|
125_atomic_misc.c:87: warning: assignment makes integer from pointer without a cast
|
||||||
|
|
||||||
|
[test_atomic_warn_2]
|
||||||
|
125_atomic_misc.c:97: warning: assignment from incompatible pointer type
|
||||||
|
|
||||||
|
[test_atomic_warn_3]
|
||||||
|
125_atomic_misc.c:105: warning: assignment of read-only location
|
||||||
@ -23,6 +23,8 @@ ifeq (,$(filter i386,$(ARCH)))
|
|||||||
endif
|
endif
|
||||||
ifeq (,$(filter i386 x86_64,$(ARCH)))
|
ifeq (,$(filter i386 x86_64,$(ARCH)))
|
||||||
SKIP += 85_asm-outside-function.test # x86 asm
|
SKIP += 85_asm-outside-function.test # x86 asm
|
||||||
|
SKIP += 124_atomic_counter.test
|
||||||
|
SKIP += 125_atomic_misc.test # currently only x86 supported
|
||||||
endif
|
endif
|
||||||
ifeq ($(CONFIG_backtrace),no)
|
ifeq ($(CONFIG_backtrace),no)
|
||||||
SKIP += 112_backtrace.test
|
SKIP += 112_backtrace.test
|
||||||
@ -47,6 +49,7 @@ endif
|
|||||||
ifeq (-$(CONFIG_WIN32)-,-yes-)
|
ifeq (-$(CONFIG_WIN32)-,-yes-)
|
||||||
SKIP += 106_versym.test # No pthread support
|
SKIP += 106_versym.test # No pthread support
|
||||||
SKIP += 114_bound_signal.test # No pthread support
|
SKIP += 114_bound_signal.test # No pthread support
|
||||||
|
SKIP += 124_atomic_counter.test # No pthread support
|
||||||
endif
|
endif
|
||||||
ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
|
ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS)))
|
||||||
SKIP += 106_versym.test # no pthread_condattr_setpshared
|
SKIP += 106_versym.test # no pthread_condattr_setpshared
|
||||||
@ -115,11 +118,7 @@ ifneq ($(CONFIG_bcheck),no)
|
|||||||
121_struct_return.test: FLAGS += -b
|
121_struct_return.test: FLAGS += -b
|
||||||
122_vla_reuse.test: FLAGS += -b
|
122_vla_reuse.test: FLAGS += -b
|
||||||
endif
|
endif
|
||||||
|
125_atomic_misc.test: FLAGS += -dt
|
||||||
# this test needs pthread and is currently supported on x86 platforms
|
|
||||||
ifneq (,$(filter i386 x86_64,$(ARCH)))
|
|
||||||
SKIP += 124_atomic_counter.test
|
|
||||||
endif
|
|
||||||
124_atomic_counter.test: FLAGS += -pthread
|
124_atomic_counter.test: FLAGS += -pthread
|
||||||
|
|
||||||
# Filter source directory in warnings/errors (out-of-tree builds)
|
# Filter source directory in warnings/errors (out-of-tree builds)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user