aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rwxr-xr-xcgcc32
-rw-r--r--evaluate.c4
-rw-r--r--machine.h6
-rw-r--r--options.c19
-rw-r--r--parse.c310
-rw-r--r--predefine.c69
-rw-r--r--sparse.110
-rw-r--r--symbol.c7
-rw-r--r--symbol.h3
-rw-r--r--target-alpha.c3
-rw-r--r--target-arm.c21
-rw-r--r--target-arm64.c5
-rw-r--r--target-h8300.c34
-rw-r--r--target-m68k.c9
-rw-r--r--target-microblaze.c9
-rw-r--r--target-mips.c10
-rw-r--r--target-nds32.c33
-rw-r--r--target-nios2.c20
-rw-r--r--target-openrisc.c31
-rw-r--r--target-ppc.c13
-rw-r--r--target-riscv.c111
-rw-r--r--target-s390.c12
-rw-r--r--target-sh.c36
-rw-r--r--target-sparc.c26
-rw-r--r--target-x86.c122
-rw-r--r--target-xtensa.c36
-rw-r--r--target.c80
-rw-r--r--target.h29
-rw-r--r--validation/eval/array-quals-node.c29
-rw-r--r--validation/eval/array-quals0.c6
-rw-r--r--validation/eval/array-quals1.c49
-rw-r--r--validation/linear/bug-assign-op0.c115
-rw-r--r--validation/static_assert.c5
34 files changed, 1080 insertions, 229 deletions
diff --git a/Makefile b/Makefile
index 35098940..fea2d74f 100644
--- a/Makefile
+++ b/Makefile
@@ -73,15 +73,20 @@ LIB_OBJS += target-arm.o
LIB_OBJS += target-arm64.o
LIB_OBJS += target-bfin.o
LIB_OBJS += target-default.o
+LIB_OBJS += target-h8300.o
LIB_OBJS += target-m68k.o
LIB_OBJS += target-microblaze.o
LIB_OBJS += target-mips.o
+LIB_OBJS += target-nds32.o
LIB_OBJS += target-nios2.o
+LIB_OBJS += target-openrisc.o
LIB_OBJS += target-ppc.o
LIB_OBJS += target-riscv.o
LIB_OBJS += target-s390.o
+LIB_OBJS += target-sh.o
LIB_OBJS += target-sparc.o
LIB_OBJS += target-x86.o
+LIB_OBJS += target-xtensa.o
LIB_OBJS += tokenize.o
LIB_OBJS += unssa.o
LIB_OBJS += utils.o
diff --git a/cgcc b/cgcc
index 9c6ad883..9c78ee63 100755
--- a/cgcc
+++ b/cgcc
@@ -221,48 +221,32 @@ sub float_types {
sub add_specs {
my ($spec) = @_;
if ($spec eq 'sunos') {
- return &add_specs ('unix') .
- ' -D__sun__=1 -D__sun=1 -Dsun=1' .
- ' -D__svr4__=1 -DSVR4=1' .
+ return " --os=$spec" .
+ ' -DSVR4=1' .
' -D__STDC__=0' .
' -D_REENTRANT' .
' -D_SOLARIS_THREADS' .
' -DNULL="((void *)0)"';
} elsif ($spec eq 'linux') {
- return &add_specs ('unix') .
- ' -D__linux__=1 -D__linux=1 -Dlinux=1';
+ return " --os=$spec";
} elsif ($spec eq 'gnu/kfreebsd') {
return &add_specs ('unix') .
' -D__FreeBSD_kernel__=1';
} elsif ($spec eq 'openbsd') {
- return &add_specs ('unix') .
- ' -D__OpenBSD__=1';
+ return " --os=$spec";
} elsif ($spec eq 'freebsd') {
- return &add_specs ('unix') .
- ' -D__FreeBSD__=1';
+ return " --os=$spec";
} elsif ($spec eq 'netbsd') {
- return &add_specs ('unix') .
- ' -D__NetBSD__=1';
+ return " --os=$spec";
} elsif ($spec eq 'darwin') {
- return
- ' -D__APPLE__=1 -D__APPLE_CC__=1 -D__MACH__=1';
+ return " --os=$spec";
} elsif ($spec eq 'gnu') { # Hurd
return &add_specs ('unix') . # So, GNU is Unix, uh?
' -D__GNU__=1 -D__gnu_hurd__=1 -D__MACH__=1';
} elsif ($spec eq 'unix') {
return ' -Dunix=1 -D__unix=1 -D__unix__=1';
} elsif ( $spec =~ /^cygwin/) {
- return &add_specs ('unix') .
- ' -fshort-wchar' .
- ' -D__CYGWIN__=1' .
- ($m32 ? ' -D__CYGWIN32__=1' : '') .
- " -D'_cdecl=__attribute__((__cdecl__))'" .
- " -D'__cdecl=__attribute__((__cdecl__))'" .
- " -D'_stdcall=__attribute__((__stdcall__))'" .
- " -D'__stdcall=__attribute__((__stdcall__))'" .
- " -D'_fastcall=__attribute__((__fastcall__))'" .
- " -D'__fastcall=__attribute__((__fastcall__))'" .
- " -D'__declspec(x)=__attribute__((x))'";
+ return ' --os=cygwin';
} elsif ($spec eq 'i386') {
$m32 = 1;
return (
diff --git a/evaluate.c b/evaluate.c
index f515ce6f..dddea761 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1444,8 +1444,8 @@ static int check_assignment_types(struct symbol *target, struct expression **rp,
}
b1 = examine_pointer_target(t);
b2 = examine_pointer_target(s);
- mod1 = target_qualifiers(t);
- mod2 = target_qualifiers(s);
+ mod1 = t->ctype.modifiers & MOD_IGN;
+ mod2 = s->ctype.modifiers & MOD_IGN;
if (whitelist_pointers(b1, b2)) {
/*
* assignments to/from void * are OK, provided that
diff --git a/machine.h b/machine.h
index 7407e716..d05b5045 100644
--- a/machine.h
+++ b/machine.h
@@ -34,9 +34,14 @@ enum machine {
MACH_S390, MACH_S390X,
MACH_ALPHA,
MACH_BFIN,
+ MACH_H8300,
MACH_M68K,
MACH_MICROBLAZE,
+ MACH_NDS32,
MACH_NIOS2,
+ MACH_OPENRISC,
+ MACH_SH,
+ MACH_XTENSA,
MACH_UNKNOWN
};
@@ -94,6 +99,7 @@ enum fp_abi {
enum {
OS_UNKNOWN,
+ OS_NONE,
OS_UNIX,
OS_CYGWIN,
OS_DARWIN,
diff --git a/options.c b/options.c
index 9f05bdf9..b2eb7a99 100644
--- a/options.c
+++ b/options.c
@@ -609,6 +609,13 @@ static char **handle_switch_M(char *arg, char **next)
return next;
}
+static int handle_march(const char *opt, const char *arg, const struct flag *flag, int options)
+{
+ if (arch_target->parse_march)
+ arch_target->parse_march(arg);
+ return 1;
+}
+
static int handle_mcmodel(const char *opt, const char *arg, const struct flag *flag, int options)
{
static const struct val_map cmodels[] = {
@@ -650,6 +657,7 @@ static const struct flag mflags[] = {
{ "x32",&arch_m64, NULL, OPT_VAL, ARCH_X32 },
{ "size-llp64", &arch_m64, NULL, OPT_VAL, ARCH_LLP64 },
{ "size-long", &arch_msize_long },
+ { "arch=", NULL, handle_march },
{ "big-endian", &arch_big_endian, NULL },
{ "little-endian", &arch_big_endian, NULL, OPT_INVERSE },
{ "cmodel", &arch_cmodel, handle_mcmodel },
@@ -925,6 +933,16 @@ static char **handle_param(char *arg, char **next)
return next;
}
+static char **handle_os(char *arg, char **next)
+{
+ if (*arg++ != '=')
+ die("missing argument for --os option");
+
+ target_os(arg);
+
+ return next;
+}
+
static char **handle_version(char *arg, char **next)
{
printf("%s\n", SPARSE_VERSION);
@@ -941,6 +959,7 @@ static char **handle_long_options(char *arg, char **next)
{
static struct switches cmd[] = {
{ "arch", handle_arch, 1 },
+ { "os", handle_os, 1 },
{ "param", handle_param, 1 },
{ "version", handle_version },
{ NULL, NULL }
diff --git a/parse.c b/parse.c
index d0a41b14..cc5dbd52 100644
--- a/parse.c
+++ b/parse.c
@@ -455,159 +455,132 @@ static struct symbol_op mode_word_op = {
.to_mode = to_word_mode
};
-/* Using NS_TYPEDEF will also make the keyword a reserved one */
+/*
+ * Define the keyword and their effects.
+ * The entries in the 'typedef' and put in NS_TYPEDEF and
+ * are automatically set as reserved keyword while the ones
+ * in the 'keyword' table are just put in NS_KEYWORD.
+ *
+ * The entries are added via the 3 macros:
+ * N() for entries with "name" only,
+ * D() for entries with "name" & "__name__",
+ * A() for entries with "name", "__name" & "__name__",
+ * U() for entries with "__name" & "__name__".
+ */
static struct init_keyword {
const char *name;
- enum namespace ns;
- unsigned long modifiers;
struct symbol_op *op;
struct symbol *type;
-} keyword_table[] = {
+ unsigned long mods;
+} typedefs[] = {
+#define N(I, O,...) { I, O,##__VA_ARGS__ }
+#define D(I, O,...) N(I,O,##__VA_ARGS__ ), \
+ N("__" I "__",O,##__VA_ARGS__)
+#define A(I, O,...) N(I,O,##__VA_ARGS__ ), \
+ N("__" I,O,##__VA_ARGS__), \
+ N("__" I "__",O,##__VA_ARGS__)
+#define U(I, O,...) N("__" I,O,##__VA_ARGS__), \
+ N("__" I "__",O,##__VA_ARGS__)
+ /* Storage classes */
+ N("auto", &auto_op),
+ N("register", &register_op),
+ N("static", &static_op),
+ N("extern", &extern_op),
+ N("__thread", &thread_op),
+ N("_Thread_local", &thread_op),
+
+ A("inline", &inline_op),
+
+ /* Typedef ... */
+ N("typedef", &typedef_op),
+ A("typeof", &typeof_op),
+ N("__auto_type", &autotype_op),
+
/* Type qualifiers */
- { "const", NS_TYPEDEF, .op = &const_op },
- { "__const", NS_TYPEDEF, .op = &const_op },
- { "__const__", NS_TYPEDEF, .op = &const_op },
- { "volatile", NS_TYPEDEF, .op = &volatile_op },
- { "__volatile", NS_TYPEDEF, .op = &volatile_op },
- { "__volatile__", NS_TYPEDEF, .op = &volatile_op },
- { "restrict", NS_TYPEDEF, .op = &restrict_op},
- { "__restrict", NS_TYPEDEF, .op = &restrict_op},
- { "__restrict__", NS_TYPEDEF, .op = &restrict_op},
- { "_Atomic", NS_TYPEDEF, .op = &atomic_op},
-
- /* Typedef.. */
- { "typedef", NS_TYPEDEF, .op = &typedef_op },
+ A("const", &const_op),
+ A("volatile", &volatile_op),
+ A("restrict", &restrict_op),
+
+ N("_Atomic", &atomic_op),
+ N("_Noreturn", &noreturn_op),
+ N("_Alignas", &alignas_op),
+
+ U("attribute", &attribute_op),
/* Type specifiers */
- { "void", NS_TYPEDEF, .type = &void_ctype, .op = &spec_op},
- { "char", NS_TYPEDEF, .op = &char_op },
- { "short", NS_TYPEDEF, .op = &short_op },
- { "int", NS_TYPEDEF, .op = &int_op },
- { "long", NS_TYPEDEF, .op = &long_op },
- { "float", NS_TYPEDEF, .op = &float_op },
- { "double", NS_TYPEDEF, .op = &double_op },
- { "signed", NS_TYPEDEF, .op = &signed_op },
- { "__signed", NS_TYPEDEF, .op = &signed_op },
- { "__signed__", NS_TYPEDEF, .op = &signed_op },
- { "unsigned", NS_TYPEDEF, .op = &unsigned_op },
- { "__int128", NS_TYPEDEF, .op = &int128_op },
- { "_Bool", NS_TYPEDEF, .type = &bool_ctype, .op = &spec_op },
+ N("struct", &struct_op),
+ N("union", &union_op),
+ N("enum", &enum_op),
+
+ N("void", &spec_op, .type = &void_ctype),
+ N("char", &char_op),
+ N("short", &short_op),
+ N("int", &int_op),
+ N("long", &long_op),
+ N("float", &float_op),
+ N("double", &double_op),
+ A("signed", &signed_op),
+ N("unsigned", &unsigned_op),
+ N("__int128", &int128_op),
+ N("_Bool", &spec_op, .type = &bool_ctype),
/* Predeclared types */
- { "__builtin_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op },
- { "__builtin_ms_va_list", NS_TYPEDEF, .type = &ptr_ctype, .op = &spec_op },
- { "__int128_t", NS_TYPEDEF, .type = &sint128_ctype, .op = &spec_op },
- { "__uint128_t",NS_TYPEDEF, .type = &uint128_ctype, .op = &spec_op },
- { "_Float32", NS_TYPEDEF, .type = &float32_ctype, .op = &spec_op },
- { "_Float32x", NS_TYPEDEF, .type = &float32x_ctype, .op = &spec_op },
- { "_Float64", NS_TYPEDEF, .type = &float64_ctype, .op = &spec_op },
- { "_Float64x", NS_TYPEDEF, .type = &float64x_ctype, .op = &spec_op },
- { "_Float128", NS_TYPEDEF, .type = &float128_ctype, .op = &spec_op },
-
- /* Extended types */
- { "typeof", NS_TYPEDEF, .op = &typeof_op },
- { "__typeof", NS_TYPEDEF, .op = &typeof_op },
- { "__typeof__", NS_TYPEDEF, .op = &typeof_op },
- { "__auto_type",NS_TYPEDEF, .op = &autotype_op },
-
- { "__attribute", NS_TYPEDEF, .op = &attribute_op },
- { "__attribute__", NS_TYPEDEF, .op = &attribute_op },
-
- { "struct", NS_TYPEDEF, .op = &struct_op },
- { "union", NS_TYPEDEF, .op = &union_op },
- { "enum", NS_TYPEDEF, .op = &enum_op },
-
- { "inline", NS_TYPEDEF, .op = &inline_op },
- { "__inline", NS_TYPEDEF, .op = &inline_op },
- { "__inline__", NS_TYPEDEF, .op = &inline_op },
-
- { "_Noreturn", NS_TYPEDEF, .op = &noreturn_op },
-
- { "_Alignas", NS_TYPEDEF, .op = &alignas_op },
-
- /* Static assertion */
- { "_Static_assert", NS_KEYWORD, .op = &static_assert_op },
-
- /* Storage class */
- { "auto", NS_TYPEDEF, .op = &auto_op },
- { "register", NS_TYPEDEF, .op = &register_op },
- { "static", NS_TYPEDEF, .op = &static_op },
- { "extern", NS_TYPEDEF, .op = &extern_op },
- { "__thread", NS_TYPEDEF, .op = &thread_op },
- { "_Thread_local", NS_TYPEDEF, .op = &thread_op },
-
- /* Statement */
- { "if", NS_KEYWORD, .op = &if_op },
- { "return", NS_KEYWORD, .op = &return_op },
- { "break", NS_KEYWORD, .op = &loop_iter_op },
- { "continue", NS_KEYWORD, .op = &loop_iter_op },
- { "default", NS_KEYWORD, .op = &default_op },
- { "case", NS_KEYWORD, .op = &case_op },
- { "switch", NS_KEYWORD, .op = &switch_op },
- { "for", NS_KEYWORD, .op = &for_op },
- { "while", NS_KEYWORD, .op = &while_op },
- { "do", NS_KEYWORD, .op = &do_op },
- { "goto", NS_KEYWORD, .op = &goto_op },
- { "context", NS_KEYWORD, .op = &context_op },
- { "__context__",NS_KEYWORD, .op = &__context___op },
- { "__range__", NS_KEYWORD, .op = &range_op },
- { "asm", NS_KEYWORD, .op = &asm_op },
- { "__asm", NS_KEYWORD, .op = &asm_op },
- { "__asm__", NS_KEYWORD, .op = &asm_op },
-
- /* Attribute */
- { "packed", NS_KEYWORD, .op = &packed_op },
- { "__packed__", NS_KEYWORD, .op = &packed_op },
- { "aligned", NS_KEYWORD, .op = &aligned_op },
- { "__aligned__",NS_KEYWORD, .op = &aligned_op },
- { "nocast", NS_KEYWORD, MOD_NOCAST, .op = &attr_mod_op },
- { "__nocast__", NS_KEYWORD, MOD_NOCAST, .op = &attr_mod_op },
- { "noderef", NS_KEYWORD, MOD_NODEREF, .op = &attr_mod_op },
- { "__noderef__",NS_KEYWORD, MOD_NODEREF, .op = &attr_mod_op },
- { "safe", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op },
- { "__safe__", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op },
- { "unused", NS_KEYWORD, MOD_UNUSED, .op = &attr_mod_op },
- { "__unused__", NS_KEYWORD, MOD_UNUSED, .op = &attr_mod_op },
- { "externally_visible", NS_KEYWORD, MOD_EXT_VISIBLE,.op = &attr_mod_op },
- { "__externally_visible__", NS_KEYWORD,MOD_EXT_VISIBLE,.op = &attr_mod_op },
- { "force", NS_KEYWORD, .op = &attr_force_op },
- { "__force__", NS_KEYWORD, .op = &attr_force_op },
- { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op },
- { "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op },
- { "address_space",NS_KEYWORD, .op = &address_space_op },
- { "__address_space__",NS_KEYWORD, .op = &address_space_op },
- { "designated_init", NS_KEYWORD, .op = &designated_init_op },
- { "__designated_init__", NS_KEYWORD, .op = &designated_init_op },
- { "transparent_union", NS_KEYWORD, .op = &transparent_union_op },
- { "__transparent_union__", NS_KEYWORD, .op = &transparent_union_op },
- { "noreturn", NS_KEYWORD, MOD_NORETURN, .op = &attr_fun_op },
- { "__noreturn__", NS_KEYWORD, MOD_NORETURN, .op = &attr_fun_op },
- { "pure", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op },
- {"__pure__", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op },
- {"const", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op },
- {"__const", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op },
- {"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op },
- {"gnu_inline", NS_KEYWORD, MOD_GNU_INLINE, .op = &attr_fun_op },
- {"__gnu_inline__",NS_KEYWORD, MOD_GNU_INLINE, .op = &attr_fun_op },
-
- { "mode", NS_KEYWORD, .op = &mode_op },
- { "__mode__", NS_KEYWORD, .op = &mode_op },
- { "QI", NS_KEYWORD, .op = &mode_QI_op },
- { "__QI__", NS_KEYWORD, .op = &mode_QI_op },
- { "HI", NS_KEYWORD, .op = &mode_HI_op },
- { "__HI__", NS_KEYWORD, .op = &mode_HI_op },
- { "SI", NS_KEYWORD, .op = &mode_SI_op },
- { "__SI__", NS_KEYWORD, .op = &mode_SI_op },
- { "DI", NS_KEYWORD, .op = &mode_DI_op },
- { "__DI__", NS_KEYWORD, .op = &mode_DI_op },
- { "TI", NS_KEYWORD, .op = &mode_TI_op },
- { "__TI__", NS_KEYWORD, .op = &mode_TI_op },
- { "byte", NS_KEYWORD, .op = &mode_QI_op },
- { "__byte__", NS_KEYWORD, .op = &mode_QI_op },
- { "pointer", NS_KEYWORD, .op = &mode_pointer_op },
- { "__pointer__",NS_KEYWORD, .op = &mode_pointer_op },
- { "word", NS_KEYWORD, .op = &mode_word_op },
- { "__word__", NS_KEYWORD, .op = &mode_word_op },
+ N("__builtin_va_list", &spec_op, .type = &ptr_ctype),
+ N("__builtin_ms_va_list",&spec_op, .type = &ptr_ctype),
+ N("__int128_t", &spec_op, .type = &sint128_ctype),
+ N("__uint128_t", &spec_op, .type = &uint128_ctype),
+ N("_Float32", &spec_op, .type = &float32_ctype),
+ N("_Float32x", &spec_op, .type = &float32x_ctype),
+ N("_Float64", &spec_op, .type = &float64_ctype),
+ N("_Float64x", &spec_op, .type = &float64x_ctype),
+ N("_Float128", &spec_op, .type = &float128_ctype),
+}, keywords[] = {
+ /* Statements */
+ N("if", &if_op),
+ N("return", &return_op),
+ N("break", &loop_iter_op),
+ N("continue", &loop_iter_op),
+ N("default", &default_op),
+ N("case", &case_op),
+ N("switch", &switch_op),
+ N("for", &for_op),
+ N("while", &while_op),
+ N("do", &do_op),
+ N("goto", &goto_op),
+ A("asm", &asm_op),
+ N("context", &context_op),
+ N("__context__", &__context___op),
+ N("__range__", &range_op),
+ N("_Static_assert", &static_assert_op),
+
+ /* Attributes */
+ D("packed", &packed_op),
+ D("aligned", &aligned_op),
+ D("nocast", &attr_mod_op, .mods = MOD_NOCAST),
+ D("noderef", &attr_mod_op, .mods = MOD_NODEREF),
+ D("safe", &attr_mod_op, .mods = MOD_SAFE),
+ D("unused", &attr_mod_op, .mods = MOD_UNUSED),
+ D("externally_visible", &attr_mod_op, .mods = MOD_EXT_VISIBLE),
+ D("force", &attr_force_op),
+ D("bitwise", &attr_bitwise_op, .mods = MOD_BITWISE),
+ D("address_space", &address_space_op),
+ D("designated_init", &designated_init_op),
+ D("transparent_union", &transparent_union_op),
+ D("noreturn", &attr_fun_op, .mods = MOD_NORETURN),
+ D("pure", &attr_fun_op, .mods = MOD_PURE),
+ A("const", &attr_fun_op, .mods = MOD_PURE),
+ D("gnu_inline", &attr_fun_op, .mods = MOD_GNU_INLINE),
+
+ /* Modes */
+ D("mode", &mode_op),
+ D("QI", &mode_QI_op),
+ D("HI", &mode_HI_op),
+ D("SI", &mode_SI_op),
+ D("DI", &mode_DI_op),
+ D("TI", &mode_TI_op),
+ D("byte", &mode_QI_op),
+ D("pointer", &mode_pointer_op),
+ D("word", &mode_word_op),
};
@@ -629,19 +602,24 @@ static const char *ignored_attributes[] = {
};
+static void init_keyword(int stream, struct init_keyword *kw, enum namespace ns)
+{
+ struct symbol *sym = create_symbol(stream, kw->name, SYM_KEYWORD, ns);
+ sym->ident->keyword = 1;
+ sym->ident->reserved |= (ns == NS_TYPEDEF);
+ sym->ctype.modifiers = kw->mods;
+ sym->ctype.base_type = kw->type;
+ sym->op = kw->op;
+}
+
void init_parser(int stream)
{
int i;
- for (i = 0; i < ARRAY_SIZE(keyword_table); i++) {
- struct init_keyword *ptr = keyword_table + i;
- struct symbol *sym = create_symbol(stream, ptr->name, SYM_KEYWORD, ptr->ns);
- sym->ident->keyword = 1;
- if (ptr->ns == NS_TYPEDEF)
- sym->ident->reserved = 1;
- sym->ctype.modifiers = ptr->modifiers;
- sym->ctype.base_type = ptr->type;
- sym->op = ptr->op;
- }
+
+ for (i = 0; i < ARRAY_SIZE(typedefs); i++)
+ init_keyword(stream, &typedefs[i], NS_TYPEDEF);
+ for (i = 0; i < ARRAY_SIZE(keywords); i++)
+ init_keyword(stream, &keywords[i], NS_KEYWORD);
for (i = 0; i < ARRAY_SIZE(ignored_attributes); i++) {
const char * name = ignored_attributes[i];
@@ -2223,17 +2201,25 @@ static struct token *parse_static_assert(struct token *token, struct symbol_list
token = constant_expression(token, &cond);
if (!cond)
sparse_error(token->pos, "Expected constant expression");
- token = expect(token, ',', "after conditional expression in _Static_assert");
- token = string_expression(token, &message, "_Static_assert()");
- if (!message)
- cond = NULL;
+ if (match_op(token, ',')) {
+ token = token->next;
+ token = string_expression(token, &message, "_Static_assert()");
+ if (!message)
+ cond = NULL;
+ }
token = expect(token, ')', "after diagnostic message in _Static_assert");
-
token = expect(token, ';', "after _Static_assert()");
- if (cond && !const_expression_value(cond) && cond->type == EXPR_VALUE)
- sparse_error(cond->pos, "static assertion failed: %s",
- show_string(message->string));
+ if (cond && !const_expression_value(cond) && cond->type == EXPR_VALUE) {
+ const char *sep = "", *msg = "";
+
+ if (message) {
+ sep = ": ";
+ msg = show_string(message->string);
+ }
+ sparse_error(cond->pos, "static assertion failed%s%s", sep, msg);
+ }
+
return token;
}
diff --git a/predefine.c b/predefine.c
index d05b1018..f898cdfa 100644
--- a/predefine.c
+++ b/predefine.c
@@ -25,12 +25,12 @@ static void predefined_sizeof(const char *name, const char *suffix, unsigned bit
predefine(buf, 1, "%d", bits/8);
}
-static void predefined_width(const char *name, unsigned bits)
+static void predefined_width(const char *name, struct symbol *type)
{
char buf[32];
snprintf(buf, sizeof(buf), "__%s_WIDTH__", name);
- predefine(buf, 1, "%d", bits);
+ predefine(buf, 1, "%d", type->bit_size);
}
static void predefined_max(const char *name, struct symbol *type)
@@ -78,7 +78,7 @@ static void predefined_ctype(const char *name, struct symbol *type, int flags)
if (flags & PTYPE_TYPE)
predefined_type(name, type);
if (flags & PTYPE_WIDTH)
- predefined_width(name, bits);
+ predefined_width(name, type);
}
void predefined_macros(void)
@@ -145,13 +145,32 @@ void predefined_macros(void)
predefined_ctype("INT64", int64_ctype, PTYPE_MAX|PTYPE_TYPE);
predefined_ctype("UINT64", uint64_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("INT_LEAST8", &schar_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_LEAST8", &uchar_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("INT_LEAST16", &short_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_LEAST16",&ushort_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("INT_LEAST32", int32_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_LEAST32", uint32_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("INT_LEAST64", int64_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_LEAST64", uint64_ctype, PTYPE_MAX|PTYPE_TYPE);
+
+ predefined_ctype("INT_FAST8", fast8_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_FAST8", ufast8_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("INT_FAST16", fast16_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_FAST16",ufast16_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("INT_FAST32", fast32_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_FAST32",ufast32_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("INT_FAST64", fast64_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINT_FAST64",ufast64_ctype, PTYPE_MAX|PTYPE_TYPE);
+
predefined_ctype("INTMAX", intmax_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
predefined_ctype("UINTMAX", uintmax_ctype, PTYPE_MAX|PTYPE_TYPE);
- predefined_ctype("INTPTR", ssize_t_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
- predefined_ctype("UINTPTR", size_t_ctype, PTYPE_MAX|PTYPE_TYPE);
- predefined_ctype("PTRDIFF", ssize_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
+ predefined_ctype("INTPTR", intptr_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
+ predefined_ctype("UINTPTR", uintptr_ctype, PTYPE_MAX|PTYPE_TYPE);
+ predefined_ctype("PTRDIFF", ptrdiff_ctype, PTYPE_ALL_T|PTYPE_TYPE);
predefined_ctype("SIZE", size_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
predefined_ctype("POINTER", &ptr_ctype, PTYPE_SIZEOF);
+ predefined_ctype("SIG_ATOMIC", sig_atomic_ctype, PTYPE_MAX|PTYPE_MIN|PTYPE_TYPE|PTYPE_WIDTH);
predefined_sizeof("FLOAT", "", bits_in_float);
predefined_sizeof("DOUBLE", "", bits_in_double);
@@ -210,16 +229,50 @@ void predefined_macros(void)
if (arch_target->predefine)
arch_target->predefine(arch_target);
- if (arch_os >= OS_UNIX) {
+ if (arch_os >= OS_UNIX && arch_os != OS_DARWIN) {
predefine("__unix__", 1, "1");
predefine("__unix", 1, "1");
predefine_nostd("unix");
}
- if (arch_os == OS_SUNOS) {
+ switch (arch_os) {
+ case OS_CYGWIN:
+ predefine("__CYGWIN__", 1, "1");
+ if (arch_m64 == ARCH_LP32)
+ predefine("__CYGWIN32__", 1, "1");
+ add_pre_buffer("#define __cdecl __attribute__((__cdecl__))\n");
+ add_pre_buffer("#define __declspec(x) __attribute__((x))\n");
+ add_pre_buffer("#define __fastcall __attribute__((__fastcall__))\n");
+ add_pre_buffer("#define __stdcall __attribute__((__stdcall__))\n");
+ add_pre_buffer("#define __thiscall __attribute__((__thiscall__))\n");
+ add_pre_buffer("#define _cdecl __attribute__((__cdecl__))\n");
+ add_pre_buffer("#define _fastcall __attribute__((__fastcall__))\n");
+ add_pre_buffer("#define _stdcall __attribute__((__stdcall__))\n");
+ add_pre_buffer("#define _thiscall __attribute__((__thiscall__))\n");
+ break;
+ case OS_DARWIN:
+ predefine("__APPLE__", 1, "1");
+ predefine("__APPLE_CC__", 1, "1");
+ predefine("__MACH__", 1, "1");
+ break;
+ case OS_FREEBSD:
+ predefine("__FreeBSD__", 1, "1");
+ break;
+ case OS_LINUX:
+ predefine("__linux__", 1, "1");
+ predefine("__linux", 1, "1");
+ break;
+ case OS_NETBSD:
+ predefine("__NetBSD__", 1, "1");
+ break;
+ case OS_OPENBSD:
+ predefine("__OpenBSD__", 1, "1");
+ break;
+ case OS_SUNOS:
predefine("__sun__", 1, "1");
predefine("__sun", 1, "1");
predefine_nostd("sun");
predefine("__svr4__", 1, "1");
+ break;
}
}
diff --git a/sparse.1 b/sparse.1
index d916ad9e..19c8c4e3 100644
--- a/sparse.1
+++ b/sparse.1
@@ -464,6 +464,16 @@ Look for system headers in the multiarch subdirectory \fIdir\fR.
The \fIdir\fR name would normally take the form of the target's
normalized GNU triplet. (e.g. i386-linux-gnu).
.
+.TP
+.B --os=\fIOS\fR
+Specify the target Operating System.
+This only makes a few differences with the predefined types.
+The accepted values are: linux, unix, freebsd, netbsd, opensd, sunos, darwin
+and cygwin.
+
+The default OS is the one of the machine used to build Sparse if it can be
+detected, otherwise some generic settings are used.
+.
.SH DEBUG OPTIONS
.TP
.B \-fmem-report
diff --git a/symbol.c b/symbol.c
index 6ee521ba..c0ca79e4 100644
--- a/symbol.c
+++ b/symbol.c
@@ -899,4 +899,11 @@ void init_ctype(void)
char_ctype.ctype.modifiers |= MOD_UNSIGNED;
char_ctype.ctype.modifiers &= ~MOD_SIGNED;
}
+
+ if (!ptrdiff_ctype)
+ ptrdiff_ctype = ssize_t_ctype;
+ if (!intptr_ctype)
+ intptr_ctype = ssize_t_ctype;
+ if (!uintptr_ctype)
+ uintptr_ctype = size_t_ctype;
}
diff --git a/symbol.h b/symbol.h
index 67464d65..c2b60ce9 100644
--- a/symbol.h
+++ b/symbol.h
@@ -304,9 +304,6 @@ extern struct symbol float128_ctype;
extern struct symbol const_void_ctype, const_char_ctype;
extern struct symbol const_ptr_ctype, const_string_ctype;
-#define uintptr_ctype size_t_ctype
-#define intptr_ctype ssize_t_ctype
-
/* Special internal symbols */
extern struct symbol zero_int;
diff --git a/target-alpha.c b/target-alpha.c
index 3f582997..4c622aec 100644
--- a/target-alpha.c
+++ b/target-alpha.c
@@ -24,6 +24,9 @@ static const struct builtin_fn builtins_alpha[] = {
const struct target target_alpha = {
.mach = MACH_ALPHA,
.bitness = ARCH_LP64,
+ .has_int128 = 1,
+
+ .bits_in_longdouble = 64,
.predefine = predefine_alpha,
.builtins = builtins_alpha,
diff --git a/target-arm.c b/target-arm.c
index 0d7c6134..104c319b 100644
--- a/target-arm.c
+++ b/target-arm.c
@@ -3,6 +3,21 @@
#include "machine.h"
+static void init_arm(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ if (arch_os == OS_NONE) {
+ int32_ctype = &long_ctype;
+ uint32_ctype = &ulong_ctype;
+ fast8_ctype = &int_ctype;
+ ufast8_ctype = &uint_ctype;
+ }
+}
+
static void predefine_arm(const struct target *self)
{
predefine("__arm__", 1, "1");
@@ -19,6 +34,11 @@ static void predefine_arm(const struct target *self)
predefine("__ARM_PCS", 1, "1");
break;
}
+
+ if (arch_big_endian)
+ predefine("__ARMEB__", 0, "1");
+ else
+ predefine("__ARMEL__", 0, "1");
}
const struct target target_arm = {
@@ -32,5 +52,6 @@ const struct target target_arm = {
.bits_in_longdouble = 64,
.max_fp_alignment = 8,
+ .init = init_arm,
.predefine = predefine_arm,
};
diff --git a/target-arm64.c b/target-arm64.c
index 8619bd84..d92ab16b 100644
--- a/target-arm64.c
+++ b/target-arm64.c
@@ -20,6 +20,11 @@ static void predefine_arm64(const struct target *self)
predefine("__aarch64__", 1, "1");
+ if (arch_big_endian)
+ predefine("__AARCH64EB__", 0, "1");
+ else
+ predefine("__AARCH64EL__", 0, "1");
+
if (cmodel)
predefine_strong("__AARCH64_CMODEL_%s__", cmodel);
}
diff --git a/target-h8300.c b/target-h8300.c
new file mode 100644
index 00000000..c3652350
--- /dev/null
+++ b/target-h8300.c
@@ -0,0 +1,34 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_h8300(const struct target *self)
+{
+ intptr_ctype = &int_ctype;
+ uintptr_ctype = &uint_ctype;
+ ssize_t_ctype = &long_ctype;
+ size_t_ctype = &ulong_ctype;
+ wchar_ctype = &ushort_ctype;
+
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+}
+
+static void predefine_h8300(const struct target *self)
+{
+ predefine("__H8300H__", 1, "1");
+}
+
+const struct target target_h8300 = {
+ .mach = MACH_H8300,
+ .bitness = ARCH_LP32,
+ .big_endian = true,
+
+ .bits_in_longdouble = 64,
+
+ .init = init_h8300,
+ .predefine = predefine_h8300,
+};
diff --git a/target-m68k.c b/target-m68k.c
index ed4a9273..0aed2eb3 100644
--- a/target-m68k.c
+++ b/target-m68k.c
@@ -3,6 +3,14 @@
#include "machine.h"
+static void init_m68k(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+}
+
static void predefine_m68k(const struct target *self)
{
predefine("__m68k__", 1, "1");
@@ -19,5 +27,6 @@ const struct target target_m68k = {
.bits_in_longdouble = 96,
.max_fp_alignment = 4,
+ .init = init_m68k,
.predefine = predefine_m68k,
};
diff --git a/target-microblaze.c b/target-microblaze.c
index 1fbeef3c..3a4c3d58 100644
--- a/target-microblaze.c
+++ b/target-microblaze.c
@@ -3,6 +3,14 @@
#include "machine.h"
+static void init_microblaze(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+}
+
static void predefine_microblaze(const struct target *self)
{
predefine("__MICROBLAZE__", 1, "1");
@@ -21,5 +29,6 @@ const struct target target_microblaze = {
.bits_in_longdouble = 64,
+ .init = init_microblaze,
.predefine = predefine_microblaze,
};
diff --git a/target-mips.c b/target-mips.c
index 3d73236f..1ff0760c 100644
--- a/target-mips.c
+++ b/target-mips.c
@@ -10,6 +10,16 @@ static void predefine_mips(const struct target *self)
predefine("_MIPS_SZINT", 1, "%d", int_ctype.bit_size);
predefine("_MIPS_SZLONG", 1, "%d", long_ctype.bit_size);
predefine("_MIPS_SZPTR", 1, "%d", ptr_ctype.bit_size);
+
+ if (arch_big_endian) {
+ predefine("_MIPSEB", 1, "1");
+ predefine("__MIPSEB", 1, "1");
+ predefine("__MIPSEB__", 1, "1");
+ } else {
+ predefine("_MIPSEL", 1, "1");
+ predefine("__MIPSEL", 1, "1");
+ predefine("__MIPSEL__", 1, "1");
+ }
}
diff --git a/target-nds32.c b/target-nds32.c
new file mode 100644
index 00000000..e3ed2e52
--- /dev/null
+++ b/target-nds32.c
@@ -0,0 +1,33 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_nds32(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ wchar_ctype = &uint_ctype;
+}
+
+static void predefine_nds32(const struct target *self)
+{
+ predefine("__NDS32__", 1, "1");
+ predefine("__nds32__", 1, "1");
+
+ predefine_weak("__NDS32_E%c__", arch_big_endian ? 'B' : 'L');
+}
+
+const struct target target_nds32 = {
+ .mach = MACH_NDS32,
+ .bitness = ARCH_LP32,
+ .big_endian = false,
+
+ .bits_in_longdouble = 64,
+
+ .init = init_nds32,
+ .predefine = predefine_nds32,
+};
diff --git a/target-nios2.c b/target-nios2.c
index 05f0926e..c57b1719 100644
--- a/target-nios2.c
+++ b/target-nios2.c
@@ -4,15 +4,28 @@
#include "builtin.h"
+static void init_nios2(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+}
+
static void predefine_nios2(const struct target *self)
{
+ predefine("__NIOS2", 1, "1");
predefine("__NIOS2__", 1, "1");
+ predefine("__nios2", 1, "1");
predefine("__nios2__", 1, "1");
- if (arch_big_endian)
+ if (arch_big_endian) {
+ predefine("__nios2_big_endian", 1, "1");
predefine("__nios2_big_endian__", 1, "1");
- else
+ } else {
+ predefine("__nios2_little_endian", 1, "1");
predefine("__nios2_little_endian__", 1, "1");
+ }
}
static const struct builtin_fn builtins_nios2[] = {
@@ -26,6 +39,9 @@ const struct target target_nios2 = {
.mach = MACH_NIOS2,
.bitness = ARCH_LP32,
+ .bits_in_longdouble = 64,
+
+ .init = init_nios2,
.predefine = predefine_nios2,
.builtins = builtins_nios2,
};
diff --git a/target-openrisc.c b/target-openrisc.c
new file mode 100644
index 00000000..ad25ff27
--- /dev/null
+++ b/target-openrisc.c
@@ -0,0 +1,31 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_openrisc(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ wchar_ctype = &uint_ctype;
+}
+
+static void predefine_openrisc(const struct target *self)
+{
+ predefine_weak("__OR1K__");
+ predefine_weak("__or1k__");
+}
+
+const struct target target_openrisc = {
+ .mach = MACH_NDS32,
+ .bitness = ARCH_LP32,
+ .big_endian = true,
+
+ .bits_in_longdouble = 64,
+
+ .init = init_openrisc,
+ .predefine = predefine_openrisc,
+};
diff --git a/target-ppc.c b/target-ppc.c
index c0d6068f..6c0c0737 100644
--- a/target-ppc.c
+++ b/target-ppc.c
@@ -14,6 +14,10 @@ static void predefine_ppc(const struct target *self)
predefine("_ARCH_PPC", 1, "1");
if (arch_big_endian)
predefine("_BIG_ENDIAN", 1, "1");
+ if (ldouble_ctype.bit_size == 128) {
+ predefine("__LONGDOUBLE128", 1, "1");
+ predefine("__LONG_DOUBLE_128__", 1, "1");
+ }
}
static const char *asm_constraint_ppc(struct asm_operand *op, int c, const char *str)
@@ -27,6 +31,14 @@ static const char *asm_constraint_ppc(struct asm_operand *op, int c, const char
}
+static void init_ppc32(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+}
+
static void predefine_ppc32(const struct target *self)
{
predefine_ppc(self);
@@ -42,6 +54,7 @@ const struct target target_ppc32 = {
.target_64bit = &target_ppc64,
+ .init = init_ppc32,
.predefine = predefine_ppc32,
.asm_constraint = asm_constraint_ppc,
};
diff --git a/target-riscv.c b/target-riscv.c
index d68fb585..6d9113c1 100644
--- a/target-riscv.c
+++ b/target-riscv.c
@@ -1,7 +1,80 @@
+#include "lib.h"
#include "symbol.h"
#include "target.h"
#include "machine.h"
+#include <string.h>
+#define RISCV_32BIT (1 << 0)
+#define RISCV_64BIT (1 << 1)
+#define RISCV_MUL (1 << 2)
+#define RISCV_DIV (1 << 3)
+#define RISCV_ATOMIC (1 << 4)
+#define RISCV_FLOAT (1 << 5)
+#define RISCV_DOUBLE (1 << 6)
+#define RISCV_FDIV (1 << 7)
+#define RISCV_COMP (1 << 8)
+#define RISCV_EMBD (1 << 9)
+#define RISCV_FPU (RISCV_FLOAT|RISCV_DOUBLE|RISCV_FDIV)
+#define RISCV_GENERIC (RISCV_MUL|RISCV_DIV|RISCV_ATOMIC|RISCV_FPU)
+
+static unsigned int riscv_flags;
+
+static void parse_march_riscv(const char *arg)
+{
+ static struct {
+ const char *pattern;
+ unsigned int flags;
+ } basic_sets[] = {
+ { "rv32i", RISCV_32BIT },
+ { "rv32e", RISCV_32BIT|RISCV_EMBD },
+ { "rv32g", RISCV_32BIT|RISCV_GENERIC },
+ { "rv64i", RISCV_64BIT },
+ { "rv64g", RISCV_64BIT|RISCV_GENERIC },
+ }, extensions[] = {
+ { "m", RISCV_MUL|RISCV_DIV },
+ { "a", RISCV_ATOMIC },
+ { "f", RISCV_FLOAT|RISCV_FDIV },
+ { "d", RISCV_DOUBLE|RISCV_FDIV },
+ { "g", RISCV_GENERIC },
+ { "q", 0 },
+ { "l", 0 },
+ { "c", RISCV_COMP },
+ { "b", 0 },
+ { "j", 0 },
+ { "t", 0 },
+ { "p", 0 },
+ { "v", 0 },
+ { "n", 0 },
+ { "h", 0 },
+ { "s", 0 },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(basic_sets); i++) {
+ const char *pat = basic_sets[i].pattern;
+ size_t len = strlen(pat);
+
+ if (!strncmp(arg, pat, len)) {
+ riscv_flags |= basic_sets[i].flags;
+ arg += len;
+ goto ext;
+ }
+ }
+ die("invalid argument to '-march': '%s'\n", arg);
+
+ext:
+ for (i = 0; i < ARRAY_SIZE(extensions); i++) {
+ const char *pat = extensions[i].pattern;
+ size_t len = strlen(pat);
+
+ if (!strncmp(arg, pat, len)) {
+ riscv_flags |= extensions[i].flags;
+ arg += len;
+ }
+ }
+ if (arg[0])
+ die("invalid argument to '-march': '%s'\n", arg);
+}
static void init_riscv(const struct target *self)
{
@@ -9,6 +82,19 @@ static void init_riscv(const struct target *self)
arch_cmodel = CMODEL_MEDLOW;
if (fpic)
arch_cmodel = CMODEL_PIC;
+
+ if (riscv_flags == 0)
+ riscv_flags = self->flags;
+}
+
+static void init_riscv32(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ init_riscv(self);
}
static void predefine_riscv(const struct target *self)
@@ -23,6 +109,25 @@ static void predefine_riscv(const struct target *self)
predefine("__riscv", 1, "1");
predefine("__riscv_xlen", 1, "%d", ptr_ctype.bit_size);
+ if (riscv_flags & RISCV_ATOMIC)
+ predefine("__riscv_atomic", 1, "1");
+ if (riscv_flags & RISCV_COMP)
+ predefine("__riscv_compressed", 1, "1");
+ if (riscv_flags & RISCV_DIV)
+ predefine("__riscv_div", 1, "1");
+ if (riscv_flags & RISCV_EMBD)
+ predefine("__riscv_32e", 1, "1");
+ if (riscv_flags & RISCV_FPU)
+ predefine("__riscv_flen", 1, "%d", (riscv_flags & RISCV_DOUBLE) ? 64 : 32);
+ if (riscv_flags & RISCV_FDIV)
+ predefine("__riscv_fdiv", 1, "1");
+ if (riscv_flags & RISCV_FDIV)
+ predefine("__riscv_fsqrt", 1, "1");
+ if (riscv_flags & RISCV_MUL)
+ predefine("__riscv_mul", 1, "1");
+ if ((riscv_flags & RISCV_MUL) && (riscv_flags & RISCV_DIV))
+ predefine("__riscv_muldiv", 1, "1");
+
if (cmodel)
predefine_strong("__riscv_cmodel_%s", cmodel);
}
@@ -32,11 +137,13 @@ const struct target target_riscv32 = {
.bitness = ARCH_LP32,
.big_endian = 0,
.unsigned_char = 1,
+ .flags = RISCV_32BIT|RISCV_GENERIC|RISCV_COMP,
.target_64bit = &target_riscv64,
- .init = init_riscv,
+ .init = init_riscv32,
.predefine = predefine_riscv,
+ .parse_march = parse_march_riscv,
};
const struct target target_riscv64 = {
@@ -45,9 +152,11 @@ const struct target target_riscv64 = {
.big_endian = 0,
.unsigned_char = 1,
.has_int128 = 1,
+ .flags = RISCV_64BIT|RISCV_GENERIC|RISCV_COMP,
.target_32bit = &target_riscv32,
.init = init_riscv,
.predefine = predefine_riscv,
+ .parse_march = parse_march_riscv,
};
diff --git a/target-s390.c b/target-s390.c
index 9dbc810e..84889c0a 100644
--- a/target-s390.c
+++ b/target-s390.c
@@ -4,6 +4,17 @@
#include "expression.h"
+static void init_s390(const struct target *self)
+{
+ intptr_ctype = &int_ctype;
+ uintptr_ctype = &uint_ctype;
+
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+}
+
static void predefine_s390(const struct target *self)
{
predefine("__s390__", 1, "1");
@@ -31,6 +42,7 @@ const struct target target_s390 = {
.target_64bit = &target_s390x,
+ .init = init_s390,
.predefine = predefine_s390,
.asm_constraint = asm_constraint_s390,
};
diff --git a/target-sh.c b/target-sh.c
new file mode 100644
index 00000000..d3a66180
--- /dev/null
+++ b/target-sh.c
@@ -0,0 +1,36 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_sh(const struct target *self)
+{
+ int64_ctype = &llong_ctype;
+ uint64_ctype = &ullong_ctype;
+ intptr_ctype = &int_ctype;
+ uintptr_ctype = &uint_ctype;
+
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ wchar_ctype = &long_ctype;
+}
+
+static void predefine_sh(const struct target *self)
+{
+ predefine_weak("__SH4__");
+ predefine_weak("__sh__");
+}
+
+const struct target target_sh = {
+ .mach = MACH_SH,
+ .bitness = ARCH_LP32,
+ .big_endian = false,
+
+ .bits_in_longdouble = 64,
+
+ .init = init_sh,
+ .predefine = predefine_sh,
+};
diff --git a/target-sparc.c b/target-sparc.c
index bd48effe..d830f6cb 100644
--- a/target-sparc.c
+++ b/target-sparc.c
@@ -3,22 +3,38 @@
#include "machine.h"
+static int sparc_version;
+
static void predefine_sparc(const struct target *self)
{
predefine("__sparc__", 1, "1");
predefine("__sparc", 1, "1");
predefine_nostd("sparc");
+
+ predefine_weak("__sparc_v%d__", sparc_version);
+ predefine_weak("__sparcv%d__", sparc_version);
+ predefine_weak("__sparcv%d", sparc_version);
}
static void init_sparc32(const struct target *target)
{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ if (!sparc_version)
+ sparc_version = 8;
+
if (arch_os == OS_SUNOS) {
wint_ctype = &long_ctype;
wchar_ctype = &long_ctype;
bits_in_longdouble = 128;
max_fp_alignment = 16;
+
+ funsigned_char = 0;
}
}
@@ -43,11 +59,14 @@ const struct target target_sparc32 = {
};
+static void init_sparc64(const struct target *target)
+{
+ if (!sparc_version)
+ sparc_version = 9;
+}
+
static void predefine_sparc64(const struct target *self)
{
- predefine("__sparc_v9__", 1, "1");
- predefine("__sparcv9__", 1, "1");
- predefine("__sparcv9", 1, "1");
predefine("__sparc64__", 1, "1");
predefine("__arch64__", 1, "1");
@@ -63,5 +82,6 @@ const struct target target_sparc64 = {
.target_32bit = &target_sparc32,
+ .init = init_sparc64,
.predefine = predefine_sparc64,
};
diff --git a/target-x86.c b/target-x86.c
index d770349c..b7ff8f2a 100644
--- a/target-x86.c
+++ b/target-x86.c
@@ -3,33 +3,51 @@
#include "machine.h"
-static void init_x86(const struct target *target)
+static void predefine_i386(const struct target *self)
+{
+ predefine("__i386__", 1, "1");
+ predefine("__i386", 1, "1");
+ predefine_nostd("i386");
+}
+
+static void predefine_x86_64(const struct target *self)
+{
+ predefine("__x86_64__", 1, "1");
+ predefine("__x86_64", 1, "1");
+ predefine("__amd64__", 1, "1");
+ predefine("__amd64", 1, "1");
+}
+
+
+static void init_x86_common(const struct target *target)
{
switch (arch_os) {
case OS_CYGWIN:
wchar_ctype = &ushort_ctype;
break;
- case OS_DARWIN:
- int64_ctype = &llong_ctype;
- uint64_ctype = &ullong_ctype;
- wint_ctype = &int_ctype;
- break;
case OS_FREEBSD:
wint_ctype = &int_ctype;
break;
case OS_OPENBSD:
+ size_t_ctype = &ulong_ctype;
+ ssize_t_ctype = &long_ctype;
wchar_ctype = &int_ctype;
wint_ctype = &int_ctype;
+ fast16_ctype = &short_ctype;
+ ufast16_ctype = &ushort_ctype;
break;
}
}
-static void predefine_i386(const struct target *self)
+static void init_i386(const struct target *target)
{
- predefine("__i386__", 1, "1");
- predefine("__i386", 1, "1");
- predefine_nostd("i386");
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ init_x86_common(target);
}
const struct target target_i386 = {
@@ -42,19 +60,88 @@ const struct target target_i386 = {
.bits_in_longdouble = 96,
.max_fp_alignment = 4,
- .init = init_x86,
.target_64bit = &target_x86_64,
+ .init = init_i386,
.predefine = predefine_i386,
};
-static void predefine_x86_64(const struct target *self)
+static void init_x86_x32(const struct target *target)
{
- predefine("__x86_64__", 1, "1");
- predefine("__x86_64", 1, "1");
- predefine("__amd64__", 1, "1");
- predefine("__amd64", 1, "1");
+ init_x86_common(target);
+
+ max_int_alignment = 8;
+
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+ wchar_ctype = &long_ctype;
+}
+
+static const struct target target_x86_x32 = {
+ .mach = MACH_X86_64,
+ .bitness = ARCH_X32,
+ .big_endian = 0,
+ .unsigned_char = 0,
+ .has_int128 = 1,
+
+ .bits_in_longdouble = 128,
+ .max_fp_alignment = 16,
+
+ .target_32bit = &target_i386,
+ .target_64bit = &target_x86_64,
+
+ .init = init_x86_x32,
+ .predefine = predefine_x86_64,
+};
+
+
+static void init_x86_64(const struct target *target)
+{
+ init_x86_common(target);
+
+ switch (arch_os) {
+ case OS_CYGWIN:
+ break;
+ case OS_DARWIN:
+ int64_ctype = &llong_ctype;
+ uint64_ctype = &ullong_ctype;
+ wint_ctype = &int_ctype;
+ fast16_ctype = &short_ctype;
+ ufast16_ctype = &ushort_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+ fast64_ctype = &llong_ctype;
+ ufast64_ctype = &ullong_ctype;
+ break;
+ case OS_FREEBSD:
+ fast16_ctype = &short_ctype;
+ ufast16_ctype = &ushort_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+ break;
+ case OS_NETBSD:
+ fast8_ctype = &int_ctype;
+ ufast8_ctype = &uint_ctype;
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+ wint_ctype = &int_ctype;
+ break;
+ case OS_OPENBSD:
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+ int64_ctype = &llong_ctype;
+ uint64_ctype = &ullong_ctype;
+ intmax_ctype = &llong_ctype;
+ uintmax_ctype = &ullong_ctype;
+ least64_ctype = &long_ctype;
+ uleast64_ctype = &ulong_ctype;
+ break;
+ }
}
const struct target target_x86_64 = {
@@ -67,8 +154,9 @@ const struct target target_x86_64 = {
.bits_in_longdouble = 128,
.max_fp_alignment = 16,
- .init = init_x86,
.target_32bit = &target_i386,
+ .target_x32bit = &target_x86_x32,
+ .init = init_x86_64,
.predefine = predefine_x86_64,
};
diff --git a/target-xtensa.c b/target-xtensa.c
new file mode 100644
index 00000000..26bda47f
--- /dev/null
+++ b/target-xtensa.c
@@ -0,0 +1,36 @@
+#include "symbol.h"
+#include "target.h"
+#include "machine.h"
+
+
+static void init_xtensa(const struct target *self)
+{
+ fast16_ctype = &int_ctype;
+ ufast16_ctype = &uint_ctype;
+ fast32_ctype = &int_ctype;
+ ufast32_ctype = &uint_ctype;
+
+ wchar_ctype = &long_ctype;
+}
+
+static void predefine_xtensa(const struct target *self)
+{
+ predefine("__XTENSA__", 1, "1");
+ predefine("__xtensa__", 1, "1");
+
+ if (arch_big_endian)
+ predefine("__XTENSA_EB__", 1, "1");
+ else
+ predefine("__XTENSA_EL__", 1, "1");
+}
+
+const struct target target_xtensa = {
+ .mach = MACH_XTENSA,
+ .bitness = ARCH_LP32,
+ .big_endian = true,
+
+ .bits_in_longdouble = 64,
+
+ .init = init_xtensa,
+ .predefine = predefine_xtensa,
+};
diff --git a/target.c b/target.c
index 6776c3a1..8ae22d74 100644
--- a/target.c
+++ b/target.c
@@ -5,6 +5,9 @@
#include "target.h"
#include "machine.h"
+struct symbol *ptrdiff_ctype;
+struct symbol *intptr_ctype;
+struct symbol *uintptr_ctype;
struct symbol *size_t_ctype = &ulong_ctype;
struct symbol *ssize_t_ctype = &long_ctype;
struct symbol *intmax_ctype = &long_ctype;
@@ -15,6 +18,23 @@ struct symbol *int32_ctype = &int_ctype;
struct symbol *uint32_ctype = &uint_ctype;
struct symbol *wchar_ctype = &int_ctype;
struct symbol *wint_ctype = &uint_ctype;
+struct symbol *least8_ctype = &schar_ctype;
+struct symbol *uleast8_ctype = &uchar_ctype;
+struct symbol *least16_ctype = &short_ctype;
+struct symbol *uleast16_ctype = &ushort_ctype;
+struct symbol *least32_ctype = &int_ctype;
+struct symbol *uleast32_ctype = &uint_ctype;
+struct symbol *least64_ctype = &llong_ctype;
+struct symbol *uleast64_ctype = &ullong_ctype;
+struct symbol *fast8_ctype = &schar_ctype;
+struct symbol *ufast8_ctype = &uchar_ctype;
+struct symbol *fast16_ctype = &long_ctype;
+struct symbol *ufast16_ctype = &ulong_ctype;
+struct symbol *fast32_ctype = &long_ctype;
+struct symbol *ufast32_ctype = &ulong_ctype;
+struct symbol *fast64_ctype = &long_ctype;
+struct symbol *ufast64_ctype = &ulong_ctype;
+struct symbol *sig_atomic_ctype = &int_ctype;
/*
* For "__attribute__((aligned))"
@@ -60,22 +80,27 @@ static const struct target *targets[] = {
[MACH_ALPHA] = &target_alpha,
[MACH_ARM] = &target_arm,
[MACH_ARM64] = &target_arm64,
- [MACH_I386] = &target_i386,
[MACH_BFIN] = &target_bfin,
- [MACH_X86_64] = &target_x86_64,
+ [MACH_H8300] = &target_h8300,
+ [MACH_I386] = &target_i386,
+ [MACH_M68K] = &target_m68k,
[MACH_MICROBLAZE] = &target_microblaze,
[MACH_MIPS32] = &target_mips32,
[MACH_MIPS64] = &target_mips64,
+ [MACH_NDS32] = &target_nds32,
[MACH_NIOS2] = &target_nios2,
+ [MACH_OPENRISC] = &target_openrisc,
[MACH_PPC32] = &target_ppc32,
[MACH_PPC64] = &target_ppc64,
[MACH_RISCV32] = &target_riscv32,
[MACH_RISCV64] = &target_riscv64,
[MACH_S390] = &target_s390,
[MACH_S390X] = &target_s390x,
+ [MACH_SH] = &target_sh,
[MACH_SPARC32] = &target_sparc32,
[MACH_SPARC64] = &target_sparc64,
- [MACH_M68K] = &target_m68k,
+ [MACH_X86_64] = &target_x86_64,
+ [MACH_XTENSA] = &target_xtensa,
[MACH_UNKNOWN] = &target_default,
};
const struct target *arch_target = &target_default;
@@ -91,12 +116,15 @@ enum machine target_parse(const char *name)
{ "aarch64", MACH_ARM64, 64, },
{ "arm64", MACH_ARM64, 64, },
{ "arm", MACH_ARM, 32, },
- { "i386", MACH_I386, 32, },
{ "bfin", MACH_BFIN, 32, },
+ { "h8300", MACH_H8300, 32, },
+ { "i386", MACH_I386, 32, },
{ "m68k", MACH_M68K, 32, },
{ "microblaze", MACH_MICROBLAZE,32, },
{ "mips", MACH_MIPS32, 0, },
+ { "nds32", MACH_NDS32, 32, },
{ "nios2", MACH_NIOS2, 32, },
+ { "openrisc", MACH_OPENRISC, 32, },
{ "powerpc", MACH_PPC32, 0, },
{ "ppc", MACH_PPC32, 0, },
{ "riscv", MACH_RISCV32, 0, },
@@ -105,6 +133,8 @@ enum machine target_parse(const char *name)
{ "sparc", MACH_SPARC32, 0, },
{ "x86_64", MACH_X86_64, 64, },
{ "x86-64", MACH_X86_64, 64, },
+ { "sh", MACH_SH, 32, },
+ { "xtensa", MACH_XTENSA, 32, },
{ NULL },
};
const struct arch *p;
@@ -136,6 +166,35 @@ enum machine target_parse(const char *name)
return MACH_UNKNOWN;
}
+void target_os(const char *name)
+{
+ static const struct os {
+ const char *name;
+ int os;
+ } oses[] = {
+ { "cygwin", OS_CYGWIN },
+ { "darwin", OS_DARWIN },
+ { "freebsd", OS_FREEBSD },
+ { "linux", OS_LINUX },
+ { "native", OS_NATIVE, },
+ { "netbsd", OS_NETBSD },
+ { "none", OS_NONE },
+ { "openbsd", OS_OPENBSD },
+ { "sunos", OS_SUNOS },
+ { "unix", OS_UNIX },
+ { NULL },
+ }, *p;
+
+ for (p = &oses[0]; p->name; p++) {
+ if (!strcmp(p->name, name)) {
+ arch_os = p->os;
+ return;
+ }
+ }
+
+ die("invalid os: %s", name);
+}
+
void target_config(enum machine mach)
{
@@ -154,10 +213,17 @@ void target_init(void)
const struct target *target = arch_target;
switch (arch_m64) {
+ case ARCH_X32:
+ if (target->target_x32bit)
+ target = target->target_x32bit;
+ goto case_32bit;
+
case ARCH_LP32:
max_int_alignment = 4;
+ if (target->target_32bit)
+ target = target->target_32bit;
/* fallthrough */
- case ARCH_X32:
+ case_32bit:
bits_in_long = 32;
bits_in_pointer = 32;
pointer_alignment = 4;
@@ -167,8 +233,8 @@ void target_init(void)
uint64_ctype = &ullong_ctype;
intmax_ctype = &llong_ctype;
uintmax_ctype = &ullong_ctype;
- if (target->target_32bit)
- target = target->target_32bit;
+ fast64_ctype = &llong_ctype;
+ ufast64_ctype = &ullong_ctype;
break;
case ARCH_LLP64:
diff --git a/target.h b/target.h
index 8f79426c..92b8af91 100644
--- a/target.h
+++ b/target.h
@@ -5,6 +5,9 @@
extern struct symbol *size_t_ctype;
extern struct symbol *ssize_t_ctype;
+extern struct symbol *ptrdiff_ctype;
+extern struct symbol *intptr_ctype;
+extern struct symbol *uintptr_ctype;
extern struct symbol *intmax_ctype;
extern struct symbol *uintmax_ctype;
extern struct symbol *int64_ctype;
@@ -13,6 +16,23 @@ extern struct symbol *int32_ctype;
extern struct symbol *uint32_ctype;
extern struct symbol *wchar_ctype;
extern struct symbol *wint_ctype;
+extern struct symbol *least8_ctype;
+extern struct symbol *uleast8_ctype;
+extern struct symbol *least16_ctype;
+extern struct symbol *uleast16_ctype;
+extern struct symbol *least32_ctype;
+extern struct symbol *uleast32_ctype;
+extern struct symbol *least64_ctype;
+extern struct symbol *uleast64_ctype;
+extern struct symbol *fast8_ctype;
+extern struct symbol *ufast8_ctype;
+extern struct symbol *fast16_ctype;
+extern struct symbol *ufast16_ctype;
+extern struct symbol *fast32_ctype;
+extern struct symbol *ufast32_ctype;
+extern struct symbol *fast64_ctype;
+extern struct symbol *ufast64_ctype;
+extern struct symbol *sig_atomic_ctype;
/*
* For "__attribute__((aligned))"
@@ -63,6 +83,7 @@ struct target {
unsigned int unsigned_char:1;
unsigned int size_t_long:1;
unsigned int has_int128:1;
+ unsigned long flags;
struct symbol *wchar;
struct symbol *wint;
@@ -71,11 +92,13 @@ struct target {
unsigned int max_fp_alignment;
const struct target *target_32bit;
+ const struct target *target_x32bit;
const struct target *target_64bit;
const struct builtin_fn *builtins;
void (*init)(const struct target *self);
+ void (*parse_march)(const char *arg);
void (*predefine)(const struct target *self);
const char *(*asm_constraint)(struct asm_operand *op, int c, const char *str);
};
@@ -85,26 +108,32 @@ extern const struct target target_alpha;
extern const struct target target_arm;
extern const struct target target_arm64;
extern const struct target target_bfin;
+extern const struct target target_h8300;
extern const struct target target_m68k;
extern const struct target target_microblaze;
extern const struct target target_mips32;
extern const struct target target_mips64;
+extern const struct target target_nds32;
extern const struct target target_nios2;
+extern const struct target target_openrisc;
extern const struct target target_ppc32;
extern const struct target target_ppc64;
extern const struct target target_riscv32;
extern const struct target target_riscv64;
extern const struct target target_s390;
extern const struct target target_s390x;
+extern const struct target target_sh;
extern const struct target target_sparc32;
extern const struct target target_sparc64;
extern const struct target target_i386;
extern const struct target target_x86_64;
+extern const struct target target_xtensa;
/* target.c */
extern const struct target *arch_target;
enum machine target_parse(const char *name);
+void target_os(const char *name);
void target_config(enum machine mach);
void target_init(void);
diff --git a/validation/eval/array-quals-node.c b/validation/eval/array-quals-node.c
new file mode 100644
index 00000000..99a4db13
--- /dev/null
+++ b/validation/eval/array-quals-node.c
@@ -0,0 +1,29 @@
+struct s {
+ int a;
+ int b[3];
+ int c[2][3];
+};
+
+struct c {
+ const struct s s;
+};
+
+extern struct c v;
+
+void f(void)
+{
+ v.s.a = 0;
+ *v.s.b = 0;
+ **v.s.c = 0;
+}
+
+/*
+ * check-name: array-quals-node
+ * check-known-to-fail
+ *
+ * check-error-start
+eval/array-quals-node.c:15:14: error: assignment to const expression
+eval/array-quals-node.c:16:14: error: assignment to const expression
+eval/array-quals-node.c:17:14: error: assignment to const expression
+ * check-error-end
+ */
diff --git a/validation/eval/array-quals0.c b/validation/eval/array-quals0.c
new file mode 100644
index 00000000..30727490
--- /dev/null
+++ b/validation/eval/array-quals0.c
@@ -0,0 +1,6 @@
+static int a[2][3];
+static const int (*p)[3] = a;
+
+/*
+ * check-name: array-quals0
+ */
diff --git a/validation/eval/array-quals1.c b/validation/eval/array-quals1.c
new file mode 100644
index 00000000..d3e54f3e
--- /dev/null
+++ b/validation/eval/array-quals1.c
@@ -0,0 +1,49 @@
+typedef const int ci_t;
+typedef int ia_t[2];
+typedef const int cia_t[2];
+
+static const int ci__a[2];
+static ci_t cit_a[2];
+static const ia_t c_iat;
+static cia_t ciat_;
+static cia_t ciata[2];
+
+static const void *const ok_ci__a = &ci__a;
+static void *const ko_ci__a = &ci__a;
+static const void *const ok_cit_a = &cit_a;
+static void *const ko_cit_a = &cit_a;
+static const void *const ok_c_iat = &c_iat;
+static void *const ko_c_iat = &c_iat;
+static const void *const ok_ciat_ = &ciat_;
+static void *const ko_ciat_ = &ciat_;
+static const void *const ok_ciata = &ciata;
+static void *const ko_ciata = &ciata;
+
+static volatile int vi__a[2];
+static volatile void *const ok_vi__a = &vi__a;
+static void *const ko_vi__a = &vi__a;
+
+/*
+ * check-name: array-quals1
+ *
+ * check-error-start
+eval/array-quals1.c:12:38: warning: incorrect type in initializer (different modifiers)
+eval/array-quals1.c:12:38: expected void *static const [toplevel] ko_ci__a
+eval/array-quals1.c:12:38: got int const ( * )[2]
+eval/array-quals1.c:14:38: warning: incorrect type in initializer (different modifiers)
+eval/array-quals1.c:14:38: expected void *static const [toplevel] ko_cit_a
+eval/array-quals1.c:14:38: got int const [usertype] ( * )[2]
+eval/array-quals1.c:16:38: warning: incorrect type in initializer (different modifiers)
+eval/array-quals1.c:16:38: expected void *static const [toplevel] ko_c_iat
+eval/array-quals1.c:16:38: got int const ( * )[2]
+eval/array-quals1.c:18:38: warning: incorrect type in initializer (different modifiers)
+eval/array-quals1.c:18:38: expected void *static const [toplevel] ko_ciat_
+eval/array-quals1.c:18:38: got int const ( * )[2]
+eval/array-quals1.c:20:38: warning: incorrect type in initializer (different modifiers)
+eval/array-quals1.c:20:38: expected void *static const [toplevel] ko_ciata
+eval/array-quals1.c:20:38: got int const [usertype] ( * )[2][2]
+eval/array-quals1.c:24:41: warning: incorrect type in initializer (different modifiers)
+eval/array-quals1.c:24:41: expected void *static const [toplevel] ko_vi__a
+eval/array-quals1.c:24:41: got int volatile ( * )[2]
+ * check-error-end
+ */
diff --git a/validation/linear/bug-assign-op0.c b/validation/linear/bug-assign-op0.c
new file mode 100644
index 00000000..0cabc622
--- /dev/null
+++ b/validation/linear/bug-assign-op0.c
@@ -0,0 +1,115 @@
+int asr(int s)
+{
+ s >>= 11U;
+ return s;
+}
+
+unsigned int lsr(unsigned int u)
+{
+ u >>= 11;
+ return u;
+}
+
+int divr(int s, unsigned long u)
+{
+ extern int use(int, unsigned);
+ int t = s;
+ s = s / u;
+ u = u / t;
+ return use(s, u);
+}
+
+int sdivul(int s, unsigned long u)
+{
+ s /= u; // divu
+ return s;
+}
+
+unsigned int udivsl(unsigned int u, long s)
+{
+ u /= s; // divs
+ return u;
+}
+
+int uldivs(int s, unsigned long u)
+{
+ u /= s; // divu
+ return u;
+}
+
+unsigned int sldivu(unsigned int u, long s)
+{
+ s /= u; // divs
+ return s;
+}
+
+/*
+ * check-name: bug-assign-op0
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-start
+asr:
+.L0:
+ <entry-point>
+ asr.32 %r2 <- %arg1, $11
+ ret.32 %r2
+
+
+lsr:
+.L2:
+ <entry-point>
+ lsr.32 %r6 <- %arg1, $11
+ ret.32 %r6
+
+
+divr:
+.L4:
+ <entry-point>
+ sext.64 %r11 <- (32) %arg1
+ divu.64 %r13 <- %r11, %arg2
+ trunc.32 %r14 <- (64) %r13
+ divu.64 %r18 <- %arg2, %r11
+ trunc.32 %r21 <- (64) %r18
+ call.32 %r22 <- use, %r14, %r21
+ ret.32 %r22
+
+
+sdivul:
+.L6:
+ <entry-point>
+ sext.64 %r26 <- (32) %arg1
+ divu.64 %r27 <- %r26, %arg2
+ trunc.32 %r28 <- (64) %r27
+ ret.32 %r28
+
+
+udivsl:
+.L8:
+ <entry-point>
+ zext.64 %r33 <- (32) %arg1
+ divs.64 %r34 <- %r33, %arg2
+ trunc.32 %r35 <- (64) %r34
+ ret.32 %r35
+
+
+uldivs:
+.L10:
+ <entry-point>
+ sext.64 %r39 <- (32) %arg1
+ divu.64 %r41 <- %arg2, %r39
+ trunc.32 %r43 <- (64) %r41
+ ret.32 %r43
+
+
+sldivu:
+.L12:
+ <entry-point>
+ zext.64 %r46 <- (32) %arg1
+ divs.64 %r48 <- %arg2, %r46
+ trunc.32 %r50 <- (64) %r48
+ ret.32 %r50
+
+
+ * check-output-end
+ */
diff --git a/validation/static_assert.c b/validation/static_assert.c
index dd5e0c08..0ab5844e 100644
--- a/validation/static_assert.c
+++ b/validation/static_assert.c
@@ -53,6 +53,10 @@ _Static_assert(1, );
_Static_assert(, "");
_Static_assert(,);
+// C2x's version: without message
+_Static_assert(1);
+_Static_assert(0);
+
/*
* check-name: static assertion
*
@@ -67,5 +71,6 @@ static_assert.c:52:19: error: string literal expected for _Static_assert()
static_assert.c:53:16: error: Expected constant expression
static_assert.c:54:16: error: Expected constant expression
static_assert.c:54:17: error: string literal expected for _Static_assert()
+static_assert.c:58:16: error: static assertion failed
* check-error-end
*/