diff options
126 files changed, 4255 insertions, 2299 deletions
@@ -54,6 +54,7 @@ /cparser/pre_parser_messages.ml /cparser/pre_parser.automaton /cparser/pre_parser.messages +/cparser/pre_parser.conflicts /cparser/handcrafted.messages.bak /cparser/handcrafted.messages.raw /cparser/deLexer @@ -75,3 +76,5 @@ runtime/mppa_k1c/i64_smod.s runtime/mppa_k1c/i64_udiv.s runtime/mppa_k1c/i64_udivmod.s runtime/mppa_k1c/i64_umod.s +# Test generated data +/test/clightgen/*.v @@ -1,3 +1,140 @@ +Release 3.4, 2018-09-17 +======================= + +Bug fixing: +- Redefinition of a typedef in a different scope was wrongly rejected. +- Attach `_Alignas(N)` and `__attribute((aligned(N)))` to names + instead of types, so that `_Alignas(16) int * p` means + "16-aligned pointer to int", not "pointer to 16-aligned int". +- For packed structs, fix a discrepancy between the size and alignment + computed during elaboration and those computed by the verified front-end + after expansion. +- Honor qualified array types in function parameters: if a parameter is + declared as e.g. `int t[const 4]`, it is now treated as `int * const t` + in the function body, not `int * t` like before. +- Reject `__builtin_offsetof(struct s, f)` if `f` is a bit-field. +- Wrong parsing of attributes having multiple arguments such as + `__attribute((packed(A,B,C)))`. +- If `__builtin_ais_annot` is followed immediately by a label (e.g. a + loop head), add a nop instruction to separate the annotation from + the label. +- Wrong parsing of the command-line options `-u <symbol>` and `-iquote`. +- PowerPC in hybrid 32/64 bit mode: reject %Q and %R register specifications + in inline assembly code, since 64-bit integer arguments are not split + in two registers. +- x86 64-bit mode: wrong expansion of __builtin_clzl and builtin_ctzl + (issue #127). + +New checks for ISO C conformance: +- Removed support for `_Alignof(expr)`, which is not C11; + only `_Alignof(ty)` is part of C11. +- Reject occurrences of `_Alignas` in places that are not allowed by C11, + e.g. in `typedef`. `__attribute((aligned(N)))` can be used instead. +- Reject occurrences of `restrict` in places that are not allowed by + C99 and C11. +- Reject structs composed of a single flexible array `struct { ty []; }`. +- Check that qualified array types such as `int t[const 4]` occur only + as function parameters, but nowhere else. +- In function definitions, reject function parameters that have no names. + +New warnings: +- Warn for flexible array types `ty[]` in places where they do not make sense. +- Warn for inline (not static inline) functions that declare + non-constant static variables. +- Optionally warn if the alignment of an object is reduced below its + natural alignment because of a _Alignas qualifier or an aligned attribute, + or a packed attribute. +- Warn for tentative static definitions with an incomplete type, e.g. + `static int x[];`. +- The warning about uses of C11 features is now off by default. + +Semantic preservation proof: +- Model the fact that external functions can destroy caller-save registers + and Outgoing stack slots; adapt the proofs accordingly. + +Coq and OCaml development: +- Support Coq versions 8.8.1 and 8.8.2. +- Support OCaml versions 4.7.0 and up. +- Support Menhir versions 20180530 and up. + +Others: +- Improved error handling in "configure" script (issue #244) +- clightgen adds configuration information to the generated .v file (issue #226) + + + +Release 3.3, 2018-05-30 +======================= + +New features: +- Introduced the __builtin_ais_annot built-in function to communicate + source-level annotations to AbsInt's a3 tool suite via a special + section in object and executable files. +- Improved C11 support: define the C11 conditional feature macros; + define the max_align_t type in stddef.h. +- PowerPC 64-bit port: new built-in functions for 64-bit load-store with + byte reversal and for 64-bit integer multiply high. +- x86 64 bits: add support for BSD. + +Bug fixing: +- Wrong code generated for unions containing several bit fields. +- Internal compiler errors for some initializers for structs and + unions containing bit-fields, and for anonymous members of unions. +- Missing error reporting for <integer> - <ptr> subtraction, + causing an internal retyping error later during compilation. +- String literals are l-values. +- String literals have array types, not pointer types. +- Array sizes >= 2^32 were handled incorrectly on 64-bit platforms. +- Wrong code generated for global variables of size 2^31 bytes or more. +- struct and union arguments to annotation builtins must be passed by + reference, regardless of the ABI calling conventions. +- "e1, e2" has pointer type if "e2" has array type. +- x86 64 bits: in "symbol + ofs" addressing modes, the offset "ofs" + must be limited to [-2^24, 2^24) otherwise linking can fail. + +New or improved diagnostics (errors and warnings): +- Warn for comparison of a pointer to a complete type and a pointer to + an incomplete type. +- More checks on variables declared in "for" loops: not static, not + extern, not function types. +- Reject empty declarations in K&R functions. +- Reject arrays of incomplete types. +- Reject duplicate 'case' or 'default' statements within a 'switch'. +- Reject 'case' and 'default' statements outside a 'switch'. +- Check that 'typedef' declares a name and doesn't contain '_Noreturn'. +- Function parameters are in the same scope as function local variables. +- More comprehensive constant-ness checks for initializers of global + or static local variables. +- Make sure an enum cannot have the same tag as a struct or an union. +- More checks on where the 'auto' storage class can be used. +- Accept empty enum declaration after nonempty enum definition. +- Reject pointers to incomplete types in ptr - ptr subtraction. +- When defining a function, take attributes (_Noreturn, etc) from + earlier declarations of the function into account. +- Better check for multiple definitions of functions or global variables. +- Reject illegal initializations of aggregates such as "char c[4] = 42;". +- Reject designated initializers where a member of a composite type is + re-initialized after the composite has been initialized as a whole. +- Reject casts to struct/union types. +- Reject sizeof(e) where e designates a bit-field member of a struct or union. +- "e1, e2" is not a compile-time constant expression even if e1 and e2 are. +- "main" function must not be "inline" +- Warn for functions declared extern after having been defined. +- Warn for function declarations after function definitions when the + declaration has more attributes than the definition. +- Warn for assignment of a volatile struct to a non-volatile struct. +- Warn for "main" function if declared _Noreturn. + +Coq development: +- Added support for Coq versions 8.7.2 and 8.8.0. +- Rewrote "Implicit Arguments" and "Require" inside sections, + these are obsolete in 8.8.0. +- Upgraded Flocq to version 2.6.1. +- Optionally install the .vo files for reuse by other projects + (options -install-coqdev and -coqdevdir to configure script; + automatically selected if option -clightgen is given). + + Release 3.2, 2018-01-15 ======================= @@ -21,9 +21,9 @@ else ARCHDIRS=$(ARCH)_$(BITSIZE) $(ARCH) endif -DIRS=lib common $(ARCHDIRS) backend cfrontend driver debug\ +DIRS=lib common $(ARCHDIRS) backend cfrontend driver \ flocq/Core flocq/Prop flocq/Calc flocq/Appli exportclight \ - cparser cparser/validator + cparser cparser/MenhirLib RECDIRS=lib common $(ARCHDIRS) backend cfrontend driver flocq exportclight cparser @@ -149,6 +149,9 @@ endif proof: $(FILES:.v=.vo) +# Turn off some warnings for compiling Flocq +flocq/%.vo: COQCOPTS+=-w -compatibility-notation + extraction: extraction/STAMP extraction/STAMP: $(FILES:.v=.vo) extraction/extraction.v $(ARCH)/extractionMachdep.v @@ -176,18 +179,11 @@ FORCE: .PHONY: proof extraction runtime FORCE -documentation: doc/coq2html $(FILES) +documentation: $(FILES) mkdir -p doc/html rm -f doc/html/*.html - doc/coq2html -o 'doc/html/%.html' doc/*.glob \ + coq2html -d doc/html/ -base compcert -short-names doc/*.glob \ $(filter-out doc/coq2html cparser/Parser.v, $^) - cp doc/coq2html.css doc/coq2html.js doc/html/ - -doc/coq2html: doc/coq2html.ml - ocamlopt -w +a-29 -o doc/coq2html str.cmxa doc/coq2html.ml - -doc/coq2html.ml: doc/coq2html.mll - ocamllex -q doc/coq2html.mll tools/ndfun: tools/ndfun.ml ocamlopt -o tools/ndfun str.cmxa tools/ndfun.ml @@ -233,7 +229,9 @@ driver/Version.ml: VERSION >driver/Version.ml cparser/Parser.v: cparser/Parser.vy - $(MENHIR) --coq cparser/Parser.vy + @rm -f $@ + $(MENHIR) $(MENHIR_FLAGS) --coq cparser/Parser.vy + @chmod a-w $@ depend: $(GENERATED) depend1 @@ -252,12 +250,21 @@ install: ifeq ($(CLIGHTGEN),true) install -m 0755 ./clightgen $(BINDIR) endif +ifeq ($(INSTALL_COQDEV),true) + install -d $(COQDEVDIR) + for d in $(DIRS); do \ + install -d $(COQDEVDIR)/$$d && \ + install -m 0644 $$d/*.vo $(COQDEVDIR)/$$d/; \ + done + install -m 0644 ./VERSION $(COQDEVDIR) + @(echo "To use, pass the following to coq_makefile or add the following to _CoqProject:"; echo "-R $(COQDEVDIR) compcert") > $(COQDEVDIR)/README +endif + clean: rm -f $(patsubst %, %/*.vo, $(DIRS)) rm -f $(patsubst %, %/.*.aux, $(DIRS)) rm -rf doc/html doc/*.glob - rm -f doc/coq2html.ml doc/coq2html doc/*.cm? doc/*.o rm -f driver/Version.ml rm -f compcert.ini rm -f extraction/STAMP extraction/*.ml extraction/*.mli .depend.extr @@ -1,3 +1,3 @@ -version=3.2 +version=3.4 buildnr= tag= @@ -231,6 +231,7 @@ Inductive instruction : Type := | Prev16: ireg -> ireg -> instruction (**r reverse bytes and reverse bits. *) | Prsc: ireg -> ireg -> shift_op -> instruction (**r reverse subtract without carry. *) | Psbc: ireg -> ireg -> shift_op -> instruction (**r add with carry *) + | Pnop : instruction (**r nop instruction *) (* Add, sub, rsb versions with s suffix *) | Padds: ireg -> ireg -> shift_op -> instruction (**r integer addition with update of condition flags *) | Psubs: ireg -> ireg -> shift_op -> instruction (**r integer subtraction with update of condition flags *) @@ -805,6 +806,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out | Pfsqrt _ _ | Prsc _ _ _ | Psbc _ _ _ + | Pnop | Padds _ _ _ | Psubs _ _ _ | Prsbs _ _ _ @@ -852,6 +854,15 @@ Definition preg_of (r: mreg) : preg := | F12 => FR12 | F13 => FR13 | F14 => FR14 | F15 => FR15 end. +(** Undefine all registers except SP and callee-save registers *) + +Definition undef_caller_save_regs (rs: regset) : regset := + fun r => + if preg_eq r SP + || In_dec preg_eq r (List.map preg_of (List.filter is_callee_save all_mregs)) + then rs r + else Vundef. + (** Extract the values of the arguments of an external call. We exploit the calling conventions from module [Conventions], except that we use ARM registers instead of locations. *) @@ -911,7 +922,7 @@ Inductive step: state -> trace -> state -> Prop := Genv.find_funct_ptr ge b = Some (External ef) -> external_call ef ge args m t res m' -> extcall_arguments rs m (ef_sig ef) args -> - rs' = (set_pair (loc_external_result (ef_sig ef) ) res rs)#PC <- (rs IR14) -> + rs' = (set_pair (loc_external_result (ef_sig ef) ) res (undef_caller_save_regs rs))#PC <- (rs IR14) -> step (State rs m) t (State rs' m'). End RELSEM. diff --git a/arm/AsmToJSON.ml b/arm/AsmToJSON.ml index 276ceecc..3874e141 100644 --- a/arm/AsmToJSON.ml +++ b/arm/AsmToJSON.ml @@ -30,7 +30,7 @@ let mnemonic_names = [ "Padc"; "Padd"; "Padds"; "Pand";"Pannot"; "Pasr"; "Pb"; " "Pftouizs"; "Pfuitod"; "Pfuitos"; "Pinlineasm"; "Pisb"; "Plabel"; "Pldr"; "Ploadsymbol_lbl"; "Pldr_p"; "Pldrb"; "Pldrb_p"; "Pldrh"; "Pldrh_p"; "Pldrsb"; "Pldrsh"; "Plsl"; "Plsr"; "Pmla"; "Pmov"; "Pmovite"; - "Pmovt"; "Pmovw"; "Pmul"; "Pmvn"; "Ploadsymbol_imm"; "Porr"; + "Pmovt"; "Pmovw"; "Pmul"; "Pmvn"; "Ploadsymbol_imm"; "Pnop"; "Porr"; "Ppush"; "Prev"; "Prev16"; "Prsb"; "Prsbs"; "Prsc"; "Psbc"; "Psbfx"; "Psdiv"; "Psmull"; "Pstr"; "Pstr_p"; "Pstrb"; "Pstrb_p"; "Pstrh"; "Pstrh_p"; "Psub"; "Psubs"; "Pudiv"; "Pumull" ] @@ -263,6 +263,7 @@ let pp_instructions pp ic = | Pmovw(r1, n) -> instruction pp "Pmovw" [Ireg r1; Long n] | Pmul(r1, r2, r3) -> instruction pp "Pmul" [Ireg r1; Ireg r2; Ireg r3] | Pmvn(r1, so) -> instruction pp "Pmvn" [Ireg r1; Shift so] + | Pnop -> instruction pp "Pnop" [] | Porr(r1, r2, so) -> instruction pp "Porr" [Ireg r1; Ireg r2; Shift so] | Ppush(rl) -> instruction pp "Ppush" (List.map (fun r -> Ireg r) rl) | Prev(r1, r2) -> instruction pp "Prev" [Ireg r1; Ireg r2] diff --git a/arm/Asmexpand.ml b/arm/Asmexpand.ml index 7c18be6b..d9424d11 100644 --- a/arm/Asmexpand.ml +++ b/arm/Asmexpand.ml @@ -404,6 +404,8 @@ let expand_builtin_inline name args res = (* Vararg stuff *) | "__builtin_va_start", [BA(IR a)], _ -> expand_builtin_va_start a + | "__builtin_nop", [], _ -> + emit Pnop (* Catch-all *) | _ -> raise (Error ("unrecognized builtin " ^ name)) @@ -665,10 +667,7 @@ let expand_function id fn = try set_current_function fn; fixup_arguments Incoming fn.fn_sig; - if !Clflags.option_g then - expand_debug id 13 preg_to_dwarf expand_instruction fn.fn_code - else - List.iter expand_instruction fn.fn_code; + expand id 13 preg_to_dwarf expand_instruction fn.fn_code; let fn = get_current_function () in let fn = Constantexpand.expand_constants fn in Errors.OK fn diff --git a/arm/Asmgen.v b/arm/Asmgen.v index 1d2f360f..f12ea870 100644 --- a/arm/Asmgen.v +++ b/arm/Asmgen.v @@ -24,6 +24,7 @@ Require Import Asm. Require Import Compopts. Local Open Scope string_scope. +Local Open Scope list_scope. Local Open Scope error_monad_scope. (** Extracting integer or float registers. *) diff --git a/arm/Asmgenproof.v b/arm/Asmgenproof.v index abec6815..2c001f45 100644 --- a/arm/Asmgenproof.v +++ b/arm/Asmgenproof.v @@ -926,8 +926,8 @@ Opaque loadind. apply plus_one. eapply exec_step_external; eauto. eapply external_call_symbols_preserved; eauto. apply senv_preserved. econstructor; eauto. - apply agree_set_other; auto with asmgen. - eapply agree_set_pair; eauto. + unfold loc_external_result. apply agree_set_other; auto. apply agree_set_pair; auto. + apply agree_undef_caller_save_regs; auto. - (* return *) inv STACKS. simpl in *. diff --git a/arm/TargetPrinter.ml b/arm/TargetPrinter.ml index 52d2ada6..bf37b0e4 100644 --- a/arm/TargetPrinter.ml +++ b/arm/TargetPrinter.ml @@ -306,6 +306,8 @@ struct fprintf oc " vsqrt.f64 %a, %a\n" freg f1 freg f2 | Psbc (r1,r2,sa) -> fprintf oc " sbc %a, %a, %a\n" ireg r1 ireg r2 shift_op sa + | Pnop -> + fprintf oc " nop\n" | Pstr(r1, r2, sa) | Pstr_a(r1, r2, sa) -> fprintf oc " str %a, [%a, %a]\n" ireg r1 ireg r2 shift_op sa | Pstrb(r1, r2, sa) -> @@ -463,7 +465,7 @@ struct | 1 -> let annot = annot_text preg_annot "sp" (camlstring_of_coqstring txt) args in fprintf oc "%s annotation: %S\n" comment annot | 2 -> let lbl = new_label () in - fprintf oc "%a: " label lbl; + fprintf oc "%a:\n" label lbl; AisAnnot.add_ais_annot lbl preg_annot "r13" (camlstring_of_coqstring txt) args | _ -> assert false end diff --git a/backend/Allocproof.v b/backend/Allocproof.v index 585fb0da..1804f46b 100644 --- a/backend/Allocproof.v +++ b/backend/Allocproof.v @@ -1317,15 +1317,6 @@ Proof. eauto. Qed. -Definition callee_save_loc (l: loc) := - match l with - | R r => is_callee_save r = true - | S sl ofs ty => sl <> Outgoing - end. - -Definition agree_callee_save (ls1 ls2: locset) : Prop := - forall l, callee_save_loc l -> ls1 l = ls2 l. - Lemma return_regs_agree_callee_save: forall caller callee, agree_callee_save caller (return_regs caller callee). @@ -2476,10 +2467,10 @@ Proof. rewrite Locmap.gss. rewrite Locmap.gso by (red; auto). rewrite Locmap.gss. rewrite val_longofwords_eq_1 by auto. auto. red; intros. rewrite (AG l H0). - symmetry; apply Locmap.gpo. - assert (X: forall r, is_callee_save r = false -> Loc.diff l (R r)). - { intros. destruct l; simpl in *. congruence. auto. } - generalize (loc_result_caller_save (ef_sig ef)). destruct (loc_result (ef_sig ef)); simpl; intuition auto. + rewrite locmap_get_set_loc_result_callee_save by auto. + unfold undef_caller_save_regs. destruct l; simpl in H0. + rewrite H0; auto. + destruct sl; auto; congruence. eapply external_call_well_typed; eauto. (* return *) diff --git a/backend/Asmexpandaux.ml b/backend/Asmexpandaux.ml index 62c4a702..0f666a65 100644 --- a/backend/Asmexpandaux.ml +++ b/backend/Asmexpandaux.ml @@ -97,6 +97,16 @@ let translate_annot sp preg_to_dwarf annot = | [] -> None | a::_ -> aux a) +let builtin_nop = + let signature ={sig_args = []; sig_res = None; sig_cc = cc_default} in + let name = coqstring_of_camlstring "__builtin_nop" in + Pbuiltin(EF_builtin(name,signature),[],BR_none) + +let rec lbl_follows = function + | Pbuiltin (EF_debug _, _, _):: rest -> + lbl_follows rest + | Plabel _ :: _ -> true + | _ -> false let expand_debug id sp preg simple l = let get_lbl = function @@ -144,6 +154,11 @@ let expand_debug id sp preg simple l = | _ -> aux None scopes rest end + | (Pbuiltin(EF_annot (kind, _, _),_,_) as annot)::rest -> + simple annot; + if P.to_int kind = 2 && lbl_follows rest then + simple builtin_nop; + aux None scopes rest | (Plabel lbl)::rest -> simple (Plabel lbl); aux (Some lbl) scopes rest | i::rest -> simple i; aux None scopes rest in (* We need to move all closing debug annotations before the last real statement *) @@ -157,3 +172,20 @@ let expand_debug id sp preg simple l = | b::rest -> List.rev ((List.rev (b::bcc)@List.rev acc)@rest) (* We found the first non debug location *) | [] -> List.rev acc (* This actually can never happen *) in aux None [] (move_debug [] [] (List.rev l)) + +let expand_simple simple l = + let rec aux = function + | (Pbuiltin(EF_annot (kind, _, _),_,_) as annot)::rest -> + simple annot; + if P.to_int kind = 2 && lbl_follows rest then + simple builtin_nop; + aux rest + | i::rest -> simple i; aux rest + | [] -> () in + aux l + +let expand id sp preg simple l = + if !Clflags.option_g then + expand_debug id sp preg simple l + else + expand_simple simple l diff --git a/backend/Asmexpandaux.mli b/backend/Asmexpandaux.mli index 797eb10c..d80b4aec 100644 --- a/backend/Asmexpandaux.mli +++ b/backend/Asmexpandaux.mli @@ -31,6 +31,6 @@ val set_current_function: coq_function -> unit (* Set the current function *) val get_current_function: unit -> coq_function (* Get the current function *) -val expand_debug: positive -> int -> (preg -> int) -> (instruction -> unit) -> instruction list -> unit - (* Expand builtin debug function. Takes the function id, the register number of the stackpointer, a - function to get the dwarf mapping of varibale names and for the expansion of simple instructions *) +val expand: positive -> int -> (preg -> int) -> (instruction -> unit) -> instruction list -> unit + (* Expand the instruction sequence of a function. Takes the function id, the register number of the stackpointer, a + function to get the dwarf mapping of varibale names and for the expansion of simple instructions *) diff --git a/backend/Asmgenproof0.v b/backend/Asmgenproof0.v index 8dfa8828..3e25c79b 100644 --- a/backend/Asmgenproof0.v +++ b/backend/Asmgenproof0.v @@ -318,6 +318,23 @@ Proof. intros. rewrite Pregmap.gso; auto. Qed. +Lemma agree_undef_caller_save_regs: + forall ms sp rs, + agree ms sp rs -> + agree (Mach.undef_caller_save_regs ms) sp (Asm.undef_caller_save_regs rs). +Proof. + intros. destruct H. unfold Mach.undef_caller_save_regs, Asm.undef_caller_save_regs; split. +- unfold proj_sumbool; rewrite dec_eq_true. auto. +- auto. +- intros. unfold proj_sumbool. rewrite dec_eq_false by (apply preg_of_not_SP). + destruct (in_dec preg_eq (preg_of r) (List.map preg_of (List.filter is_callee_save all_mregs))); simpl. ++ apply list_in_map_inv in i. destruct i as (mr & A & B). + assert (r = mr) by (apply preg_of_injective; auto). subst mr; clear A. + apply List.filter_In in B. destruct B as [C D]. rewrite D. auto. ++ destruct (is_callee_save r) eqn:CS; auto. + elim n. apply List.in_map. apply List.filter_In. auto using all_mregs_complete. +Qed. + Lemma agree_change_sp: forall ms sp rs sp', agree ms sp rs -> sp' <> Vundef -> diff --git a/backend/Conventions.v b/backend/Conventions.v index bdc4c8b6..989bfa05 100644 --- a/backend/Conventions.v +++ b/backend/Conventions.v @@ -103,3 +103,56 @@ Proof. generalize (loc_arguments_bounded _ _ _ H0). generalize (typesize_pos ty). omega. Qed. + + +(** * Callee-save locations *) + +(** We classify locations as either +- callee-save, i.e. preserved across function calls: + callee-save registers, [Local] and [Incoming] stack slots; +- caller-save, i.e. possibly modified by a function call: + non-callee-save registers, [Outgoing] stack slots. + +Concerning [Outgoing] stack slots: several ABIs allow a function to modify +the stack slots used for passing parameters to this function. +The code currently generated by CompCert never does so, but the code +generated by other compilers often does so (e.g. GCC for x86-32). +Hence, CompCert-generated code must not assume that [Outgoing] stack slots +are preserved across function calls, because they might not be preserved +if the called function was compiled by another compiler. +*) + +Definition callee_save_loc (l: loc) := + match l with + | R r => is_callee_save r = true + | S sl ofs ty => sl <> Outgoing + end. + +Hint Unfold callee_save_loc. + +Definition agree_callee_save (ls1 ls2: Locmap.t) : Prop := + forall l, callee_save_loc l -> ls1 l = ls2 l. + +(** * Assigning result locations *) + +(** Useful lemmas to reason about the result of an external call. *) + +Lemma locmap_get_set_loc_result: + forall sg v rs l, + match l with R r => is_callee_save r = true | S _ _ _ => True end -> + Locmap.setpair (loc_result sg) v rs l = rs l. +Proof. + intros. apply Locmap.gpo. + assert (X: forall r, is_callee_save r = false -> Loc.diff l (R r)). + { intros. destruct l; simpl. congruence. auto. } + generalize (loc_result_caller_save sg). destruct (loc_result sg); simpl; intuition auto. +Qed. + +Lemma locmap_get_set_loc_result_callee_save: + forall sg v rs l, + callee_save_loc l -> + Locmap.setpair (loc_result sg) v rs l = rs l. +Proof. + intros. apply locmap_get_set_loc_result. + red in H; destruct l; auto. +Qed. diff --git a/backend/LTL.v b/backend/LTL.v index 8567a891..5e7eec8c 100644 --- a/backend/LTL.v +++ b/backend/LTL.v @@ -96,16 +96,31 @@ Definition call_regs (caller: locset) : locset := - Callee-save machine registers have the same values as in the caller before the call. - Caller-save machine registers have the same values as in the callee. -- Stack slots have the same values as in the caller. +- Local and Incoming stack slots have the same values as in the caller. +- Outgoing stack slots are set to Vundef to reflect the fact that they + may have been changed by the callee. *) Definition return_regs (caller callee: locset) : locset := fun (l: loc) => match l with | R r => if is_callee_save r then caller (R r) else callee (R r) + | S Outgoing ofs ty => Vundef | S sl ofs ty => caller (S sl ofs ty) end. +(** [undef_caller_save_regs ls] models the effect of calling + an external function: caller-save registers and outgoing locations + can change unpredictably, hence we set them to [Vundef]. *) + +Definition undef_caller_save_regs (ls: locset) : locset := + fun (l: loc) => + match l with + | R r => if is_callee_save r then ls (R r) else Vundef + | S Outgoing ofs ty => Vundef + | S sl ofs ty => ls (S sl ofs ty) + end. + (** LTL execution states. *) Inductive stackframe : Type := @@ -259,7 +274,7 @@ Inductive step: state -> trace -> state -> Prop := | exec_function_external: forall s ef t args res rs m rs' m', args = map (fun p => Locmap.getpair p rs) (loc_arguments (ef_sig ef)) -> external_call ef ge args m t res m' -> - rs' = Locmap.setpair (loc_result (ef_sig ef)) res rs -> + rs' = Locmap.setpair (loc_result (ef_sig ef)) res (undef_caller_save_regs rs) -> step (Callstate s (External ef) rs m) t (Returnstate s rs' m') | exec_return: forall f sp rs1 bb s rs m, diff --git a/backend/Linear.v b/backend/Linear.v index 55f92d16..447c6ba6 100644 --- a/backend/Linear.v +++ b/backend/Linear.v @@ -239,7 +239,7 @@ Inductive step: state -> trace -> state -> Prop := forall s ef args res rs1 rs2 m t m', args = map (fun p => Locmap.getpair p rs1) (loc_arguments (ef_sig ef)) -> external_call ef ge args m t res m' -> - rs2 = Locmap.setpair (loc_result (ef_sig ef)) res rs1 -> + rs2 = Locmap.setpair (loc_result (ef_sig ef)) res (undef_caller_save_regs rs1) -> step (Callstate s (External ef) rs1 m) t (Returnstate s rs2 m') | exec_return: diff --git a/backend/Lineartyping.v b/backend/Lineartyping.v index d5fadd4c..55d86448 100644 --- a/backend/Lineartyping.v +++ b/backend/Lineartyping.v @@ -146,7 +146,18 @@ Lemma wt_return_regs: wt_locset caller -> wt_locset callee -> wt_locset (return_regs caller callee). Proof. intros; red; intros. - unfold return_regs. destruct l; auto. destruct (is_callee_save r); auto. + unfold return_regs. destruct l. +- destruct (is_callee_save r); auto. +- destruct sl; auto; red; auto. +Qed. + +Lemma wt_undef_caller_save_regs: + forall ls, wt_locset ls -> wt_locset (undef_caller_save_regs ls). +Proof. + intros; red; intros. unfold undef_caller_save_regs. + destruct l. + destruct (is_callee_save r); auto; simpl; auto. + destruct sl; auto; red; auto. Qed. Lemma wt_init: @@ -197,6 +208,24 @@ Proof. auto. Qed. +(** In addition to type preservation during evaluation, we also show + properties of the environment [ls] at call points and at return points. + These properties are used in the proof of the [Stacking] pass. + For call points, we have that the current environment [ls] and the + one from the top call stack agree on the [Outgoing] locations + used for parameter passing. *) + +Definition agree_outgoing_arguments (sg: signature) (ls pls: locset) : Prop := + forall ty ofs, + In (S Outgoing ofs ty) (regs_of_rpairs (loc_arguments sg)) -> + ls (S Outgoing ofs ty) = pls (S Outgoing ofs ty). + +(** For return points, we have that all [Outgoing] stack locations have + been set to [Vundef]. *) + +Definition outgoing_undef (ls: locset) : Prop := + forall ty ofs, ls (S Outgoing ofs ty) = Vundef. + (** Soundness of the type system *) Definition wt_fundef (fd: fundef) := @@ -233,11 +262,15 @@ Inductive wt_state: state -> Prop := | wt_call_state: forall s fd rs m (WTSTK: wt_callstack s) (WTFD: wt_fundef fd) - (WTRS: wt_locset rs), + (WTRS: wt_locset rs) + (AGCS: agree_callee_save rs (parent_locset s)) + (AGARGS: agree_outgoing_arguments (funsig fd) rs (parent_locset s)), wt_state (Callstate s fd rs m) | wt_return_state: forall s rs m (WTSTK: wt_callstack s) - (WTRS: wt_locset rs), + (WTRS: wt_locset rs) + (AGCS: agree_callee_save rs (parent_locset s)) + (UOUT: outgoing_undef rs), wt_state (Returnstate s rs m). (** Preservation of state typing by transitions *) @@ -307,11 +340,15 @@ Local Opaque mreg_type. simpl in *; InvBooleans. econstructor; eauto. econstructor; eauto. eapply wt_find_function; eauto. + red; simpl; auto. + red; simpl; auto. - (* tailcall *) simpl in *; InvBooleans. econstructor; eauto. eapply wt_find_function; eauto. apply wt_return_regs; auto. apply wt_parent_locset; auto. + red; simpl; intros. destruct l; simpl in *. rewrite H3; auto. destruct sl; auto; congruence. + red; simpl; intros. apply zero_size_arguments_tailcall_possible in H. apply H in H3. contradiction. - (* builtin *) simpl in *; InvBooleans. econstructor; eauto. @@ -334,13 +371,20 @@ Local Opaque mreg_type. simpl in *. InvBooleans. econstructor; eauto. apply wt_return_regs; auto. apply wt_parent_locset; auto. + red; simpl; intros. destruct l; simpl in *. rewrite H0; auto. destruct sl; auto; congruence. + red; simpl; intros. auto. - (* internal function *) simpl in WTFD. econstructor. eauto. eauto. eauto. apply wt_undef_regs. apply wt_call_regs. auto. - (* external function *) - econstructor. auto. apply wt_setpair; auto. + econstructor. auto. apply wt_setpair. eapply external_call_well_typed; eauto. + apply wt_undef_caller_save_regs; auto. + red; simpl; intros. destruct l; simpl in *. + rewrite locmap_get_set_loc_result by auto. simpl. rewrite H; auto. + rewrite locmap_get_set_loc_result by auto. simpl. destruct sl; auto; congruence. + red; simpl; intros. rewrite locmap_get_set_loc_result by auto. auto. - (* return *) inv WTSTK. econstructor; eauto. Qed. @@ -352,6 +396,8 @@ Proof. unfold ge0 in H1. exploit Genv.find_funct_ptr_inversion; eauto. intros [id IN]. eapply wt_prog; eauto. apply wt_init. + red; auto. + red; auto. Qed. End SOUNDNESS. @@ -397,3 +443,19 @@ Lemma wt_callstate_wt_regs: Proof. intros. inv H. apply WTRS. Qed. + +Lemma wt_callstate_agree: + forall s f rs m, + wt_state (Callstate s f rs m) -> + agree_callee_save rs (parent_locset s) /\ agree_outgoing_arguments (funsig f) rs (parent_locset s). +Proof. + intros. inv H; auto. +Qed. + +Lemma wt_returnstate_agree: + forall s rs m, + wt_state (Returnstate s rs m) -> + agree_callee_save rs (parent_locset s) /\ outgoing_undef rs. +Proof. + intros. inv H; auto. +Qed. diff --git a/backend/Mach.v b/backend/Mach.v index 839a25bd..9fdee9eb 100644 --- a/backend/Mach.v +++ b/backend/Mach.v @@ -156,6 +156,9 @@ Proof. unfold Regmap.set. destruct (RegEq.eq r a); auto. Qed. +Definition undef_caller_save_regs (rs: regset) : regset := + fun r => if is_callee_save r then rs r else Vundef. + Definition set_pair (p: rpair mreg) (v: val) (rs: regset) : regset := match p with | One r => rs#r <- v @@ -407,7 +410,7 @@ Inductive step: state -> trace -> state -> Prop := Genv.find_funct_ptr ge fb = Some (External ef) -> extcall_arguments rs m (parent_sp s) (ef_sig ef) args -> external_call ef ge args m t res m' -> - rs' = set_pair (loc_result (ef_sig ef)) res rs -> + rs' = set_pair (loc_result (ef_sig ef)) res (undef_caller_save_regs rs) -> step (Callstate s fb rs m) t (Returnstate s rs' m') | exec_return: diff --git a/backend/Regalloc.ml b/backend/Regalloc.ml index d4d7362d..19aba4f6 100644 --- a/backend/Regalloc.ml +++ b/backend/Regalloc.ml @@ -644,7 +644,7 @@ let add_interfs_instr g instr live = (* Reloads from incoming slots can occur when some 64-bit parameters are split and passed as two 32-bit stack locations. *) begin match src with - | L(Locations.S(Incoming, _, _)) -> + | L(Locations.S(Incoming, _, _)) -> add_interfs_def g (vmreg temp_for_parent_frame) live | _ -> () end @@ -1210,9 +1210,9 @@ let regalloc f = Errors.OK(first_round f3 liveness) with | Timeout -> - Errors.Error(Errors.msg (coqstring_of_camlstring "Spilling fails to converge")) + Errors.Error(Errors.msg (coqstring_of_camlstring "spilling fails to converge")) | Type_error_at pc -> - Errors.Error [Errors.MSG(coqstring_of_camlstring "Ill-typed XTL code at PC "); + Errors.Error [Errors.MSG(coqstring_of_camlstring "ill-typed XTL code at PC "); Errors.POS pc] | Bad_LTL -> - Errors.Error(Errors.msg (coqstring_of_camlstring "Bad LTL after spilling")) + Errors.Error(Errors.msg (coqstring_of_camlstring "bad LTL after spilling")) diff --git a/backend/Stackingproof.v b/backend/Stackingproof.v index 6d46d04d..c9b07427 100644 --- a/backend/Stackingproof.v +++ b/backend/Stackingproof.v @@ -294,12 +294,13 @@ Qed. Lemma contains_locations_exten: forall ls ls' j sp pos bound sl, - (forall ofs ty, ls' (S sl ofs ty) = ls (S sl ofs ty)) -> + (forall ofs ty, Val.lessdef (ls' (S sl ofs ty)) (ls (S sl ofs ty))) -> massert_imp (contains_locations j sp pos bound sl ls) (contains_locations j sp pos bound sl ls'). Proof. intros; split; simpl; intros; auto. - intuition auto. rewrite H. eauto. + intuition auto. exploit H5; eauto. intros (v & A & B). exists v; split; auto. + specialize (H ofs ty). inv H. congruence. auto. Qed. Lemma contains_locations_incr: @@ -481,7 +482,8 @@ Qed. Lemma frame_contents_exten: forall ls ls0 ls' ls0' j sp parent retaddr P m, - (forall sl ofs ty, ls' (S sl ofs ty) = ls (S sl ofs ty)) -> + (forall ofs ty, Val.lessdef (ls' (S Local ofs ty)) (ls (S Local ofs ty))) -> + (forall ofs ty, Val.lessdef (ls' (S Outgoing ofs ty)) (ls (S Outgoing ofs ty))) -> (forall r, In r b.(used_callee_save) -> ls0' (R r) = ls0 (R r)) -> m |= frame_contents j sp ls ls0 parent retaddr ** P -> m |= frame_contents j sp ls' ls0' parent retaddr ** P. @@ -573,16 +575,6 @@ Record agree_locs (ls ls0: locset) : Prop := ls (S Incoming ofs ty) = ls0 (S Outgoing ofs ty) }. -(** Auxiliary predicate used at call points *) - -Definition agree_callee_save (ls ls0: locset) : Prop := - forall l, - match l with - | R r => is_callee_save r = true - | S _ _ _ => True - end -> - ls l = ls0 l. - (** ** Properties of [agree_regs]. *) (** Values of registers *) @@ -666,6 +658,16 @@ Proof. apply agree_regs_set_reg; auto. Qed. +Lemma agree_regs_undef_caller_save_regs: + forall j ls rs, + agree_regs j ls rs -> + agree_regs j (LTL.undef_caller_save_regs ls) (Mach.undef_caller_save_regs rs). +Proof. + intros; red; intros. + unfold LTL.undef_caller_save_regs, Mach.undef_caller_save_regs. + destruct (is_callee_save r); auto. +Qed. + (** Preservation under assignment of stack slot *) Lemma agree_regs_set_slot: @@ -800,41 +802,7 @@ Lemma agree_locs_return: Proof. intros. red in H0. inv H; constructor; auto; intros. - rewrite H0; auto. unfold mreg_within_bounds in H. tauto. -- rewrite H0; auto. -Qed. - -(** Preservation at tailcalls (when [ls0] is changed but not [ls]). *) - -Lemma agree_locs_tailcall: - forall ls ls0 ls0', - agree_locs ls ls0 -> - agree_callee_save ls0 ls0' -> - agree_locs ls ls0'. -Proof. - intros. red in H0. inv H; constructor; auto; intros. -- rewrite <- H0; auto. unfold mreg_within_bounds in H. tauto. -- rewrite <- H0; auto. -Qed. - -(** ** Properties of [agree_callee_save]. *) - -Lemma agree_callee_save_return_regs: - forall ls1 ls2, - agree_callee_save (return_regs ls1 ls2) ls1. -Proof. - intros; red; intros. - unfold return_regs. destruct l; auto. rewrite H; auto. -Qed. - -Lemma agree_callee_save_set_result: - forall sg v ls1 ls2, - agree_callee_save ls1 ls2 -> - agree_callee_save (Locmap.setpair (loc_result sg) v ls1) ls2. -Proof. - intros; red; intros. rewrite Locmap.gpo. apply H; auto. - assert (X: forall r, is_callee_save r = false -> Loc.diff l (R r)). - { intros. destruct l; auto. simpl; congruence. } - generalize (loc_result_caller_save sg). destruct (loc_result sg); simpl; intuition auto. +- rewrite <- agree_incoming0 by auto. apply H0. congruence. Qed. (** ** Properties of destroyed registers. *) @@ -1071,6 +1039,7 @@ Lemma function_prologue_correct: forall j ls ls0 ls1 rs rs1 m1 m1' m2 sp parent ra cs fb k P, agree_regs j ls rs -> agree_callee_save ls ls0 -> + agree_outgoing_arguments (Linear.fn_sig f) ls ls0 -> (forall r, Val.has_type (ls (R r)) (mreg_type r)) -> ls1 = LTL.undef_regs destroyed_at_function_entry (LTL.call_regs ls) -> rs1 = undef_regs destroyed_at_function_entry rs -> @@ -1090,7 +1059,7 @@ Lemma function_prologue_correct: /\ j' sp = Some(sp', fe.(fe_stack_data)) /\ inject_incr j j'. Proof. - intros until P; intros AGREGS AGCS WTREGS LS1 RS1 ALLOC TYPAR TYRA SEP. + intros until P; intros AGREGS AGCS AGARGS WTREGS LS1 RS1 ALLOC TYPAR TYRA SEP. rewrite unfold_transf_function. unfold fn_stacksize, fn_link_ofs, fn_retaddr_ofs. (* Stack layout info *) @@ -1174,7 +1143,7 @@ Local Opaque b fe. split. rewrite LS1. apply agree_locs_undef_locs; [|reflexivity]. constructor; intros. unfold call_regs. apply AGCS. unfold mreg_within_bounds in H; tauto. - unfold call_regs. apply AGCS. auto. + unfold call_regs. apply AGARGS. apply incoming_slot_in_parameters; auto. split. exact SEPFINAL. split. exact SAME. exact INCR. Qed. @@ -1325,7 +1294,7 @@ Proof. apply CS; auto. rewrite NCS by auto. apply AGR. split. red; unfold return_regs; intros. - destruct l; auto. rewrite H; auto. + destruct l. rewrite H; auto. destruct sl; auto; contradiction. assumption. Qed. @@ -1619,6 +1588,7 @@ Variable ls: locset. Variable rs: regset. Hypothesis AGR: agree_regs j ls rs. Hypothesis AGCS: agree_callee_save ls (parent_locset cs). +Hypothesis AGARGS: agree_outgoing_arguments sg ls (parent_locset cs). Variable m': mem. Hypothesis SEP: m' |= stack_contents j cs cs'. @@ -1641,7 +1611,7 @@ Proof. assert (slot_within_bounds (function_bounds f) Outgoing pos ty) by eauto. exploit frame_get_outgoing; eauto. intros (v & A & B). exists v; split. - constructor. exact A. red in AGCS. rewrite AGCS; auto. + constructor. exact A. rewrite AGARGS by auto. exact B. Qed. Lemma transl_external_argument_2: @@ -1816,7 +1786,6 @@ Inductive match_states: Linear.state -> Mach.state -> Prop := (TRANSL: transf_fundef f = OK tf) (FIND: Genv.find_funct_ptr tge fb = Some tf) (AGREGS: agree_regs j ls rs) - (AGLOCS: agree_callee_save ls (parent_locset cs)) (SEP: m' |= stack_contents j cs cs' ** minjection j m ** globalenv_inject ge j), @@ -1826,7 +1795,6 @@ Inductive match_states: Linear.state -> Mach.state -> Prop := forall cs ls m cs' rs m' j sg (STACKS: match_stacks j cs cs' sg) (AGREGS: agree_regs j ls rs) - (AGLOCS: agree_callee_save ls (parent_locset cs)) (SEP: m' |= stack_contents j cs cs' ** minjection j m ** globalenv_inject ge j), @@ -1989,9 +1957,8 @@ Proof. econstructor; eauto with coqlib. apply Val.Vptr_has_type. intros; red. - apply Z.le_trans with (size_arguments (Linear.funsig f')); auto. + apply Z.le_trans with (size_arguments (Linear.funsig f')); auto. apply loc_arguments_bounded; auto. - simpl; red; auto. simpl. rewrite sep_assoc. exact SEP. - (* Ltailcall *) @@ -2091,6 +2058,7 @@ Proof. destruct (transf_function f) as [tfn|] eqn:TRANSL; simpl; try congruence. intros EQ; inversion EQ; clear EQ; subst tf. rewrite sep_comm, sep_assoc in SEP. + exploit wt_callstate_agree; eauto. intros [AGCS AGARGS]. exploit function_prologue_correct; eauto. red; intros; eapply wt_callstate_wt_regs; eauto. eapply match_stacks_type_sp; eauto. @@ -2109,6 +2077,7 @@ Proof. - (* external function *) simpl in TRANSL. inversion TRANSL; subst tf. + exploit wt_callstate_agree; eauto. intros [AGCS AGARGS]. exploit transl_external_arguments; eauto. apply sep_proj1 in SEP; eauto. intros [vl [ARGS VINJ]]. rewrite sep_comm, sep_assoc in SEP. exploit external_call_parallel_rule; eauto. @@ -2118,18 +2087,22 @@ Proof. eapply external_call_symbols_preserved; eauto. apply senv_preserved. eapply match_states_return with (j := j'). eapply match_stacks_change_meminj; eauto. - apply agree_regs_set_pair. apply agree_regs_inject_incr with j; auto. auto. - apply agree_callee_save_set_result; auto. + apply agree_regs_set_pair. apply agree_regs_undef_caller_save_regs. + apply agree_regs_inject_incr with j; auto. + auto. apply stack_contents_change_meminj with j; auto. rewrite sep_comm, sep_assoc; auto. - (* return *) - inv STACKS. simpl in AGLOCS. simpl in SEP. rewrite sep_assoc in SEP. + inv STACKS. exploit wt_returnstate_agree; eauto. intros [AGCS OUTU]. + simpl in AGCS. simpl in SEP. rewrite sep_assoc in SEP. econstructor; split. apply plus_one. apply exec_return. econstructor; eauto. apply agree_locs_return with rs0; auto. apply frame_contents_exten with rs0 (parent_locset s); auto. + intros; apply Val.lessdef_same; apply AGCS; red; congruence. + intros; rewrite (OUTU ty ofs); auto. Qed. Lemma transf_initial_states: @@ -2147,7 +2120,6 @@ Proof. eapply match_states_call with (j := j); eauto. constructor. red; intros. rewrite H3, loc_arguments_main in H. contradiction. red; simpl; auto. - red; simpl; auto. simpl. rewrite sep_pure. split; auto. split;[|split]. eapply Genv.initmem_inject; eauto. simpl. exists (Mem.nextblock m0); split. apply Ple_refl. diff --git a/backend/Tunnelingproof.v b/backend/Tunnelingproof.v index c6644ceb..4f95ac9b 100644 --- a/backend/Tunnelingproof.v +++ b/backend/Tunnelingproof.v @@ -334,6 +334,16 @@ Proof. induction res; intros; simpl; auto using locmap_set_lessdef, Val.loword_lessdef, Val.hiword_lessdef. Qed. +Lemma locmap_undef_caller_save_regs_lessdef: + forall ls1 ls2, + locmap_lessdef ls1 ls2 -> locmap_lessdef (undef_caller_save_regs ls1) (undef_caller_save_regs ls2). +Proof. + intros; red; intros. unfold undef_caller_save_regs. + destruct l. +- destruct (Conventions1.is_callee_save r); auto. +- destruct sl; auto. +Qed. + Lemma find_function_translated: forall ros ls tls fd, locmap_lessdef ls tls -> @@ -363,7 +373,7 @@ Lemma return_regs_lessdef: Proof. intros; red; intros. destruct l; simpl. - destruct (Conventions1.is_callee_save r); auto. -- auto. +- destruct sl; auto. Qed. (** To preserve non-terminating behaviours, we show that the transformed @@ -516,7 +526,7 @@ Proof. left; simpl; econstructor; split. eapply exec_function_external; eauto. eapply external_call_symbols_preserved; eauto. apply senv_preserved. - simpl. econstructor; eauto using locmap_setpair_lessdef. + simpl. econstructor; eauto using locmap_setpair_lessdef, locmap_undef_caller_save_regs_lessdef. - (* return *) inv STK. inv H1. left; econstructor; split. diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml index c4772688..d6bf76f3 100644 --- a/cfrontend/C2C.ml +++ b/cfrontend/C2C.ml @@ -16,7 +16,7 @@ open C open Camlcoq -open Floats +open! Floats open Values open Ctypes open Csyntax @@ -307,18 +307,18 @@ let builtins = (** ** The known attributes *) let attributes = [ - (* type-related *) - ("aligned", Cutil.Attr_type); + (* type-related -- currently none *) (* struct-related *) ("packed", Cutil.Attr_struct); (* function-related *) ("noreturn", Cutil.Attr_function); ("noinline",Cutil.Attr_function); (* name-related *) + ("aligned", Cutil.Attr_name); ("section", Cutil.Attr_name); ("unused", Cutil.Attr_name) ] - + (** ** Functions used to handle string literals *) @@ -546,14 +546,14 @@ let convertFkind k a : coq_type = let checkFunctionType env tres targs = if not !Clflags.option_fstruct_passing then begin if Cutil.is_composite_type env tres then - unsupported "function returning a struct or union (consider adding option -fstruct-passing)"; + unsupported "function returning a struct or union (consider adding option [-fstruct-passing])"; begin match targs with | None -> () | Some l -> List.iter (fun (id, ty) -> if Cutil.is_composite_type env ty then - unsupported "function parameter of struct or union type (consider adding option -fstruct-passing)") + unsupported "function parameter of struct or union type (consider adding option [-fstruct-passing])") l end end @@ -606,13 +606,15 @@ let rec convertTypArgs env tl el = let convertField env f = if f.fld_bitfield <> None then - unsupported "bit field in struct or union (consider adding option -fbitfields)"; + unsupported "bit field in struct or union (consider adding option [-fbitfields])"; (intern_string f.fld_name, convertTyp env f.fld_typ) let convertCompositedef env su id attr members = + if Cutil.find_custom_attributes ["packed";"__packed__"] attr <> [] then + unsupported "packed struct (consider adding option [-fpacked-structs])"; let t = match su with | C.Struct -> - let layout = Cutil.struct_layout env members in + let layout = Cutil.struct_layout env attr members in List.iter (fun (a,b) -> Debug.set_member_offset id a b) layout; TStruct (id,attr) | C.Union -> TUnion (id,attr) in @@ -717,6 +719,7 @@ let ewrap = function let rec convertExpr env e = match e.edesc with + | C.EConst (C.CStr _ | C.CWStr _) | C.EVar _ | C.EUnop((C.Oderef|C.Odot _|C.Oarrow _), _) | C.EBinop(C.Oindex, _, _, _) -> @@ -732,12 +735,6 @@ let rec convertExpr env e = if k = C.FLongDouble && not !Clflags.option_flongdouble then unsupported "'long double' floating-point constant"; convertFloat f k - | C.EConst(C.CStr s) -> - let ty = typeStringLiteral s in - Evalof(Evar(name_for_string_literal s, ty), ty) - | C.EConst(C.CWStr s) -> - let ty = typeWideStringLiteral s in - Evalof(Evar(name_for_wide_string_literal s, ty), ty) | C.EConst(C.CEnum(id, i)) -> Ctyping.econst_int (convertInt32 i) Signed | C.ESizeof ty1 -> @@ -793,6 +790,9 @@ let rec convertExpr env e = if Cutil.is_composite_type env e1.etyp && List.mem AVolatile (Cutil.attributes_of_type env e1.etyp) then warning Diagnostics.Unnamed "assignment to an lvalue of volatile composite type, the 'volatile' qualifier is ignored"; + if Cutil.is_composite_type env e2.etyp + && List.mem AVolatile (Cutil.attributes_of_type env e2.etyp) then + warning Diagnostics.Unnamed "assignment of a value of volatile composite type, the 'volatile' qualifier is ignored"; ewrap (Ctyping.eassign e1' e2') | C.EBinop((C.Oadd_assign|C.Osub_assign|C.Omul_assign|C.Odiv_assign| C.Omod_assign|C.Oand_assign|C.Oor_assign|C.Oxor_assign| @@ -829,10 +829,10 @@ let rec convertExpr env e = | C.ECompound(ty1, ie) -> unsupported "compound literals"; ezero + | C.ECall({edesc = C.EVar {name = "__builtin_debug"}}, args) when List.length args < 2 -> + error "too few arguments to function call, expected at least 2, have 0"; + ezero | C.ECall({edesc = C.EVar {name = "__builtin_debug"}}, args) -> - let len = List.length args in - if len < 2 then - error "too few arguments to function call, expected at least 2, have 0"; let (kind, args1) = match args with | {edesc = C.EConst(CInt(n,_,_))} :: args1 when n <> 0L-> (n, args1) @@ -957,6 +957,12 @@ and convertLvalue env e = let e1' = convertExpr env e1 and e2' = convertExpr env e2 in let e3' = ewrap (Ctyping.ebinop Cop.Oadd e1' e2') in ewrap (Ctyping.ederef e3') + | C.EConst(C.CStr s) -> + let ty = typeStringLiteral s in + Evar(name_for_string_literal s, ty) + | C.EConst(C.CWStr s) -> + let ty = typeWideStringLiteral s in + Evar(name_for_wide_string_literal s, ty) | _ -> error "illegal lvalue"; ezero @@ -1002,7 +1008,7 @@ type switchbody = let rec flattenSwitch = function | {sdesc = C.Sseq(s1, s2)} -> flattenSwitch s1 @ flattenSwitch s2 - | {sdesc = C.Slabeled(C.Scase e, s1)} -> + | {sdesc = C.Slabeled(C.Scase(e, _), s1)} -> Label(Case e) :: flattenSwitch s1 | {sdesc = C.Slabeled(C.Sdefault, s1)} -> Label Default :: flattenSwitch s1 diff --git a/cfrontend/SimplExpr.v b/cfrontend/SimplExpr.v index 45b686f3..7cdff468 100644 --- a/cfrontend/SimplExpr.v +++ b/cfrontend/SimplExpr.v @@ -26,6 +26,7 @@ Require Import Csyntax. Require Import Clight. Local Open Scope string_scope. +Local Open Scope list_scope. (** State and error monad for generating fresh identifiers. *) diff --git a/cfrontend/SimplLocals.v b/cfrontend/SimplLocals.v index b142d3cc..f54aa60d 100644 --- a/cfrontend/SimplLocals.v +++ b/cfrontend/SimplLocals.v @@ -22,6 +22,7 @@ Require Compopts. Open Scope error_monad_scope. Open Scope string_scope. +Open Scope list_scope. Module VSet := FSetAVL.Make(OrderedPositive). diff --git a/cfrontend/SimplLocalsproof.v b/cfrontend/SimplLocalsproof.v index 7af499f4..26d3d347 100644 --- a/cfrontend/SimplLocalsproof.v +++ b/cfrontend/SimplLocalsproof.v @@ -1053,7 +1053,7 @@ Proof. assert (RPSRC: Mem.range_perm m bsrc (Ptrofs.unsigned osrc) (Ptrofs.unsigned osrc + sizeof tge ty) Cur Nonempty). eapply Mem.range_perm_implies. eapply Mem.loadbytes_range_perm; eauto. auto with mem. assert (RPDST: Mem.range_perm m bdst (Ptrofs.unsigned odst) (Ptrofs.unsigned odst + sizeof tge ty) Cur Nonempty). - replace (sizeof tge ty) with (Z.of_nat (length bytes)). + replace (sizeof tge ty) with (Z.of_nat (List.length bytes)). eapply Mem.range_perm_implies. eapply Mem.storebytes_range_perm; eauto. auto with mem. rewrite LEN. apply nat_of_Z_eq. omega. assert (PSRC: Mem.perm m bsrc (Ptrofs.unsigned osrc) Cur Nonempty). @@ -18,15 +18,21 @@ prefix='/usr/local' bindir='$(PREFIX)/bin' libdir='$(PREFIX)/lib/compcert' +coqdevdir='$(PREFIX)/lib/compcert/coq' toolprefix='' target='' has_runtime_lib=true has_standard_headers=true clightgen=false +install_coqdev=false responsefile="gnu" ignore_coq_version=false usage='Usage: ./configure [options] target +For help on options and targets, do: ./configure -help +' + +help='Usage: ./configure [options] target Supported targets: ppc-eabi (PowerPC, EABI with GNU/Unix tools) @@ -76,13 +82,19 @@ Options: -prefix <dir> Install in <dir>/bin and <dir>/lib/compcert -bindir <dir> Install binaries in <dir> -libdir <dir> Install libraries in <dir> + -coqdevdir <dir> Install Coq development (.vo files) in <dir> -toolprefix <pref> Prefix names of tools ("gcc", etc) with <pref> -no-runtime-lib Do not compile nor install the runtime support library -no-standard-headers Do not install nor use the standard .h headers - -clightgen Also compile the clightgen tool + -clightgen Also compile and install the clightgen tool + -install-coqdev Also install the Coq development (implied by -clightgen) -ignore-coq-version Accept to use experimental or unsupported versions of Coq ' +# +# Remove Leftover Makefile.config (if any) (GPR#244) +# +rm -f Makefile.config # # Parse Command-Line Arguments @@ -97,6 +109,8 @@ while : ; do bindir="$2"; shift;; -libdir|--libdir) libdir="$2"; shift;; + -coqdevdir|--coqdevdir) + coqdevdir="$2"; install_coqdev=true; shift;; -toolprefix|--toolprefix) toolprefix="$2"; shift;; -no-runtime-lib) @@ -104,9 +118,18 @@ while : ; do -no-standard-headers) has_standard_headers=false;; -clightgen) - clightgen=true;; + clightgen=true + install_coqdev=true;; -ignore-coq-version|--ignore-coq-version) ignore_coq_version=true;; + -install-coqdev|--install-coqdev|-install-coq-dev|--install-coq-dev) + install_coqdev=true;; + -help|--help) + echo "$help"; exit 0;; + -*) + echo "Error: unknown option '$1'." 1>&2 + echo "$usage" 1>&2 + exit 2;; *) if test -n "$target"; then echo "$usage" 1>&2; exit 2; fi target="$1";; @@ -505,19 +528,19 @@ missingtools=false echo "Testing Coq... " | tr -d '\n' coq_ver=$(${COQBIN}coqc -v 2>/dev/null | sed -n -e 's/The Coq Proof Assistant, version \([^ ]*\).*$/\1/p') case "$coq_ver" in - 8.6.1|8.7.0|8.7.1|8.7.2) + 8.6.1|8.7.0|8.7.1|8.7.2|8.8.0|8.8.1|8.8.2) echo "version $coq_ver -- good!";; ?*) echo "version $coq_ver -- UNSUPPORTED" if $ignore_coq_version; then echo "Warning: this version of Coq is unsupported, proceed at your own risks." else - echo "Error: CompCert requires Coq version 8.6.1 or 8.7.0 or 8.7.1 or 8.7.2." + echo "Error: CompCert requires one of the following Coq versions: 8.8.2, 8.8.1, 8.8.0, 8.7.2, 8.7.1, 8.7.0, 8.6.1" missingtools=true fi;; "") echo "NOT FOUND" - echo "Error: make sure Coq version 8.7.2 is installed." + echo "Error: make sure Coq version 8.8.1 is installed." missingtools=true;; esac @@ -556,6 +579,8 @@ else fi MENHIR_REQUIRED=20161201 +MENHIR_NEW_API=20180530 +menhir_flags='' echo "Testing Menhir... " | tr -d '\n' menhir_ver=`menhir --version 2>/dev/null | sed -n -e 's/^.*version \([0-9]*\).*$/\1/p'` case "$menhir_ver" in @@ -563,11 +588,14 @@ case "$menhir_ver" in if test "$menhir_ver" -ge $MENHIR_REQUIRED; then echo "version $menhir_ver -- good!" menhir_includes="-I `menhir --suggest-menhirLib`" - else + if test "$menhir_ver" -ge $MENHIR_NEW_API; then + menhir_flags="--coq-lib-path compcert.cparser.MenhirLib" + fi + else echo "version $menhir_ver -- UNSUPPORTED" echo "Error: CompCert requires Menhir version $MENHIR_REQUIRED or later." missingtools=true - fi;; + fi;; *) echo "NOT FOUND" echo "Error: make sure Menhir version $MENHIR_REQUIRED or later is installed." @@ -648,8 +676,10 @@ BINDIR=$bindir LIBDIR=$libdir MANDIR=$sharedir/man SHAREDIR=$sharedir +COQDEVDIR=$coqdevdir OCAML_OPT_COMP=$ocaml_opt_comp MENHIR_INCLUDES=$menhir_includes +MENHIR_FLAGS=$menhir_flags COMPFLAGS=-bin-annot EOF @@ -671,6 +701,7 @@ CPREPRO_OPTIONS=$cprepro_options ENDIANNESS=$endianness HAS_RUNTIME_LIB=$has_runtime_lib HAS_STANDARD_HEADERS=$has_standard_headers +INSTALL_COQDEV=$install_coqdev LIBMATH=$libmath MODEL=$model SYSTEM=$system @@ -786,6 +817,7 @@ else bindirexp=`echo "$bindir" | sed -e "s|\\\$(PREFIX)|$prefix|"` libdirexp=`echo "$libdir" | sed -e "s|\\\$(PREFIX)|$prefix|"` +coqdevdirexp=`echo "$coqdevdir" | sed -e "s|\\\$(PREFIX)|$prefix|"` cat <<EOF @@ -803,12 +835,23 @@ CompCert configuration: Linker........................ $clinker Linker needs '-no-pie'........ $clinker_needs_no_pie Math library.................. $libmath + Build command to use.......... $make Binaries installed in......... $bindirexp Runtime library provided...... $has_runtime_lib Library files installed in.... $libdirexp Standard headers provided..... $has_standard_headers Standard headers installed in. $libdirexp/include - Build command to use.......... $make +EOF +if $install_coqdev; then +cat <<EOF + Coq development installed in.. $coqdevdirexp EOF +else +cat <<EOF + Coq development will not be installed +EOF +fi + fi + diff --git a/cparser/Bitfields.ml b/cparser/Bitfields.ml index baf2b0ec..696a9a8d 100644 --- a/cparser/Bitfields.ml +++ b/cparser/Bitfields.ml @@ -40,7 +40,11 @@ type bitfield_info = 0 < pos + sz <= bitsizeof(int) *) -(* Mapping (struct identifier, bitfield name) -> bitfield info *) +let carrier_field bf = + { fld_name = bf.bf_carrier; fld_typ = bf.bf_carrier_typ; + fld_bitfield = None; fld_anonymous = false } + +(* Mapping (struct/union identifier, bitfield name) -> bitfield info *) let bitfield_table = (Hashtbl.create 57: (ident * string, bitfield_info) Hashtbl.t) @@ -49,6 +53,13 @@ let is_bitfield structid fieldname = try Some (Hashtbl.find bitfield_table (structid, fieldname)) with Not_found -> None +(* Mapping struct/union identifier -> list of members after transformation, + including the carrier fields, but without the bit fields. + structs and unions containing no bit fields are not put in this table. *) + +let composite_transformed_members = + (Hashtbl.create 57: (ident, C.field list) Hashtbl.t) + (* Signedness issues *) let unsigned_ikind_for_carrier nbits = @@ -179,9 +190,16 @@ let rec transf_union_members env id count = function :: transf_union_members env id (count + 1) ms) let transf_composite env su id attr ml = - match su with - | Struct -> (attr, transf_struct_members env id 1 ml) - | Union -> (attr, transf_union_members env id 1 ml) + if List.for_all (fun f -> f.fld_bitfield = None) ml then + (attr, ml) + else begin + let ml' = + match su with + | Struct -> transf_struct_members env id 1 ml + | Union -> transf_union_members env id 1 ml in + Hashtbl.add composite_transformed_members id ml'; + (attr, ml') + end (* Bitfield manipulation expressions *) @@ -336,12 +354,25 @@ let rec transf_struct_init id fld_init_list = | Some bf -> let (el, rem') = pack_bitfield_init id bf.bf_carrier fld_init_list in - ({fld_name = bf.bf_carrier; fld_typ = bf.bf_carrier_typ; - fld_bitfield = None; fld_anonymous = false}, + (carrier_field bf, Init_single {edesc = ECast(bf.bf_carrier_typ, or_expr_list el); etyp = bf.bf_carrier_typ}) :: transf_struct_init id rem' +(* Add default initialization for carrier fields that are not listed in the output of + [transf_struct_init]. This happens with carrier fields that contain no named + bitfields, only anonymous bitfields. *) + +let rec completed_struct_init env actual expected = + match actual, expected with + | [], [] -> [] + | (f_a, i) :: actual', f_e :: expected' when f_a.fld_name = f_e.fld_name -> + (f_a, i) :: completed_struct_init env actual' expected' + | _, f_e :: expected' -> + (f_e, default_init env f_e.fld_typ) :: completed_struct_init env actual expected' + | _, [] -> + assert false + (* Check whether a field access (e.f or e->f) is a bitfield access. If so, return carrier expression (e and *e, respectively) and bitfield_info *) @@ -503,8 +534,19 @@ and transf_init env i = | Init_struct(id, fld_init_list) -> let fld_init_list' = List.map (fun (f, i) -> (f, transf_init env i)) fld_init_list in - Init_struct(id, transf_struct_init id fld_init_list') - | Init_union(id, fld, i) -> Init_union(id, fld, transf_init env i) + begin match Hashtbl.find composite_transformed_members id with + | exception Not_found -> + Init_struct(id, fld_init_list') + | ml -> + Init_struct(id, completed_struct_init env (transf_struct_init id fld_init_list') ml) + end + | Init_union(id, fld, i) -> + let i' = transf_init env i in + match is_bitfield id fld.fld_name with + | None -> + Init_union(id, fld, i') + | Some bf -> + Init_union(id, carrier_field bf, Init_single (bitfield_initializer bf i')) (* Declarations *) @@ -528,6 +570,8 @@ let transf_fundef env f = (* Programs *) let program p = + Hashtbl.clear bitfield_table; + Hashtbl.clear composite_transformed_members; Transform.program ~composite:transf_composite ~decl: transf_decl diff --git a/cparser/C.mli b/cparser/C.mli index cacdbe7c..cc8d4065 100644 --- a/cparser/C.mli +++ b/cparser/C.mli @@ -85,9 +85,10 @@ type attributes = attribute list (** Storage classes *) type storage = - | Storage_default + | Storage_default (* used for toplevel names without explicit storage *) | Storage_extern | Storage_static + | Storage_auto (* used for block-scoped names without explicit storage *) | Storage_register (** Unary operators *) @@ -219,7 +220,7 @@ and stmt_desc = and slabel = | Slabel of string - | Scase of exp + | Scase of exp * int64 | Sdefault (** Declarations *) diff --git a/cparser/Cabs.v b/cparser/Cabs.v index b3e4ffda..5865ab69 100644 --- a/cparser/Cabs.v +++ b/cparser/Cabs.v @@ -140,8 +140,7 @@ with expression := | MEMBEROFPTR : expression -> string -> expression (* Non-standard *) - | EXPR_ALIGNOF : expression -> expression - | TYPE_ALIGNOF : (list spec_elem * decl_type) -> expression + | ALIGNOF : (list spec_elem * decl_type) -> expression | BUILTIN_OFFSETOF : (list spec_elem * decl_type) -> list initwhat -> expression with constant := diff --git a/cparser/Ceval.ml b/cparser/Ceval.ml index c3d7eeeb..58dea5f4 100644 --- a/cparser/Ceval.ml +++ b/cparser/Ceval.ml @@ -13,7 +13,7 @@ (* *) (* *********************************************************************) -(* Evaluation of compile-time constants *) +(* Evaluation and recognition of compile-time constants *) open C open Cutil @@ -103,7 +103,7 @@ let cast env ty_to v = else raise Notconst | TPtr(ty, _), I n -> I (normalize_int n (ptr_t_ikind ())) - | TPtr(ty, _), (S _ | WS _) -> + | (TArray(ty, _, _) | TPtr (ty, _)), (S _ | WS _) -> v | TEnum(_, _), I n -> I (normalize_int n enum_ikind) @@ -217,8 +217,6 @@ let binop env op tyop tyres ty1 v1 ty2 v2 = comparison env (<=) None tyop v1 v2 | Oge -> comparison env (>=) None tyop v1 v2 - | Ocomma -> - v2 | Ologand -> if boolean_value v1 then if boolean_value v2 then I 1L else I 0L @@ -274,8 +272,102 @@ let constant_expr env ty e = match unroll env ty, cast env ty (expr env e) with | TInt(ik, _), I n -> Some(CInt(n, ik, "")) | TPtr(_, _), I n -> Some(CInt(n, IInt, "")) - | TPtr(_, _), S s -> Some(CStr s) - | TPtr(_, _), WS s -> Some(CWStr s) + | (TArray(_, _, _) | TPtr(_, _)), S s -> Some(CStr s) + | (TArray(_, _, _) | TPtr(_, _)), WS s -> Some(CWStr s) | TEnum(_, _), I n -> Some(CInt(n, enum_ikind, "")) | _ -> None with Notconst -> None + +(* Recognition of constant initializers and constant expressions. + This is just a check: no evaluation of the constants is done. + Reference: ISO C99 section 6.6 *) + +let rec is_constant_init env = function + | Init_single e -> is_constant_expr env e + | Init_array il -> List.for_all (is_constant_init env) il + | Init_struct(id, fil) -> + List.for_all (fun (f, i) -> is_constant_init env i) fil + | Init_union(id, f, i) -> is_constant_init env i + +and is_constant_expr env e = + match e.edesc with + | EConst cst -> true + | ESizeof ty -> true + | EAlignof ty -> true + | EVar id -> + begin match Env.find_ident env id with + | Env.II_ident _ -> is_constant_rval_of_lval env e + | Env.II_enum _ -> true (* an enum value is a constant *) + | exception Env.Error _ -> false (* should not happen *) + end + | EUnop(op, e1) -> + begin match op with + | Ominus | Oplus | Olognot | Onot -> is_constant_expr env e1 + | Oderef | Odot _ | Oarrow _ -> is_constant_rval_of_lval env e + | Oaddrof -> is_constant_lval env e1 + | Opreincr | Opredecr | Opostincr | Opostdecr -> false + (* Constant expressions shall not contain increment or decrement *) + end + | EBinop(op, e1, e2, _) -> + begin match op with + | Oadd | Osub | Omul | Odiv | Omod + | Oand | Oor | Oxor | Oshl | Oshr + | Oeq | One | Olt | Ogt | Ole | Oge + | Ologand | Ologor -> + is_constant_expr env e1 && is_constant_expr env e2 + | Oindex -> + is_constant_rval_of_lval env e + | Oassign + | Oadd_assign | Osub_assign | Omul_assign | Odiv_assign | Omod_assign + | Oand_assign | Oor_assign | Oxor_assign | Oshl_assign | Oshr_assign -> + false + (* constant expressions shall not contain assignments *) + | Ocomma -> + false + (* some C compilers accept "e1, e2" as a constant expression. + But this is not standard ISO C. *) + end + | EConditional(e1, e2, e3) -> + is_constant_expr env e1 && is_constant_expr env e2 + && is_constant_expr env e3 + | ECast(ty, e1) -> + is_constant_expr env e1 + | ECompound(ty, i) -> + is_constant_init env i + | ECall(fn, args) -> + false + (* constant expressions shall not contain function calls *) + +and is_constant_rval_of_lval env e = + (* The value of an object shall not be accessed by use of the . -> * [] + operators. This is the case if the object has array or function type. + A scalar type or a composite type implies a memory access. *) + match unroll env e.etyp with + | TArray _ | TFun _ -> is_constant_lval env e + | _ -> false + +and is_constant_lval env e = + match e.edesc with + | EConst (CStr _) + | EConst (CWStr _) -> true + | EVar id -> + begin match Env.find_ident env id with + | Env.II_ident(sto, _) -> + begin match sto with + | Storage_default | Storage_extern | Storage_static -> true + | Storage_auto | Storage_register -> false + end + | Env.II_enum _ -> false (* should not happen *) + | exception Env.Error _ -> false (* should not happen *) + end + | EUnop(Oderef, e1) -> is_constant_expr env e1 + | EUnop(Odot f, e1) -> is_constant_lval env e1 + | EUnop(Oarrow f, e1) -> is_constant_expr env e1 + | EBinop(Oindex, e1, e2, _) -> + is_constant_expr env e1 && is_constant_expr env e2 + | ECompound(ty, i) -> + is_constant_init env i + | _ -> false + + + diff --git a/cparser/Ceval.mli b/cparser/Ceval.mli index 7425a332..32a0ed91 100644 --- a/cparser/Ceval.mli +++ b/cparser/Ceval.mli @@ -16,3 +16,5 @@ val integer_expr : Env.t -> C.exp -> int64 option val constant_expr : Env.t -> C.typ -> C.exp -> C.constant option val normalize_int : int64 -> C.ikind -> int64 +val is_constant_init: Env.t -> C.init -> bool +val is_constant_expr: Env.t -> C.exp -> bool diff --git a/cparser/Cflow.ml b/cparser/Cflow.ml index c7236ce8..cc257189 100644 --- a/cparser/Cflow.ml +++ b/cparser/Cflow.ml @@ -135,7 +135,7 @@ let catch_continue (s: flow) : flow = fun i -> let o = s i in { o with onormal = o.onormal || o.ocontinue; ocontinue = false} -(* Convert "continue" into "fallthrough". Typically applied to a loop. *) +(* Convert "break" into "fallthrough". Typically applied to a loop. *) let catch_break (s: flow) : flow = fun i -> let o = s i in diff --git a/cparser/Checks.ml b/cparser/Checks.ml index ee36e226..62d85c1b 100644 --- a/cparser/Checks.ml +++ b/cparser/Checks.ml @@ -106,6 +106,7 @@ let unknown_attrs_program p = let decl env loc d = unknown_attrs_decl env loc d and fundef env loc f = + List.iter (fun (id,typ) -> unknown_attrs_typ env loc typ) f.fd_params; unknown_attrs loc f.fd_attrib; unknown_attrs_stmt env f.fd_body; List.iter (unknown_attrs_decl env loc) f.fd_locals; diff --git a/cparser/Cleanup.ml b/cparser/Cleanup.ml index fe674d9b..63ac8ac1 100644 --- a/cparser/Cleanup.ml +++ b/cparser/Cleanup.ml @@ -93,7 +93,7 @@ let rec add_stmt s = | Scontinue -> () | Sswitch(e, s1) -> add_exp e; add_stmt s1 | Slabeled(lbl, s) -> - begin match lbl with Scase e -> add_exp e | _ -> () end; + begin match lbl with Scase(e, _) -> add_exp e | _ -> () end; add_stmt s | Sgoto lbl -> () | Sreturn None -> () @@ -118,7 +118,12 @@ let add_enum e = e (* Saturate the set of referenced identifiers, starting with externally - visible global declarations *) + visible global declarations. + + Externally-visible globals include a minima: + - Definitions of functions, unless "static" or "inline". + - Declaration of variables with default storage. +*) let visible_decl (sto, id, ty, init) = sto = Storage_default && @@ -129,7 +134,7 @@ let visible_fundef f = | Storage_default -> not f.fd_inline | Storage_extern -> true | Storage_static -> false - | Storage_register -> assert false + | Storage_auto | Storage_register -> assert false let rec add_init_globdecls accu = function | [] -> accu diff --git a/cparser/Cprint.ml b/cparser/Cprint.ml index d623ab96..9aeec421 100644 --- a/cparser/Cprint.ml +++ b/cparser/Cprint.ml @@ -361,6 +361,7 @@ let storage pp = function | Storage_default -> () | Storage_extern -> fprintf pp "extern " | Storage_static -> fprintf pp "static " + | Storage_auto -> () (* used only in blocks, where it can be omitted *) | Storage_register -> fprintf pp "register " let full_decl pp (sto, id, ty, int) = @@ -477,7 +478,7 @@ let rec stmt pp s = and slabel pp = function | Slabel s -> fprintf pp "%s" s - | Scase e -> + | Scase(e, _) -> fprintf pp "case %a" exp (0, e) | Sdefault -> fprintf pp "default" diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml index f3cd5d14..ea9713d5 100644 --- a/cparser/Cutil.ml +++ b/cparser/Cutil.ml @@ -110,7 +110,8 @@ let declare_attributes l = List.iter (fun (n,c) -> declare_attribute n c) l let class_of_attribute = function - | AConst | AVolatile | ARestrict | AAlignas _ -> Attr_type + | AConst | AVolatile | ARestrict -> Attr_type + | AAlignas _ -> Attr_name | Attr(name, args) -> try Hashtbl.find attr_class (normalize_attrname name) with Not_found -> Attr_unknown @@ -124,9 +125,8 @@ let attr_is_standard = function (* Is an attribute applicable to a whole array (true) or only to array elements (false)? *) -let attr_array_applicable = function - | AConst | AVolatile | ARestrict | AAlignas _ -> false - | Attr _ -> true +let attr_array_applicable a = + class_of_attribute a <> Attr_type (* Is an attribute of a composite type applicable to members of this type when they are accessed? *) @@ -175,11 +175,20 @@ let rec attributes_of_type env t = | TFun(ty, params, vararg, a) -> a | TNamed(s, a) -> attributes_of_type env (unroll env t) | TStruct(s, a) -> - let ci = Env.find_struct env s in add_attributes ci.ci_attr a + begin match Env.find_struct env s with + | ci -> add_attributes ci.ci_attr a + | exception Env.Error(Env.Unbound_tag _) -> a + end | TUnion(s, a) -> - let ci = Env.find_union env s in add_attributes ci.ci_attr a + begin match Env.find_union env s with + | ci -> add_attributes ci.ci_attr a + | exception Env.Error(Env.Unbound_tag _) -> a + end | TEnum(s, a) -> - let ei = Env.find_enum env s in add_attributes ei.ei_attr a + begin match Env.find_enum env s with + | ei -> add_attributes ei.ei_attr a + | exception Env.Error(Env.Unbound_tag _) -> a + end (* Changing the attributes of a type (at top-level) *) (* Same hack as above for array types. *) @@ -249,15 +258,33 @@ let strip_last_attribute typ = | TEnum (n,at) -> let l,r = hd_opt at in l,TEnum(n,r) +(* Check whether the attributes contain _Alignas attribute *) +let has_std_alignas env typ = + List.exists (function | AAlignas _ -> true | _ -> false) (attributes_of_type env typ) + (* Extracting alignment value from a set of attributes. Return 0 if none. *) let alignas_attribute al = let rec alignas_attr accu = function | [] -> accu | AAlignas n :: al -> alignas_attr (max n accu) al + | Attr(("aligned" | "__aligned__"), [AInt n]) :: al -> + alignas_attr (max (Int64.to_int n) accu) al | a :: al -> alignas_attr accu al in alignas_attr 0 al +(* Extracting struct packing parameters from a set of attributes. + Assume the parameters were checked earlier, e.g. alignments are + either 0 or powers of two. *) + +let packing_parameters al = + match find_custom_attributes ["packed";"__packed__"] al with + | [[]] -> (1, 0, false) + | [[AInt n]] -> (Int64.to_int n, 0, false) + | [[AInt n; AInt p]] -> (Int64.to_int n, Int64.to_int p, false) + | [[AInt n; AInt p; AInt q]] -> (Int64.to_int n, Int64.to_int p, q = 1L) + | _ -> (0, 0, false) + (* Type compatibility *) exception Incompat @@ -452,7 +479,10 @@ let rec alignof env t = let ci = Env.find_union env name in ci.ci_alignof | TEnum(_, _) -> Some(alignof_ikind enum_ikind) -(* Compute the natural alignment of a struct or union. *) +(* Compute the natural alignment of a struct or union. + Not done here but in composite_info_decl: taking into account + the packing parameters (max-field-alignment, min-struct-alignment) + and the alignas attributes. *) let alignof_struct_union env members = let rec align_rec al = function @@ -521,7 +551,7 @@ let rec sizeof env t = (* Compute the size of a union. It is the size is the max of the sizes of fields. - Not done here but in composite_info_decl: rounding size to alignment. *) + Not done here but in composite_info_def: rounding size to alignment. *) let sizeof_union env members = let rec sizeof_rec sz = function @@ -534,69 +564,66 @@ let sizeof_union env members = end in sizeof_rec 0 members -(* Compute the size of a struct. +(* Compute the size of a struct and the byte offset of the members. We lay out fields consecutively, inserting padding to preserve their alignment. - Not done here but in composite_info_decl: rounding size to alignment. *) -let sizeof_struct env members = - let rec sizeof_rec ofs = function + The [ma] parameter is the maximal alignment for each member. + It is used for packed structs. If [ma = 0], it is ignored. + Bitfields are taken into account for the size and offset computations + but not given an offset. + Not done here but in composite_info_def: rounding size to alignment. *) +let sizeof_layout_struct env members ma = + let align_offset ofs a = + align ofs (if ma > 0 && a > ma then ma else a) in + let rec sizeof_rec ofs accu = function | [] -> - Some ofs + Some (ofs, accu) | [ { fld_typ = TArray(_, None, _) } as m ] -> (* C99: ty[] allowed as last field *) begin match alignof env m.fld_typ with - | Some a -> Some (align ofs a) + | Some a -> + let ofs = align_offset ofs a in + Some (ofs, (m.fld_name, ofs) :: accu) | None -> None end | m :: rem as ml -> if m.fld_bitfield = None then begin match alignof env m.fld_typ, sizeof env m.fld_typ with - | Some a, Some s -> sizeof_rec (align ofs a + s) rem + | Some a, Some s -> + let ofs = align_offset ofs a in + sizeof_rec (ofs + s) ((m.fld_name, ofs) :: accu) rem | _, _ -> None end else begin let (s, a, ml') = pack_bitfields ml in - sizeof_rec (align ofs a + s) ml' + sizeof_rec (align_offset ofs a + s) accu ml' end - in sizeof_rec 0 members + in sizeof_rec 0 [] members + +let sizeof_struct env members ma = + match sizeof_layout_struct env members ma with + | None -> None + | Some(sz, offsets) -> Some sz + +(* Compute the offsets of all non-bitfield members of a struct. *) +let struct_layout env attrs members = + let (ma, _, _) = packing_parameters attrs in + match sizeof_layout_struct env members ma with + | Some(sz, offsets) -> offsets + | None -> [] (* Compute the offset of a struct member *) let offsetof env ty field = - let rec sub acc name = function - | [] -> List.rev acc - | m::rem -> if m.fld_name = name then - List.rev acc - else - sub (m::acc) name rem in match unroll env ty with - | TStruct (id,_) -> + | TStruct (id, _) -> let str = Env.find_struct env id in - let pre = sub [] field.fld_name str.ci_members in - begin match sizeof_struct env pre, alignof env field.fld_typ with - | Some s, Some a -> - align s a - | _ -> assert false end - | TUnion _ -> 0 - | _ -> assert false - -(* Simplified version to compute offsets on structs without bitfields *) -let struct_layout env members = - let rec struct_layout_rec mem ofs = function - | [] -> - mem - | [ { fld_typ = TArray(_, None, _) } as m ] -> - (* C99: ty[] allowed as last field *) - begin match alignof env m.fld_typ with - | Some a -> ( m.fld_name,align ofs a)::mem - | None -> [] + let offsets = struct_layout env str.ci_attr str.ci_members in + begin try + List.assoc field.fld_name offsets + with Not_found -> + raise (Env.Error(No_member(id.C.name, "struct", field.fld_name))) end - | m :: rem -> - match alignof env m.fld_typ, sizeof env m.fld_typ with - | Some a, Some s -> - let offset = align ofs a in - struct_layout_rec ((m.fld_name,offset)::mem) (offset + s) rem - | _, _ -> [] - in struct_layout_rec [] 0 members - + | TUnion _ -> 0 + | _ -> assert false (* Determine whether a type is incomplete *) @@ -616,12 +643,35 @@ let composite_info_decl su attr = ci_attr = attr } let composite_info_def env su attr m = + let (max_field_align, min_struct_align, swapped) = packing_parameters attr in + let attr_align = alignas_attribute attr in + let natural_align = alignof_struct_union env m in let al = - let a = alignas_attribute attr in - if a > 0 then Some a else alignof_struct_union env m - and sz = + (* alignas takes precedence over packing *) + if attr_align > 0 then Some attr_align + (* ignore packing on unions for compatibility with earlier versions *) + else if su = Union then natural_align + else begin + match natural_align with + | None -> None + | Some a -> + (* If max_field_align is given, reduce natural alignment a + to be at most max_field_align *) + let a = + if max_field_align > 0 && a > max_field_align + then max_field_align + else a in + (* If min_struct_align is given, increase alignment a + to be at least min_struct_align *) + let a = + if min_struct_align > 0 && a < min_struct_align + then min_struct_align + else a in + Some a + end in + let sz = match su with - | Struct -> sizeof_struct env m + | Struct -> sizeof_struct env m max_field_align | Union -> sizeof_union env m in { ci_kind = su; ci_members = m; @@ -749,6 +799,11 @@ let is_anonymous_composite = function | TUnion (id,_) -> id.C.name = "" | _ -> false +let is_function_pointer_type env t = + match unroll env t with + | TPtr (ty, _) -> is_function_type env ty + | _ -> false + (* Find the info for a field access *) let field_of_dot_access env t m = @@ -780,6 +835,15 @@ let float_rank = function | FDouble -> 2 | FLongDouble -> 3 +(* Test for qualified array types *) + +let rec is_qualified_array = function + | TArray (ty, _, attr) -> + List.exists attr_is_standard attr || is_qualified_array ty + | TPtr (ty, _) -> is_qualified_array ty + | TFun(ty_ret, _, _, _) -> is_qualified_array ty_ret + | _ -> false + (* Array and function types "decay" to pointer types in many cases *) let pointer_decay env t = @@ -857,7 +921,7 @@ let argument_conversion env t = (* Arrays and functions degrade automatically to pointers *) (* Other types are not changed *) match unroll env t with - | TArray(ty, _, _) -> TPtr(ty, []) + | TArray(ty, _, attr) -> TPtr(ty, attr) | TFun _ as ty -> TPtr(ty, []) | _ -> t (* preserve typedefs *) @@ -923,8 +987,12 @@ let ptrdiff_t_ikind () = find_matching_signed_ikind !config.sizeof_ptrdiff_t let type_of_constant = function | CInt(_, ik, _) -> TInt(ik, []) | CFloat(_, fk) -> TFloat(fk, []) - | CStr _ -> TPtr(TInt(IChar, []), []) - | CWStr _ -> TPtr(TInt(wchar_ikind(), []), []) + | CStr s -> + let size = Int64.of_int (String.length s + 1) in + TArray(TInt(IChar,[]), Some size, []) + | CWStr s -> + let size = Int64.of_int (List.length s + 1) in + TArray(TInt(wchar_ikind(), []), Some size, []) | CEnum(_, _) -> TInt(IInt, []) (* Check that a C expression is a lvalue *) @@ -932,6 +1000,8 @@ let type_of_constant = function let rec is_lvalue e = match e.edesc with | EVar id -> true + | EConst (CStr _) + | EConst (CWStr _) -> true | EUnop((Oderef | Oarrow _), _) -> true | EUnop(Odot _, e') -> is_lvalue e' | EBinop(Oindex, _, _, _) -> true @@ -998,6 +1068,17 @@ let is_bitfield env e = fld.fld_bitfield <> None | _ -> false +let contains_flex_array_mem env ty = + match unroll env ty with + | TStruct (id,_) -> + let ci = Env.find_struct env id in + let rec check_mem = function + | [] -> false + | [ { fld_typ = TArray(ty_elt, None, _) } ] -> true + | _::rem -> check_mem rem in + check_mem ci.ci_members + | _ -> false + (* Assignment compatibility check over attributes. Standard attributes ("const", "volatile", "restrict") can safely be added (to the rhs type to get the lhs type) but must not be dropped. diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli index fb875b0d..dc9dc0cc 100644 --- a/cparser/Cutil.mli +++ b/cparser/Cutil.mli @@ -34,8 +34,14 @@ val remove_attributes : attributes -> attributes -> attributes val incl_attributes : attributes -> attributes -> bool (* Check that first set of attributes is a subset of second set. *) val alignas_attribute : attributes -> int - (* Extract the value of the [_Alignas] attributes, if any. + (* Extract the value of the [_Alignas] and [attribute((aligned(N)))] + attributes, if any. Return 0 if none, a (positive) power of two alignment if some. *) +val packing_parameters : attributes -> int * int * bool + (* Extract the value of the [__packed__] attributes, if any. + Return a triple + (maximum field alignment, minimum struct alignment, byte swapping). + Alignments of 0 mean default alignment. *) val find_custom_attributes : string list -> attributes -> attr_arg list list (* Extract arguments of custom [Attr] attributes whose names appear in the given list of names. *) @@ -52,6 +58,8 @@ val erase_attributes_type : Env.t -> typ -> typ (* Erase the attributes of the given type. *) val change_attributes_type : Env.t -> (attributes -> attributes) -> typ -> typ (* Apply the given function to the top-level attributes of the given type *) +val has_std_alignas : Env.t -> typ -> bool + (* Do the attributes of the type contain the C11 _Alignas attribute *) type attribute_class = | Attr_name (* Attribute applies to the names being declared *) @@ -127,7 +135,7 @@ val composite_info_decl: val composite_info_def: Env.t -> struct_or_union -> attributes -> field list -> Env.composite_info val struct_layout: - Env.t -> field list -> (string * int) list + Env.t -> attributes -> field list -> (string * int) list val offsetof: Env.t -> typ -> field -> int (* Compute the offset of a struct member *) @@ -153,8 +161,12 @@ val is_composite_type : Env.t -> typ -> bool (* Is type a struct or union? *) val is_function_type : Env.t -> typ -> bool (* Is type a function type? (not pointer to function) *) +val is_function_pointer_type : Env.t -> typ -> bool + (* Is type a pointer to function type? *) val is_anonymous_composite : typ -> bool - (* Is type an anonymous composite? *) + (* Is type an anonymous composite? *) +val is_qualified_array : typ -> bool + (* Does the type contain a qualified array type (e.g. int[const 5])? *) val pointer_arithmetic_ok : Env.t -> typ -> bool (* Is the type [*ty] appropriate for pointer arithmetic? [ty] must not be void, nor a function type, nor an incomplete type. *) @@ -245,6 +257,8 @@ val is_volatile_variable: Env.t -> exp -> bool (* Test whether the expression is an access to a volatile variable *) val is_bitfield: Env.t -> exp -> bool (* Test whether the expression is a bit-field *) +val contains_flex_array_mem : Env.t -> typ -> bool + (* Is this a struct with a flexible array member *) (* Constructors *) diff --git a/cparser/Diagnostics.ml b/cparser/Diagnostics.ml index f18d1b2d..172affab 100644 --- a/cparser/Diagnostics.ml +++ b/cparser/Diagnostics.ml @@ -92,12 +92,17 @@ type warning_type = | Unused_parameter | Wrong_ais_parameter | Unused_ais_parameter + | Ignored_attributes + | Extern_after_definition + | Static_in_inline + | Flexible_array_extensions + | Tentative_incomplete_static + | Reduced_alignment (* List of active warnings *) let active_warnings: warning_type list ref = ref [ Unnamed; Unknown_attribute; - Celeven_extension; Gnu_empty_struct; Missing_declarations; Constant_conversion; @@ -114,6 +119,9 @@ let active_warnings: warning_type list ref = ref [ Inline_asm_sdump; Wrong_ais_parameter; Unused_ais_parameter; + Ignored_attributes; + Extern_after_definition; + Static_in_inline; ] (* List of errors treated as warning *) @@ -145,6 +153,12 @@ let string_of_warning = function | Unused_parameter -> "unused-parameter" | Wrong_ais_parameter -> "wrong-ais-parameter" | Unused_ais_parameter -> "unused-ais-parameter" + | Ignored_attributes -> "ignored-attributes" + | Extern_after_definition -> "extern-after-definition" + | Static_in_inline -> "static-in-inline" + | Flexible_array_extensions -> "flexible-array-extensions" + | Tentative_incomplete_static -> "tentative-incomplete-static" + | Reduced_alignment -> "reduced-alignment" (* Activate the given warning *) let activate_warning w () = @@ -192,6 +206,12 @@ let wall () = Unused_variable; Unused_parameter; Wrong_ais_parameter; + Ignored_attributes; + Extern_after_definition; + Static_in_inline; + Flexible_array_extensions; + Tentative_incomplete_static; + Reduced_alignment; ] let wnothing () = @@ -223,6 +243,12 @@ let werror () = Unused_variable; Wrong_ais_parameter; Unused_ais_parameter; + Ignored_attributes; + Extern_after_definition; + Static_in_inline; + Flexible_array_extensions; + Tentative_incomplete_static; + Reduced_alignment; ] (* Generate the warning key for the message *) @@ -401,6 +427,12 @@ let warning_options = error_option Unused_parameter @ error_option Wrong_ais_parameter @ error_option Unused_ais_parameter @ + error_option Ignored_attributes @ + error_option Extern_after_definition @ + error_option Static_in_inline @ + error_option Flexible_array_extensions @ + error_option Tentative_incomplete_static @ + error_option Reduced_alignment @ [Exact ("-Wfatal-errors"), Set error_fatal; Exact ("-fdiagnostics-color"), Ignore; (* Either output supports it or no color *) Exact ("-fno-diagnostics-color"), Unset color_diagnostics; diff --git a/cparser/Diagnostics.mli b/cparser/Diagnostics.mli index 75865cb2..ded8019f 100644 --- a/cparser/Diagnostics.mli +++ b/cparser/Diagnostics.mli @@ -49,6 +49,12 @@ type warning_type = | Unused_parameter (** unused function parameter *) | Wrong_ais_parameter (** wrong parameter type for ais replacement *) | Unused_ais_parameter (** unused builtin ais parameter *) + | Ignored_attributes (** attributes declarations after definition *) + | Extern_after_definition (** extern declaration after non-extern definition *) + | Static_in_inline (** static variable in non-static inline function *) + | Flexible_array_extensions (** usange of structs with flexible arrays in structs and arrays *) + | Tentative_incomplete_static (** static tentative definition with incomplete type *) + | Reduced_alignment (** alignment reduction *) val warning : (string * int) -> warning_type -> ('a, Format.formatter, unit, unit, unit, unit) format6 -> 'a (** [warning (f,c) w fmt arg1 ... argN] formats the arguments [arg1] to [argN] as warining according to diff --git a/cparser/Elab.ml b/cparser/Elab.ml index a1f85886..718261b4 100644 --- a/cparser/Elab.ml +++ b/cparser/Elab.ml @@ -69,6 +69,20 @@ let top_declarations = ref ([] : globdecl list) let top_environment = ref Env.empty +(* Set of all globals with a definitions *) + +module StringSet = Set.Make(String) + +let global_defines = ref StringSet.empty + +let add_global_define loc name = + if StringSet.mem name !global_defines then + error loc "redefinition of '%s'" name; + global_defines := StringSet.add name !global_defines + +let is_global_defined name = + StringSet.mem name !global_defines + let emit_elab ?(debuginfo = true) ?(linkage = false) env loc td = let loc = elab_loc loc in let dec ={ gdesc = td; gloc = loc } in @@ -84,7 +98,7 @@ let emit_elab ?(debuginfo = true) ?(linkage = false) env loc td = | _ -> () end -let reset() = top_declarations := []; top_environment := Env.empty +let reset() = top_declarations := []; top_environment := Env.empty; global_defines := StringSet.empty let elaborated_program () = let p = !top_declarations in @@ -101,6 +115,15 @@ let rec mmap f env = function let (tl', env2) = mmap f env1 tl in (hd' :: tl', env2) +let rec mmap2 f env l1 l2 = + match l1,l2 with + | [],[] -> [],env + | a1::l1,a2::l2 -> + let hd,env1 = f env a1 a2 in + let tl,env2 = mmap2 f env1 l1 l2 in + (hd::tl,env2) + | _, _ -> invalid_arg "mmap2" + (* To detect redefinitions within the same scope *) let previous_def fn env arg = @@ -116,6 +139,13 @@ let redef fn env arg = (* Auxiliaries for handling declarations and redeclarations *) +let name_of_storage_class = function + | Storage_default -> "<default>" + | Storage_extern -> "'extern'" + | Storage_static -> "'static'" + | Storage_auto -> "'auto'" + | Storage_register -> "'register'" + let combine_toplevel_definitions loc env s old_sto old_ty sto ty = let new_ty = match combine_types AttrCompat env old_ty ty with @@ -126,26 +156,43 @@ let combine_toplevel_definitions loc env s old_sto old_ty sto ty = "redefinition of '%s' with a different type: %a vs %a" s (print_typ env) old_ty (print_typ env) ty; ty in + if is_global_defined s then begin + let old_attrs = attributes_of_type env old_ty + and new_attrs = attributes_of_type env ty in + if not (Cutil.incl_attributes new_attrs old_attrs) then + warning loc Ignored_attributes "attribute declaration must precede definition" + end; let new_sto = (* The only case not allowed is removing static *) match old_sto,sto with | Storage_static,Storage_static | Storage_extern,Storage_extern - | Storage_register,Storage_register | Storage_default,Storage_default -> sto | _,Storage_static -> error loc "static declaration of '%s' follows non-static declaration" s; sto | Storage_static,_ -> Storage_static (* Static stays static *) | Storage_extern,_ -> sto - | Storage_default,Storage_extern -> Storage_extern + | Storage_default,Storage_extern -> + if is_global_defined s && is_function_type env ty then + warning loc Extern_after_definition "this extern declaration follows a non-extern definition and is ignored"; + Storage_extern | _,Storage_extern -> old_sto + (* "auto" and "register" don't appear in toplevel definitions. + Normally this was checked earlier. Generate error message + instead of "assert false", just in case. *) + | _,Storage_auto + | Storage_auto,_ | _,Storage_register - | Storage_register,_ -> Storage_register + | Storage_register,_ -> + error loc "unexpected %s declaration of '%s'" + (name_of_storage_class sto) s; + sto in (new_sto, new_ty) -let enter_or_refine_ident local loc env s sto ty = +let enter_or_refine_ident_base local loc env new_id sto ty = + let s = new_id.C.name in (* Check for illegal redefinitions: - a name that was previously a typedef - a variable that was already declared in the same local scope @@ -155,41 +202,67 @@ let enter_or_refine_ident local loc env s sto ty = if redef Env.lookup_typedef env s then error loc "redefinition of '%s' as different kind of symbol" s; begin match previous_def Env.lookup_ident env s with - | Some(id, Env.II_ident(old_sto, old_ty)) - when local && Env.in_current_scope env id + | Some(old_id, Env.II_ident(old_sto, old_ty)) + when local && Env.in_current_scope env old_id && not (sto = Storage_extern && old_sto = Storage_extern) -> error loc "redefinition of '%s'" s - | Some(id, Env.II_enum _) when Env.in_current_scope env id -> + | Some(old_id, Env.II_enum _) when Env.in_current_scope env old_id -> error loc "redefinition of '%s' as different kind of symbol" s; | _ -> () end; - (* For a block-scoped, non-"extern" variable, a new declaration - is entered, and it has no linkage. *) - if local && sto <> Storage_extern then begin - let (id, env') = Env.enter_ident env s sto ty in - (id, sto, env', ty, false) + (* For a block-scoped, "static" or "auto" or "register" variable, + a new declaration is entered, and it has no linkage. *) + if local + && (sto = Storage_auto || sto = Storage_register || sto = Storage_static) + then begin + (new_id, sto, Env.add_ident env new_id sto ty, ty, false) end else begin (* For a file-scoped or "extern" variable, we need to check against prior declarations of this variable with internal or external linkage. The variable has linkage. *) match previous_def Env.lookup_ident !top_environment s with - | Some(id, Env.II_ident(old_sto, old_ty)) -> + | Some(old_id, Env.II_ident(old_sto, old_ty)) -> let (new_sto, new_ty) = combine_toplevel_definitions loc env s old_sto old_ty sto ty in - (id, new_sto, Env.add_ident env id new_sto new_ty, new_ty, true) + (old_id, new_sto, Env.add_ident env old_id new_sto new_ty, new_ty, true) | _ -> - let (id, env') = Env.enter_ident env s sto ty in - (id, sto, env', ty, true) + (new_id, sto, Env.add_ident env new_id sto ty, ty, true) end +(* We use two variants of [enter_or_refine]: + + - [enter_or_refine_ident] is to be used for all declarations, + block-scoped ([local = true]) or top-level ([local = false]). + The name of the declared thing is given as a string [s]. If a + previous declaration with this name exists in the current scope, + its unique identifier is returned. Otherwise a fresh identifier + named [s] is created in the current scope of [env] and returned. + + - [enter_or_refine_function] is to be used for function definitions. + Such definitions are always global, hence the [local] parameter + defaults to [false] and is omitted. The function name is given + as an identifier, created in advance by the caller. This + identifier is used if no previous declaration exists for the + function. Otherwise, the identifier of the previous declaration is + used. By creating the identifier in advance, [elab_fundef] makes + sure that it is properly scoped to file scope and not to the local + scope of function parameters. +*) + +let enter_or_refine_ident local loc env s sto ty = + enter_or_refine_ident_base local loc env (Env.fresh_ident s) sto ty + +let enter_or_refine_function loc env id sto ty = + enter_or_refine_ident_base false loc env id sto ty + (* Forward declarations *) let elab_expr_f : (cabsloc -> Env.t -> Cabs.expression -> C.exp * Env.t) ref = ref (fun _ _ _ -> assert false) -let elab_funbody_f : (C.typ -> bool -> Env.t -> statement -> C.stmt) ref - = ref (fun _ _ _ _ -> assert false) +let elab_funbody_f : (C.typ -> bool -> bool -> Env.t -> statement -> C.stmt) ref + = ref (fun _ _ _ _ _ -> assert false) (** * Elaboration of constants - C99 section 6.4.4 *) @@ -422,35 +495,53 @@ let elab_gcc_attr loc env = function let is_power_of_two n = n > 0L && Int64.logand n (Int64.pred n) = 0L -let extract_alignas loc a = +(* Check alignment parameter *) +let check_alignment loc n = + if not (is_power_of_two n || n = 0L) then begin + error loc "requested alignment %Ld is not a power of 2" n; false + end else + if n <> Int64.of_int (Int64.to_int n) then begin + error loc "requested alignment %Ld is too large" n; false + end else + true + +(* Process GCC attributes that have special significance. Currently we + have two: "aligned" and "packed". *) +let enter_gcc_attr loc a = match a with | Attr(("aligned"|"__aligned__"), args) -> begin match args with - | [AInt n] when is_power_of_two n -> AAlignas (Int64.to_int n) - | [AInt n] -> error loc "requested alignment is not a power of 2"; a - | [_] -> error loc "requested alignment is not an integer constant"; a - | [] -> a (* Use the default alignment as the gcc does *) - | _ -> error loc "'aligned' attribute takes no more than 1 argument"; a + | [AInt n] -> if check_alignment loc n then [a] else [] + | [_] -> error loc "requested alignment is not an integer constant"; [] + | [] -> [] (* Use default alignment, like gcc does *) + | _ -> error loc "'aligned' attribute takes no more than 1 argument"; [] + end + | Attr(("packed"|"__packed__"), args) -> + begin match args with + | [] -> [a] + | [AInt n] -> if check_alignment loc n then [a] else [] + | [AInt n; AInt p] -> + if check_alignment loc n && check_alignment loc p then [a] else [] + | [AInt n; AInt p; AInt q] when q = 0L || q = 1L -> + if check_alignment loc n && check_alignment loc p then [a] else [] + | _ -> error loc "ill-formed 'packed' attribute"; [] end - | _ -> a + | _ -> [a] let elab_attribute env = function | GCC_ATTR (l, loc) -> List.fold_left add_attributes [] - (List.map (fun attr -> [attr]) - (List.map (extract_alignas loc) - (List.flatten - (List.map (elab_gcc_attr loc env) l)))) + (List.map (enter_gcc_attr loc) + (List.flatten + (List.map (elab_gcc_attr loc env) l))) | PACKED_ATTR (args, loc) -> - [Attr("__packed__", List.map (elab_attr_arg loc env) args)] + enter_gcc_attr loc + (Attr("__packed__", List.map (elab_attr_arg loc env) args)) | ALIGNAS_ATTR ([a], loc) -> + warning loc Celeven_extension "'_Alignas' is a C11 extension"; begin match elab_attr_arg loc env a with | AInt n -> - if is_power_of_two n then - [AAlignas (Int64.to_int n)] - else begin - error loc "requested alignment is not a power of 2"; [] - end + if check_alignment loc n then [AAlignas (Int64.to_int n)] else [] | _ -> error loc "requested alignment is not an integer constant"; [] | exception Wrong_attr_arg -> error loc "bad _Alignas value"; [] end @@ -460,6 +551,22 @@ let elab_attribute env = function let elab_attributes env al = List.fold_left add_attributes [] (List.map (elab_attribute env) al) +(* Warning for alignment requests that reduce the alignment below the + natural alignment. *) + +let warn_if_reduced_alignment loc ~actual ~natural = + match actual, natural with + | Some act, Some nat when act < nat -> + warning loc Reduced_alignment + "requested alignment (%d) is less than natural alignment (%d)" + act nat + | _, _ -> () + +let check_reduced_alignment loc env typ = + warn_if_reduced_alignment loc + ~actual: (wrap alignof loc env typ) + ~natural: (wrap alignof loc env (erase_attributes_type env typ)) + (* Auxiliary for typespec elaboration *) let typespec_rank = function (* Don't change this *) @@ -491,14 +598,15 @@ let get_nontype_attrs env ty = let nta = List.filter to_be_removed (attributes_of_type env ty) in (remove_attributes_type env nta ty, nta) -(* Elaboration of a type specifier. Returns 5-tuple: - (storage class, "inline" flag, "typedef" flag, elaborated type, new env) +(* Elaboration of a type specifier. Returns 6-tuple: + (storage class, "inline" flag, "noreturn" flag, "typedef" flag, + elaborated type, new env) Optional argument "only" is true if this is a standalone struct or union declaration, without variable names. C99 section 6.7.2. *) -let rec elab_specifier keep_ty ?(only = false) loc env specifier = +let rec elab_specifier ?(only = false) loc env specifier = (* We first divide the parts of the specifier as follows: - a storage class - a set of attributes (const, volatile, restrict) @@ -506,18 +614,20 @@ let rec elab_specifier keep_ty ?(only = false) loc env specifier = let sto = ref Storage_default and inline = ref false and noreturn = ref false + and restrict = ref false and attr = ref [] and tyspecs = ref [] and typedef = ref false in let do_specifier = function | SpecCV cv -> + restrict := cv = CV_RESTRICT; attr := add_attributes (elab_cvspec env cv) !attr | SpecStorage st -> if !sto <> Storage_default && st <> TYPEDEF then - error loc "multiple storage-classes in declaration specifier"; + error loc "multiple storage classes in declaration specifier"; begin match st with - | AUTO -> () + | AUTO -> sto := Storage_auto | STATIC -> sto := Storage_static | EXTERN -> sto := Storage_extern | REGISTER -> sto := Storage_register @@ -530,9 +640,18 @@ let rec elab_specifier keep_ty ?(only = false) loc env specifier = | SpecFunction NORETURN -> noreturn := true | SpecType tys -> tyspecs := tys :: !tyspecs in + let restrict_check ty = + if !restrict then + if not (is_pointer_type env ty) then + error loc "restrict requires a pointer type (%a is invalid)" (print_typ env) ty + else if is_function_pointer_type env ty then + error loc "pointer to function type %a may not be 'restrict' qualified" (print_typ env) ty in + List.iter do_specifier specifier; - let simple ty = (!sto, !inline, !noreturn ,!typedef, add_attributes_type !attr ty, env) in + let simple ty = + restrict_check ty; + (!sto, !inline, !noreturn ,!typedef, add_attributes_type !attr ty, env) in (* As done in CIL, partition !attr into struct-related attributes, which are returned, and other attributes, which are left in !attr. @@ -603,22 +722,28 @@ let rec elab_specifier keep_ty ?(only = false) loc env specifier = let a' = add_attributes (get_struct_attrs()) (elab_attributes env a) in let (id', env') = - elab_struct_or_union keep_ty only Struct loc id optmembers a' env in - (!sto, !inline, !noreturn, !typedef, TStruct(id', !attr), env') + elab_struct_or_union only Struct loc id optmembers a' env in + let ty = TStruct(id', !attr) in + restrict_check ty; + (!sto, !inline, !noreturn, !typedef, ty, env') | [Cabs.Tstruct_union(UNION, id, optmembers, a)] -> let a' = add_attributes (get_struct_attrs()) (elab_attributes env a) in let (id', env') = - elab_struct_or_union keep_ty only Union loc id optmembers a' env in - (!sto, !inline, !noreturn, !typedef, TUnion(id', !attr), env') + elab_struct_or_union only Union loc id optmembers a' env in + let ty = TUnion(id', !attr) in + restrict_check ty; + (!sto, !inline, !noreturn, !typedef, ty, env') | [Cabs.Tenum(id, optmembers, a)] -> let a' = add_attributes (get_struct_attrs()) (elab_attributes env a) in let (id', env') = elab_enum only loc id optmembers a' env in - (!sto, !inline, !noreturn, !typedef, TEnum(id', !attr), env') + let ty = TEnum (id', !attr) in + restrict_check ty; + (!sto, !inline, !noreturn, !typedef, ty, env') (* Specifier doesn't make sense *) | _ -> @@ -644,12 +769,23 @@ and elab_return_type loc env ty = error loc "function cannot return function type %a" (print_typ env) ty | _ -> () -and elab_type_declarator keep_ty loc env ty kr_ok = function +(* The [?fundef] parameter is true if we're elaborating a function definition + and false otherwise. When [fundef = true], K&R function declarators + are allowed, and the returned environment includes bindings for the + function parameters and the struct/unions they may define. + When [fundef = false], K&R function declarators are rejected + and declarations in parameters are not returned. *) + +and elab_type_declarator ?(fundef = false) loc env ty = function | Cabs.JUSTBASE -> ((ty, None), env) | Cabs.ARRAY(d, cv_specs, sz) -> let (ty, a) = get_nontype_attrs env ty in let a = add_attributes a (elab_cvspecs env cv_specs) in + if wrap incomplete_type loc env ty then + error loc "array type has incomplete element type %a" (print_typ env) ty; + if wrap contains_flex_array_mem loc env ty then + warning loc Flexible_array_extensions "%a may not be used as an array element due to flexible array member" (print_typ env) ty; let sz' = match sz with | None -> @@ -666,33 +802,45 @@ and elab_type_declarator keep_ty loc env ty kr_ok = function | None -> error loc "size of array is not a compile-time constant"; Some 1L in (* produces better error messages later *) - elab_type_declarator keep_ty loc env (TArray(ty, sz', a)) kr_ok d + elab_type_declarator ~fundef loc env (TArray(ty, sz', a)) d | Cabs.PTR(cv_specs, d) -> let (ty, a) = get_nontype_attrs env ty in let a = add_attributes a (elab_cvspecs env cv_specs) in - elab_type_declarator keep_ty loc env (TPtr(ty, a)) kr_ok d + if is_function_type env ty && incl_attributes [ARestrict] a then + error loc "pointer to function type %a may not be 'restrict' qualified" (print_typ env) ty; + elab_type_declarator ~fundef loc env (TPtr(ty, a)) d | Cabs.PROTO(d, (params, vararg)) -> elab_return_type loc env ty; let (ty, a) = get_nontype_attrs env ty in - let params',env' = elab_parameters keep_ty env params in - let env = if keep_ty then Env.add_types env env' else env in - elab_type_declarator keep_ty loc env (TFun(ty, Some params', vararg, a)) kr_ok d + let (params', env') = elab_parameters env params in + (* For a function declaration (fundef = false), the scope introduced + to treat parameters ends here, so we discard the extended + environment env' returned by elab_parameters. + For a function definition (fundef = true) we return the + extended environment env' so that it can serve as the basis + to elaborating the function body. *) + let env'' = if fundef then env' else env in + elab_type_declarator ~fundef loc env'' (TFun(ty, Some params', vararg, a)) d | Cabs.PROTO_OLD(d, params) -> elab_return_type loc env ty; let (ty, a) = get_nontype_attrs env ty in + (* For consistency with the PROTO case above, for a function definition + (fundef = true) we open a new scope, even though we do not + add any bindings for the parameters. *) + let env'' = if fundef then Env.new_scope env else env in match params with | [] -> - elab_type_declarator keep_ty loc env (TFun(ty, None, false, a)) kr_ok d + elab_type_declarator ~fundef loc env'' (TFun(ty, None, false, a)) d | _ -> - if not kr_ok || d <> Cabs.JUSTBASE then + if not fundef || d <> Cabs.JUSTBASE then fatal_error loc "illegal old-style K&R function definition"; - ((TFun(ty, None, false, a), Some params), env) + ((TFun(ty, None, false, a), Some params), env'') (* Elaboration of parameters in a prototype *) -and elab_parameters keep_ty env params = +and elab_parameters env params = (* Prototype introduces a new scope *) - let (vars, env) = mmap (elab_parameter keep_ty) (Env.new_scope env) params in + let (vars, env) = mmap elab_parameter (Env.new_scope env) params in (* Catch special case f(t) where t is void or a typedef to void *) match vars with | [ ( {C.name=""}, t) ] when is_void_type env t -> [],env @@ -700,42 +848,62 @@ and elab_parameters keep_ty env params = (* Elaboration of a function parameter *) -and elab_parameter keep_ty env (PARAM (spec, id, decl, attr, loc)) = - let (sto, inl, noret, tydef, bty, env1) = elab_specifier keep_ty loc env spec in +and elab_parameter env (PARAM (spec, id, decl, attr, loc)) = + let (sto, inl, noret, tydef, bty, env1) = elab_specifier loc env spec in if tydef then error loc "'typedef' used in function parameter"; - let ((ty, _), _) = elab_type_declarator keep_ty loc env1 bty false decl in + let ((ty, _), _) = elab_type_declarator loc env1 bty decl in let ty = add_attributes_type (elab_attributes env attr) ty in if sto <> Storage_default && sto <> Storage_register then - error loc - "invalid storage-class specifier in function declarator"; + error loc (* NB: 'auto' not allowed *) + "invalid storage class %s for function parameter" + (name_of_storage_class sto); if inl then error loc "'inline' can only appear on functions"; if noret then error loc "'_Noreturn' can only appear on functions"; let id = match id with None -> "" | Some id -> id in + if id <> "" && is_void_type env1 ty then + error loc "argument '%s' may not have 'void' type" id; if id <> "" && redef Env.lookup_ident env id then error loc "redefinition of parameter '%s'" id; (* replace array and function types by pointer types *) let ty1 = argument_conversion env1 ty in + if is_qualified_array ty1 then + error loc "type qualifier used in non-outermost array type derivation"; + if has_std_alignas env ty then begin + if id <> "" then + error loc "alignment specified for parameter '%s'" id + else + error loc "alignment specified for unnamed parameter" + end; let (id', env2) = Env.enter_ident env1 id sto ty1 in ( (id', ty1) , env2) -(* Elaboration of a (specifier, Cabs "name") pair *) - -and elab_fundef_name keep_ty env spec (Name (id, decl, attr, loc)) = - let (sto, inl, noret, tydef, bty, env') = elab_specifier keep_ty loc env spec in +(* Elaboration of a (specifier, Cabs "name") pair as found in a function + definition. Returns two environments: the first is [env] + enriched with struct/union definitions from the return type, + as usual; the second is like the first, plus a new scope. + For a prototyped function ([kr_params = None]) the new scope + includes bindings for the function parameters and the struct/unions + they may define. For a K&R function ([kr_params <> None]) the new + scope is empty. *) + +and elab_fundef_name env spec (Name (s, decl, attr, loc)) = + let (sto, inl, noret, tydef, bty, env') = elab_specifier loc env spec in if tydef then error loc "'typedef' is forbidden here"; - let ((ty, kr_params), env'') = elab_type_declarator keep_ty loc env' bty true decl in + let id = Env.fresh_ident s in + let ((ty, kr_params), env'') = + elab_type_declarator ~fundef:true loc env' bty decl in let a = elab_attributes env attr in - (id, sto, inl, noret, add_attributes_type a ty, kr_params, env'') + (id, sto, inl, noret, add_attributes_type a ty, kr_params, env', env'') (* Elaboration of a name group. C99 section 6.7.6 *) -and elab_name_group keep_ty loc env (spec, namelist) = +and elab_name_group loc env (spec, namelist) = let (sto, inl, noret, tydef, bty, env') = - elab_specifier keep_ty loc env spec in + elab_specifier loc env spec in if tydef then error loc "'typedef' is forbidden here"; if inl then @@ -744,35 +912,40 @@ and elab_name_group keep_ty loc env (spec, namelist) = error loc "'_Noreturn' is forbidden here"; let elab_one_name env (Name (id, decl, attr, loc)) = let ((ty, _), env1) = - elab_type_declarator keep_ty loc env bty false decl in + elab_type_declarator loc env bty decl in let a = elab_attributes env attr in ((id, add_attributes_type a ty), env1) in (mmap elab_one_name env' namelist, sto) (* Elaboration of an init-name group *) -and elab_init_name_group keep_ty loc env (spec, namelist) = +and elab_init_name_group loc env (spec, namelist) = let (sto, inl, noret, tydef, bty, env') = - elab_specifier keep_ty ~only:(namelist=[]) loc env spec in + elab_specifier ~only:(namelist=[]) loc env spec in + if noret && tydef then + error loc "'_Noreturn' can only appear on functions"; let elab_one_name env (Init_name (Name (id, decl, attr, loc), init)) = let ((ty, _), env1) = - elab_type_declarator keep_ty loc env bty false decl in + elab_type_declarator loc env bty decl in let a = elab_attributes env attr in - if inl && not (is_function_type env ty) then + let has_fun_typ = is_function_type env ty in + if inl && not has_fun_typ then error loc "'inline' can only appear on functions"; let a' = if noret then begin warning loc Celeven_extension "_Noreturn functions are a C11 extension"; - if not (is_function_type env ty) then + if not has_fun_typ then error loc "'_Noreturn' can only appear on functions"; add_attributes [Attr("noreturn",[])] a end else a in + if has_std_alignas env ty && has_fun_typ then + error loc "alignment specified for function '%s'" id; ((id, add_attributes_type a' ty, init), env1) in (mmap elab_one_name env' namelist, sto, tydef) (* Elaboration of a field group *) -and elab_field_group keep_ty env (Field_group (spec, fieldlist, loc)) = +and elab_field_group env (Field_group (spec, fieldlist, loc)) = let fieldlist = List.map (function (None, x) -> (Name ("", JUSTBASE, [], loc), x) @@ -781,7 +954,7 @@ and elab_field_group keep_ty env (Field_group (spec, fieldlist, loc)) = in let ((names, env'), sto) = - elab_name_group keep_ty loc env (spec, List.map fst fieldlist) in + elab_name_group loc env (spec, List.map fst fieldlist) in if sto <> Storage_default then error loc "non-default storage in struct or union"; @@ -789,10 +962,10 @@ and elab_field_group keep_ty env (Field_group (spec, fieldlist, loc)) = (* This should actually never be triggered, empty structs are captured earlier *) warning loc Missing_declarations "declaration does not declare anything"; - let elab_bitfield (Name (_, _, _, loc), optbitsize) (id, ty) = - let optbitsize' = + let elab_bitfield env (Name (_, _, _, loc), optbitsize) (id, ty) = + let optbitsize',env' = match optbitsize with - | None -> None + | None -> None,env | Some sz -> let ik = match unroll env' ty with @@ -802,40 +975,45 @@ and elab_field_group keep_ty env (Field_group (spec, fieldlist, loc)) = if integer_rank ik > integer_rank IInt then begin error loc "the type of bit-field '%a' must be an integer type no bigger than 'int'" pp_field id; - None + None,env + end else if has_std_alignas env' ty then begin + error loc "alignment specified for bit-field '%a'" pp_field id; + None, env end else begin let expr,env' =(!elab_expr_f loc env sz) in match Ceval.integer_expr env' expr with | Some n -> if n < 0L then begin error loc "bit-field '%a' has negative width (%Ld)" pp_field id n; - None + None,env end else let max = Int64.of_int(sizeof_ikind ik * 8) in if n > max then begin error loc "size of bit-field '%a' (%Ld bits) exceeds its type (%Ld bits)" pp_field id n max; - None + None,env end else if n = 0L && id <> "" then begin error loc "named bit-field '%a' has zero width" pp_field id; - None + None,env end else - Some(Int64.to_int n) + Some(Int64.to_int n),env' | None -> error loc "bit-field '%a' width not an integer constant" pp_field id; - None + None,env end in + if is_qualified_array ty then + error loc "type qualifier used in array declarator outside of function prototype"; let anon_composite = is_anonymous_composite ty in if id = "" && not anon_composite && optbitsize = None then warning loc Missing_declarations "declaration does not declare anything"; - { fld_name = id; fld_typ = ty; fld_bitfield = optbitsize'; fld_anonymous = id = "" && anon_composite} + { fld_name = id; fld_typ = ty; fld_bitfield = optbitsize'; fld_anonymous = id = "" && anon_composite},env' in - (List.map2 elab_bitfield fieldlist names, env') + (mmap2 elab_bitfield env' fieldlist names) (* Elaboration of a struct or union. C99 section 6.7.2.1 *) -and elab_struct_or_union_info keep_ty kind loc env members attrs = - let (m, env') = mmap (elab_field_group keep_ty) env members in +and elab_struct_or_union_info kind loc env members attrs = + let (m, env') = mmap elab_field_group env members in let m = List.flatten m in let m,_ = mmap (fun c fld -> if fld.fld_anonymous then @@ -866,16 +1044,22 @@ and elab_struct_or_union_info keep_ty kind loc env members attrs = duplicate acc rest in duplicate [] m; (* Check for incomplete types *) - let rec check_incomplete = function + let rec check_incomplete only = function | [] -> () - | [ { fld_typ = TArray(ty_elt, None, _) } ] when kind = Struct -> () - (* C99: ty[] allowed as last field of a struct *) + | [ { fld_typ = TArray(ty_elt, None, _) as typ; fld_name = name } ] when kind = Struct -> + (* C99: ty[] allowed as last field of a struct, provided this is not the only field *) + if only then + error loc "flexible array member '%a' not allowed in otherwise empty struct" pp_field name; + check_reduced_alignment loc env' typ | fld :: rem -> if wrap incomplete_type loc env' fld.fld_typ then (* Must be fatal otherwise we get problems constructing the init *) fatal_error loc "member '%a' has incomplete type" pp_field fld.fld_name; - check_incomplete rem in - check_incomplete m; + if wrap contains_flex_array_mem loc env' fld.fld_typ && kind = Struct then + warning loc Flexible_array_extensions "%a may not be used as a struct member due to flexible array member" (print_typ env) fld.fld_typ; + check_reduced_alignment loc env' fld.fld_typ; + check_incomplete false rem in + check_incomplete true m; (* Warn for empty structs or unions *) if m = [] then if kind = Struct then begin @@ -883,16 +1067,26 @@ and elab_struct_or_union_info keep_ty kind loc env members attrs = end else begin fatal_error loc "empty union is a GNU extension" end; + let ci = composite_info_def env' kind attrs m in + (* Warn for reduced alignment *) + if attrs <> [] then begin + let ci_nat = composite_info_def env' kind [] m in + warn_if_reduced_alignment loc + ~actual:ci.Env.ci_alignof ~natural:ci_nat.Env.ci_alignof + end; + (* Final result *) (composite_info_def env' kind attrs m, env') -and elab_struct_or_union keep_ty only kind loc tag optmembers attrs env = +and elab_struct_or_union only kind loc tag optmembers attrs env = let warn_attrs () = if attrs <> [] then - warning loc Unnamed "attribute declaration must precede definition" in + warning loc Ignored_attributes "attribute declaration must precede definition" in let optbinding, tag = match tag with | None -> None, "" | Some s -> + if redef Env.lookup_enum env s then + error loc "'%s' redeclared as different kind of symbol" s; Env.lookup_composite env s, s in match optbinding, optmembers with @@ -910,9 +1104,9 @@ and elab_struct_or_union keep_ty only kind loc tag optmembers attrs env = | Some(tag', ({Env.ci_sizeof = None} as ci)), Some members when Env.in_current_scope env tag' -> if ci.Env.ci_kind <> kind then - error loc "use of '%s' with tag type that does not match previous declaration" tag; + fatal_error loc "use of '%s' with tag type that does not match previous declaration" tag; (* finishing the definition of an incomplete struct or union *) - let (ci', env') = elab_struct_or_union_info keep_ty kind loc env members attrs in + let (ci', env') = elab_struct_or_union_info kind loc env members attrs in (* Emit a global definition for it *) emit_elab env' loc (Gcompositedef(kind, tag', attrs, ci'.Env.ci_members)); (* Replace infos but keep same ident *) @@ -939,7 +1133,7 @@ and elab_struct_or_union keep_ty only kind loc tag optmembers attrs env = emit_elab env' loc (Gcompositedecl(kind, tag', attrs)); (* elaborate the members *) let (ci2, env'') = - elab_struct_or_union_info keep_ty kind loc env' members attrs in + elab_struct_or_union_info kind loc env' members attrs in (* emit a definition *) emit_elab env'' loc (Gcompositedef(kind, tag', attrs, ci2.Env.ci_members)); (* Replace infos but keep same ident *) @@ -965,7 +1159,7 @@ and elab_enum_item env ((s, exp), loc) nextval = if redef Env.lookup_typedef env s then error loc "'%s' redeclared as different kind of symbol" s; if not (int_representable v (8 * sizeof_ikind enum_ikind) (is_signed_ikind enum_ikind)) then - warning loc Constant_conversion "integer literal '%Ld' is too large to be represented in any integer type" + warning loc Constant_conversion "integer literal '%Ld' is too large to be represented in the enumeration integer type" v; let (id, env') = Env.enter_enum_item env s v in ((id, v, exp'), Int64.succ v, env') @@ -973,10 +1167,15 @@ and elab_enum_item env ((s, exp), loc) nextval = (* Elaboration of an enumeration declaration. C99 section 6.7.2.2 *) and elab_enum only loc tag optmembers attrs env = - let tag = match tag with None -> "" | Some s -> s in + let tag = match tag with + | None -> "" + | Some s -> + if redef Env.lookup_struct env s || redef Env.lookup_union env s then + error loc "'%s' redeclared as different kind of symbol" s; + s in match optmembers with | None -> - if only then + if only && not (redef Env.lookup_enum env tag) then fatal_error loc "forward declaration of 'enum %s' is not allowed in ISO C" tag; let (tag', info) = wrap Env.lookup_enum loc env tag in (tag', env) @@ -998,10 +1197,12 @@ and elab_enum only loc tag optmembers attrs env = (* Elaboration of a naked type, e.g. in a cast *) let elab_type loc env spec decl = - let (sto, inl, noret, tydef, bty, env') = elab_specifier false loc env spec in - let ((ty, _), env'') = elab_type_declarator false loc env' bty false decl in + let (sto, inl, noret, tydef, bty, env') = elab_specifier loc env spec in + let ((ty, _), env'') = elab_type_declarator loc env' bty decl in + (* NB: it seems the parser doesn't accept any of the specifiers below. + We keep the error message as extra safety. *) if sto <> Storage_default || inl || noret || tydef then - error loc "'typedef', 'extern', 'static', 'register' and 'inline' are meaningless in cast"; + error loc "'typedef', 'extern', 'static', 'auto', 'register' and 'inline' are meaningless in cast"; (ty, env'') @@ -1040,11 +1241,11 @@ let check_init_type loc env a ty = else if wrap2 valid_cast loc env a.etyp ty then if wrap2 int_pointer_conversion loc env a.etyp ty then warning loc Int_conversion - "incompatible integer-pointer conversion initializer has type %a instead of the expected type %a" + "incompatible integer-pointer conversion: initializer has type %a instead of the expected type %a" (print_typ env) a.etyp (print_typ env) ty else warning loc Unnamed - "incompatible conversion initializer has type %a instead of the expected type %a" + "incompatible conversion: initializer has type %a instead of the expected type %a" (print_typ env) a.etyp (print_typ env) ty else error loc @@ -1087,6 +1288,9 @@ module I = struct (* Change the initializer for the current point *) let set (z, i) i' = (z, i') + (* Is the current point at top? *) + let at_top = function Ztop(_, _), _ -> true | _, _ -> false + (* Put the current point back to the top *) let rec to_top = function | Ztop(name, ty), i as zi -> zi @@ -1372,7 +1576,13 @@ and elab_single zi a il = from the expression: do as above *) elab_list (I.set zi (Init_single a)) il false | TStruct _ | TUnion _ | TArray _ -> - (* This is an aggregate: we need to drill into it, recursively *) + (* This is an aggregate. + At top, explicit { } are required. *) + if I.at_top zi then begin + error loc "invalid initializer, an initializer list was expected"; + raise Exit + end; + (* Otherwise we need to drill into the aggregate, recursively *) begin match I.first env zi with | I.OK zi' -> elab_single zi' a il @@ -1434,23 +1644,51 @@ let elab_initializer loc env root ty ie = (fixup_typ loc env ty init, Some init) +(* Contexts for elaborating statements and expressions *) + +type elab_context = { + ctx_return_typ: typ; (**r return type for the function *) + ctx_labels: StringSet.t; (**r all labels defined in the function *) + ctx_break: bool; (**r is 'break' allowed? *) + ctx_continue: bool; (**r is 'continue' allowed? *) + ctx_in_switch: bool; (**r are 'case' and 'default' allowed? *) + ctx_vararg: bool; (**r is this a vararg function? *) + ctx_nonstatic_inline: bool (**r is this a nonstatic inline function? *) +} + +(* Context for evaluating compile-time constant expressions. + Only the [ctx_vararg] and [ctx_nonstatic_inline] fields matter. *) +let ctx_constexp = { + ctx_return_typ = TVoid []; + ctx_labels = StringSet.empty; + ctx_break = false; ctx_continue = false; ctx_in_switch = false; + ctx_vararg = false; ctx_nonstatic_inline = false +} + + (* Elaboration of expressions *) -let elab_expr vararg loc env a = +let elab_expr ctx loc env a = - let err fmt = error loc fmt in (* non-fatal error *) - let error fmt = fatal_error loc fmt in - let warning t fmt = - warning loc t fmt in + let error fmt = error loc fmt in + let fatal_error fmt = fatal_error loc fmt in + let warning t fmt = warning loc t fmt in let check_ptr_arith env ty s = match unroll env ty with | TVoid _ -> - err "illegal arithmetic on a pointer to void in binary '%c'" s + error "illegal arithmetic on a pointer to void in binary '%c'" s | TFun _ -> - err "illegal arithmetic on a pointer to the function type %a in binary '%c'" (print_typ env) ty s + error "illegal arithmetic on a pointer to the function type %a in binary '%c'" (print_typ env) ty s | _ -> if incomplete_type env ty then - err "arithmetic on a pointer to an incomplete type %a in binary '%c'" (print_typ env) ty s + error "arithmetic on a pointer to an incomplete type %a in binary '%c'" (print_typ env) ty s + in + + let check_static_var id sto ty = + if ctx.ctx_nonstatic_inline + && sto = Storage_static + && List.mem AConst (attributes_of_type env ty) + then warning Static_in_inline "static variable '%s' is used in an inline function with external linkage" id.C.name in let rec elab env = function @@ -1459,7 +1697,8 @@ let elab_expr vararg loc env a = | VARIABLE s -> begin match wrap Env.lookup_ident loc env s with - | (id, Env.II_ident(sto, ty)) -> + | (id, Env.II_ident(sto, ty)) -> + check_static_var id sto ty; { edesc = EVar id; etyp = ty },env | (id, Env.II_enum v) -> { edesc = EConst(CEnum(id, v)); etyp = TInt(enum_ikind, []) },env @@ -1478,7 +1717,7 @@ let elab_expr vararg loc env a = match (unroll env b1.etyp, unroll env b2.etyp) with | (TPtr(t, _) | TArray(t, _, _)), (TInt _ | TEnum _) -> t | (TInt _ | TEnum _), (TPtr(t, _) | TArray(t, _, _)) -> t - | t1, t2 -> error "subscripted value is neither an array nor pointer" in + | t1, t2 -> fatal_error "subscripted value is neither an array nor pointer" in { edesc = EBinop(Oindex, b1, b2, TPtr(tres, [])); etyp = tres },env | MEMBEROF(a1, fieldname) -> @@ -1490,7 +1729,7 @@ let elab_expr vararg loc env a = | TUnion(id, attrs) -> (wrap Env.find_union_member loc env (id, fieldname), attrs) | _ -> - error "request for member '%s' in something not a structure or union" fieldname in + fatal_error "request for member '%s' in something not a structure or union" fieldname in (* A field of a const/volatile struct or union is itself const/volatile *) let rec access = function | [] -> b1 @@ -1512,10 +1751,10 @@ let elab_expr vararg loc env a = | TUnion(id, attrs) -> (wrap Env.find_union_member loc env (id, fieldname), attrs) | _ -> - error "request for member '%s' in something not a structure or union" fieldname + fatal_error "request for member '%s' in something not a structure or union" fieldname end | _ -> - error "member reference type %a is not a pointer" (print_typ env) b1.etyp in + fatal_error "member reference type %a is not a pointer" (print_typ env) b1.etyp in let rec access = function | [] -> assert false | [fld] -> @@ -1538,8 +1777,8 @@ let elab_expr vararg loc env a = (elaboration) --> __builtin_va_arg(ap, sizeof(ty)) *) | CALL((VARIABLE "__builtin_va_start" as a1), [a2; a3]) -> - if not vararg then - err "'va_start' used in function with fixed args"; + if not ctx.ctx_vararg then + error "'va_start' used in function with fixed args"; let b1,env = elab env a1 in let b2,env = elab env a2 in let _b3,env = elab env a3 in @@ -1584,9 +1823,9 @@ let elab_expr vararg loc env a = | TPtr(ty, a) -> begin match unroll env ty with | TFun(res, args, vararg, a) -> (res, args, vararg) - | _ -> error "called object type %a is neither a function nor function pointer" (print_typ env) b1.etyp + | _ -> fatal_error "called object type %a is neither a function nor function pointer" (print_typ env) b1.etyp end - | _ -> error "called object type %a is neither a function nor function pointer" (print_typ env) b1.etyp + | _ -> fatal_error "called object type %a is neither a function nor function pointer" (print_typ env) b1.etyp in (* Type-check the arguments against the prototype *) let bl',env = @@ -1608,18 +1847,18 @@ let elab_expr vararg loc env a = if not (wrap2 valid_cast loc env b1.etyp ty) then begin match unroll env b1.etyp, unroll env ty with | _, (TStruct _|TUnion _ | TVoid _) -> - err "used type %a where arithmetic or pointer type is required" + error "used type %a where arithmetic or pointer type is required" (print_typ env) ty | (TStruct _| TUnion _ | TVoid _),_ -> - err "operand of type %a where arithmetic or pointer type is required" + error "operand of type %a where arithmetic or pointer type is required" (print_typ env) b1.etyp | TFloat _, TPtr _ -> - err "operand of type %a cannot be cast to a pointer type" + error "operand of type %a cannot be cast to a pointer type" (print_typ env) b1.etyp | TPtr _ , TFloat _ -> - err "pointer cannot be cast to type %a" (print_typ env) ty + error "pointer cannot be cast to type %a" (print_typ env) ty | _ -> - err "illegal cast from %a to %a" (print_typ env) b1.etyp (print_typ env) ty + error "illegal cast from %a to %a" (print_typ env) b1.etyp (print_typ env) ty end; { edesc = ECast(ty, b1); etyp = ty },env @@ -1629,7 +1868,7 @@ let elab_expr vararg loc env a = let (ty, env) = elab_type loc env spec dcl in begin match elab_initializer loc env "<compound literal>" ty ie with | (ty', Some i) -> { edesc = ECompound(ty', i); etyp = ty' },env - | (ty', None) -> error "ill-formed compound literal" + | (ty', None) -> fatal_error "ill-formed compound literal" end (* 6.5.3 Unary expressions *) @@ -1637,54 +1876,39 @@ let elab_expr vararg loc env a = | EXPR_SIZEOF a1 -> let b1,env = elab env a1 in if wrap incomplete_type loc env b1.etyp then - error "invalid application of 'sizeof' to an incomplete type %a" (print_typ env) b1.etyp; + fatal_error "invalid application of 'sizeof' to an incomplete type %a" (print_typ env) b1.etyp; if wrap is_bitfield loc env b1 then - error "invalid application of 'sizeof' to a bit-field"; - let bdesc = - (* Catch special cases sizeof("string literal") *) - match b1.edesc with - | EConst(CStr s) -> - let sz = String.length s + 1 in - EConst(CInt(Int64.of_int sz, size_t_ikind(), "")) - | EConst(CWStr s) -> - let sz = (!config).sizeof_wchar * (List.length s + 1) in - EConst(CInt(Int64.of_int sz, size_t_ikind(), "")) - | _ -> - ESizeof b1.etyp in - { edesc = bdesc; etyp = TInt(size_t_ikind(), []) },env + fatal_error "invalid application of 'sizeof' to a bit-field"; + { edesc = ESizeof b1.etyp; etyp = TInt(size_t_ikind(), []) },env | TYPE_SIZEOF (spec, dcl) -> let (ty, env') = elab_type loc env spec dcl in if wrap incomplete_type loc env' ty then - error "invalid application of 'sizeof' to an incomplete type %a" (print_typ env) ty; + fatal_error "invalid application of 'sizeof' to an incomplete type %a" (print_typ env) ty; { edesc = ESizeof ty; etyp = TInt(size_t_ikind(), []) },env' - | EXPR_ALIGNOF a1 -> - let b1,env = elab env a1 in - if wrap incomplete_type loc env b1.etyp then - error "invalid application of '_Alignof' to an incomplete type %a" (print_typ env) b1.etyp; - if wrap is_bitfield loc env b1 then - error "invalid application of '_Alignof' to a bit-field"; - { edesc = EAlignof b1.etyp; etyp = TInt(size_t_ikind(), []) },env - - | TYPE_ALIGNOF (spec, dcl) -> + | ALIGNOF (spec, dcl) -> let (ty, env') = elab_type loc env spec dcl in + warning Celeven_extension "'_Alignof' is a C11 extension"; if wrap incomplete_type loc env' ty then - error "invalid application of 'alignof' to an incomplete type %a" (print_typ env) ty; + fatal_error "invalid application of 'alignof' to an incomplete type %a" (print_typ env) ty; { edesc = EAlignof ty; etyp = TInt(size_t_ikind(), []) },env' | BUILTIN_OFFSETOF ((spec,dcl), mem) -> let (ty,env) = elab_type loc env spec dcl in if incomplete_type env ty then - error "offsetof of incomplete type %a" (print_typ env) ty; + fatal_error "offsetof of incomplete type %a" (print_typ env) ty; let members env ty mem = match ty with | TStruct (id,_) -> wrap Env.find_struct_member loc env (id,mem) | TUnion (id,_) -> wrap Env.find_union_member loc env (id,mem) - | _ -> error "request for member '%s' in something not a structure or union" mem in + | _ -> fatal_error "request for member '%s' in something not a structure or union" mem in let rec offset_of_list acc env ty = function | [] -> acc,ty - | fld::rest -> let off = offsetof env ty fld in + | fld::rest -> + if fld.fld_bitfield <> None then + fatal_error "cannot compute offset of bit-field '%s'" fld.fld_name; + let off = offsetof env ty fld in offset_of_list (acc+off) env fld.fld_typ rest in let offset_of_member (env,off_accu,ty) mem = match mem,unroll env ty with @@ -1696,16 +1920,16 @@ let elab_expr vararg loc env a = | ATINDEX_INIT e,TArray (sub_ty,_,_) -> let e,env = elab env e in let e = match Ceval.integer_expr env e with - | None -> error "array element designator for is not an integer constant expression" + | None -> fatal_error "array element designator is not an integer constant expression" | Some n-> n in let size = match sizeof env sub_ty with | None -> assert false (* We expect only complete types *) | Some s -> s in let off_accu = match cautious_mul e size with - | None -> error "'offsetof' overflows" + | None -> fatal_error "'offsetof' overflows" | Some s -> off_accu + s in env,off_accu,sub_ty - | ATINDEX_INIT _,_ -> error "subscripted value is not an array" in + | ATINDEX_INIT _,_ -> fatal_error "subscripted value is not an array" in let env,offset,_ = List.fold_left offset_of_member (env,0,ty) mem in let size_t = size_t_ikind () in let offset = Ceval.normalize_int (Int64.of_int offset) size_t in @@ -1715,46 +1939,46 @@ let elab_expr vararg loc env a = | UNARY(PLUS, a1) -> let b1,env = elab env a1 in if not (is_arith_type env b1.etyp) then - error "invalid argument type %a to unary '+'" (print_typ env) b1.etyp; + fatal_error "invalid argument type %a to unary '+'" (print_typ env) b1.etyp; { edesc = EUnop(Oplus, b1); etyp = unary_conversion env b1.etyp },env | UNARY(MINUS, a1) -> let b1,env = elab env a1 in if not (is_arith_type env b1.etyp) then - error "invalid argument type %a to unary '-'" (print_typ env) b1.etyp; + fatal_error "invalid argument type %a to unary '-'" (print_typ env) b1.etyp; { edesc = EUnop(Ominus, b1); etyp = unary_conversion env b1.etyp },env | UNARY(BNOT, a1) -> let b1,env = elab env a1 in if not (is_integer_type env b1.etyp) then - error "invalid argument type %a to unary '~'" (print_typ env) b1.etyp; + fatal_error "invalid argument type %a to unary '~'" (print_typ env) b1.etyp; { edesc = EUnop(Onot, b1); etyp = unary_conversion env b1.etyp },env | UNARY(NOT, a1) -> let b1,env = elab env a1 in if not (is_scalar_type env b1.etyp) then - error "invalid argument type %a to unary '!'" (print_typ env) b1.etyp; + fatal_error "invalid argument type %a to unary '!'" (print_typ env) b1.etyp; { edesc = EUnop(Olognot, b1); etyp = TInt(IInt, []) },env | UNARY(ADDROF, a1) -> let b1,env = elab env a1 in if not (is_lvalue b1 || is_function_type env b1.etyp) then - err "argument of '&' is not an lvalue (invalid %a)" (print_typ env) b1.etyp; + error "argument of '&' is not an lvalue (invalid %a)" (print_typ env) b1.etyp; begin match b1.edesc with | EVar id -> begin match wrap Env.find_ident loc env id with | Env.II_ident(Storage_register, _) -> - err "address of register variable '%s' requested" id.C.name + error "address of register variable '%s' requested" id.C.name | _ -> () end | EUnop(Odot f, b2) -> let fld = wrap2 field_of_dot_access loc env b2.etyp f in if fld.fld_bitfield <> None then - err "address of bit-field '%s' requested" f + error "address of bit-field '%s' requested" f | EUnop(Oarrow f, b2) -> let fld = wrap2 field_of_arrow_access loc env b2.etyp f in if fld.fld_bitfield <> None then - err "address of bit-field '%s' requested" f + error "address of bit-field '%s' requested" f | _ -> () end; { edesc = EUnop(Oaddrof, b1); etyp = TPtr(b1.etyp, []) },env @@ -1767,7 +1991,7 @@ let elab_expr vararg loc env a = | TPtr(ty, _) | TArray(ty, _, _) -> { edesc = EUnop(Oderef, b1); etyp = ty },env | _ -> - error "arguemnt of unary '*' is not a pointer (%a invalid)" + fatal_error "argument of unary '*' is not a pointer (%a invalid)" (print_typ env) b1.etyp end @@ -1798,7 +2022,7 @@ let elab_expr vararg loc env a = match unroll env b1.etyp, unroll env b2.etyp with | (TPtr(ty, a) | TArray(ty, _, a)), (TInt _ | TEnum _) -> ty | (TInt _ | TEnum _), (TPtr(ty, a) | TArray(ty, _, a)) -> ty - | _, _ -> error "invalid operands to binary '+' (%a and %a)" + | _, _ -> fatal_error "invalid operands to binary '+' (%a and %a)" (print_typ env) b1.etyp (print_typ env) b2.etyp in check_ptr_arith env ty '+'; @@ -1817,21 +2041,19 @@ let elab_expr vararg loc env a = match wrap unroll loc env b1.etyp, wrap unroll loc env b2.etyp with | (TPtr(ty, a) | TArray(ty, _, a)), (TInt _ | TEnum _) -> if not (wrap pointer_arithmetic_ok loc env ty) then - err "illegal pointer arithmetic in binary '-'"; - (TPtr(ty, []), TPtr(ty, [])) - | (TInt _ | TEnum _), (TPtr(ty, a) | TArray(ty, _, a)) -> - check_ptr_arith env ty '-'; + error "illegal pointer arithmetic in binary '-'"; (TPtr(ty, []), TPtr(ty, [])) | (TPtr(ty1, a1) | TArray(ty1, _, a1)), (TPtr(ty2, a2) | TArray(ty2, _, a2)) -> if not (compatible_types AttrIgnoreAll env ty1 ty2) then - err "%a and %a are not pointers to compatible types" + error "%a and %a are not pointers to compatible types" (print_typ env) b1.etyp (print_typ env) b1.etyp; check_ptr_arith env ty1 '-'; + check_ptr_arith env ty2 '-'; if wrap sizeof loc env ty1 = Some 0 then - err "subtraction between two pointers to zero-sized objects"; + error "subtraction between two pointers to zero-sized objects"; (TPtr(ty1, []), TInt(ptrdiff_t_ikind(), [])) - | _, _ -> error "invalid operands to binary '-' (%a and %a)" + | _, _ -> fatal_error "invalid operands to binary '-' (%a and %a)" (print_typ env) b1.etyp (print_typ env) b2.etyp end in { edesc = EBinop(Osub, b1, b2, tyop); etyp = tyres },env @@ -1875,7 +2097,7 @@ let elab_expr vararg loc env a = let b2,env = elab env a2 in let b3,env = elab env a3 in if not (is_scalar_type env b1.etyp) then - err "first argument of '?:' is not a scalar type (invalid %a)" + error "first argument of '?:' is not a scalar type (invalid %a)" (print_typ env) b1.etyp; begin match pointer_decay env b2.etyp, pointer_decay env b3.etyp with | (TInt _ | TFloat _ | TEnum _), (TInt _ | TFloat _ | TEnum _) -> @@ -1903,7 +2125,7 @@ let elab_expr vararg loc env a = | ty1, ty2 -> match combine_types AttrIgnoreAll env ty1 ty2 with | None -> - error "the second and third argument of '?:' incompatible types (%a and %a)" + fatal_error "the second and third argument of '?:' incompatible types (%a and %a)" (print_typ env) ty1 (print_typ env) ty2 | Some tyres -> { edesc = EConditional(b1, b2, b3); etyp = tyres },env @@ -1917,7 +2139,7 @@ let elab_expr vararg loc env a = if List.mem AConst (attributes_of_type env b1.etyp) then error "left-hand side of assignment has 'const' type"; if not (is_modifiable_lvalue env b1) then - err "expression is not assignable"; + error "expression is not assignable"; if not (wrap2 valid_assignment loc env b2 b1.etyp) then begin if wrap2 valid_cast loc env b2.etyp b1.etyp then if wrap2 int_pointer_conversion loc env b2.etyp b1.etyp then @@ -1926,10 +2148,10 @@ let elab_expr vararg loc env a = (print_typ env) b1.etyp (print_typ env) b2.etyp else warning Unnamed - "incompatible conversion assigning to %a from %a" + "incompatible conversion: assigning to %a from %a" (print_typ env) b1.etyp (print_typ env) b2.etyp else - err "assigning to %a from incompatible type %a" + error "assigning to %a from incompatible type %a" (print_typ env) b1.etyp (print_typ env) b2.etyp; end; { edesc = EBinop(Oassign, b1, b2, b1.etyp); etyp = b1.etyp },env @@ -1953,9 +2175,9 @@ let elab_expr vararg loc env a = begin match elab env (BINARY(sop, a1, a2)) with | ({ edesc = EBinop(_, b1, b2, _); etyp = ty } as b),env -> if List.mem AConst (attributes_of_type env b1.etyp) then - err "left-hand side of assignment has 'const' type"; + error "left-hand side of assignment has 'const' type"; if not (is_modifiable_lvalue env b1) then - err "expression is not assignable"; + error "expression is not assignable"; if not (wrap2 valid_assignment loc env b b1.etyp) then begin if wrap2 valid_cast loc env ty b1.etyp then if wrap2 int_pointer_conversion loc env ty b1.etyp then @@ -1964,10 +2186,10 @@ let elab_expr vararg loc env a = (print_typ env) b1.etyp (print_typ env) ty else warning Unnamed - "incompatible conversion assigning to %a from %a" + "incompatible conversion: assigning to %a from %a" (print_typ env) b1.etyp (print_typ env) ty else - err "assigning to %a from incompatible type %a" + error "assigning to %a from incompatible type %a" (print_typ env) b1.etyp (print_typ env) ty; end; { edesc = EBinop(top, b1, b2, ty); etyp = b1.etyp },env @@ -1986,9 +2208,9 @@ let elab_expr vararg loc env a = and elab_pre_post_incr_decr op msg a1 = let b1,env = elab env a1 in if not (is_modifiable_lvalue env b1) then - err "expression is not assignable"; + error "expression is not assignable"; if not (is_scalar_type env b1.etyp) then - err "cannot %s value of type %a" msg (print_typ env) b1.etyp; + error "cannot %s value of type %a" msg (print_typ env) b1.etyp; { edesc = EUnop(op, b1); etyp = b1.etyp },env (* Elaboration of binary operators over integers *) @@ -1996,7 +2218,7 @@ let elab_expr vararg loc env a = let b1,env = elab env a1 in let b2,env = elab env a2 in if not ((is_integer_type env b1.etyp) && (is_integer_type env b2.etyp)) then - error "invalid operands to binary '%s' (%a and %a)" msg + fatal_error "invalid operands to binary '%s' (%a and %a)" msg (print_typ env) b1.etyp (print_typ env) b2.etyp; let tyres = binary_conversion env b1.etyp b2.etyp in { edesc = EBinop(op, b1, b2, tyres); etyp = tyres },env @@ -2006,7 +2228,7 @@ let elab_expr vararg loc env a = let b1,env = elab env a1 in let b2,env = elab env a2 in if not ((is_arith_type env b1.etyp) && (is_arith_type env b2.etyp)) then - error "invalid operands to binary '%s' (%a and %a)" msg + fatal_error "invalid operands to binary '%s' (%a and %a)" msg (print_typ env) b1.etyp (print_typ env) b2.etyp; let tyres = binary_conversion env b1.etyp b2.etyp in { edesc = EBinop(op, b1, b2, tyres); etyp = tyres },env @@ -2016,7 +2238,7 @@ let elab_expr vararg loc env a = let b1,env = elab env a1 in let b2,env = elab env a2 in if not ((is_integer_type env b1.etyp) && (is_integer_type env b2.etyp)) then - error "invalid operands to '%s' (%a and %a)" msg + fatal_error "invalid operands to '%s' (%a and %a)" msg (print_typ env) b1.etyp (print_typ env) b2.etyp; let tyres = unary_conversion env b1.etyp in { edesc = EBinop(op, b1, b2, tyres); etyp = tyres },env @@ -2043,6 +2265,10 @@ let elab_expr vararg loc env a = if not (compatible_types AttrIgnoreAll env ty1 ty2) then warning Compare_distinct_pointer_types "comparison of distinct pointer types (%a and %a)" (print_typ env) b1.etyp (print_typ env) b2.etyp; + let incomp_ty1 = wrap incomplete_type loc env ty1 + and incomp_ty2 = wrap incomplete_type loc env ty2 in + if incomp_ty1 <> incomp_ty2 then + warning Unnamed "comparison of complete and incomplete pointers"; EBinop(op, b1, b2, TPtr(ty1, [])) | TPtr _, (TInt _ | TEnum _) | (TInt _ | TEnum _), TPtr _ -> @@ -2050,7 +2276,7 @@ let elab_expr vararg loc env a = (print_typ env) b1.etyp (print_typ env) b2.etyp; EBinop(op, b1, b2, TPtr(TVoid [], [])) | ty1, ty2 -> - error "illegal comparison between types@ %a@ and %a" + fatal_error "illegal comparison between types@ %a@ and %a" (print_typ env) b1.etyp (print_typ env) b2.etyp; in { edesc = resdesc; etyp = TInt(IInt, []) },env @@ -2059,7 +2285,7 @@ let elab_expr vararg loc env a = let b1,env = elab env a1 in let b2,env = elab env a2 in if not ((is_scalar_type env b1.etyp) && (is_scalar_type env b2.etyp)) then - error "invalid operands to binary %s (%a and %a)" msg + fatal_error "invalid operands to binary '%s' (%a and %a)" msg (print_typ env) b1.etyp (print_typ env) b2.etyp; { edesc = EBinop(op, b1, b2, TInt(IInt, [])); etyp = TInt(IInt, []) },env @@ -2071,14 +2297,14 @@ let elab_expr vararg loc env a = let found = argno - 1 in let expected = List.length params + found in let vararg = if vararg then "at least " else "" in - err "too few arguments to function call, expected %s%d, have %d" vararg expected found; [],env + error "too few arguments to function call, expected %s%d, have %d" vararg expected found; [],env | (_::_,env), [] -> if vararg then args else let expected = argno - 1 in let found = List.length (fst args) + expected in - (err "too many arguments to function call, expected %d, have %d" expected found; args) + (error "too many arguments to function call, expected %d, have %d" expected found; args) | (arg1 :: argl,env), (_, ty_p) :: paraml -> let ty_a = argument_conversion env arg1.etyp in if not (wrap2 valid_assignment loc env {arg1 with etyp = ty_a} ty_p) @@ -2090,10 +2316,10 @@ let elab_expr vararg loc env a = (print_typ env) ty_a argno (print_typ env) ty_p else warning Unnamed - "incompatible conversion passing %a to parameter %d of type %a" + "incompatible conversion: passing %a to parameter %d of type %a" (print_typ env) ty_a argno (print_typ env) ty_p end else - err + error "passing %a to parameter %d of incompatible type %a" (print_typ env) ty_a argno (print_typ env) ty_p end; @@ -2102,16 +2328,16 @@ let elab_expr vararg loc env a = in elab env a (* Filling in forward declaration *) -let _ = elab_expr_f := (elab_expr false) +let _ = elab_expr_f := (elab_expr ctx_constexp) -let elab_opt_expr vararg loc env = function +let elab_opt_expr ctx loc env = function | None -> None,env - | Some a -> let a,env = (elab_expr vararg loc env a) in + | Some a -> let a,env = (elab_expr ctx loc env a) in Some a,env -let elab_for_expr vararg loc env = function +let elab_for_expr ctx loc env = function | None -> { sdesc = Sskip; sloc = elab_loc loc },env - | Some a -> let a,env = elab_expr vararg loc env a in + | Some a -> let a,env = elab_expr ctx loc env a in { sdesc = Sdo a; sloc = elab_loc loc },env (* Handling of __func__ (section 6.4.2.2) *) @@ -2125,49 +2351,69 @@ let __func__type_and_init s = let enter_typedefs loc env sto dl = if sto <> Storage_default then - error loc "non-default storage-class on 'typedef' definition"; + error loc "non-default storage class on 'typedef' definition"; + if dl = [] then + warning loc Missing_declarations "typedef requires a name"; List.fold_left (fun env (s, ty, init) -> if init <> NO_INIT then error loc "initializer in typedef"; + if has_std_alignas env ty then + error loc "alignment specified for typedef '%s'" s; match previous_def Env.lookup_typedef env s with - | Some (s',ty') -> + | Some (s',ty') when Env.in_current_scope env s' -> if equal_types env ty ty' then begin - warning loc Celeven_extension "redefinition of typedef '%s' is C11 extension" s; + warning loc Celeven_extension "redefinition of typedef '%s' is a C11 extension" s; env end else begin error loc "typedef redefinition with different types (%a vs %a)" (print_typ env) ty (print_typ env) ty'; env end - | None -> + | _ -> if redef Env.lookup_ident env s then error loc "redefinition of '%s' as different kind of symbol" s; let (id, env') = Env.enter_typedef env s ty in + check_reduced_alignment loc env' ty; emit_elab env loc (Gtypedef(id, ty)); env') env dl -let enter_decdefs local loc env sto dl = +let enter_decdefs local nonstatic_inline loc env sto dl = (* Sanity checks on storage class *) - if sto = Storage_register && not local then - fatal_error loc "'register' storage-class on file-scoped variable"; + if (sto = Storage_auto || sto = Storage_register) && not local then + fatal_error loc "illegal storage class %s on file-scoped variable" + (name_of_storage_class sto); if sto <> Storage_default && dl = [] then warning loc Missing_declarations "declaration does not declare anything"; let enter_decdef (decls, env) (s, ty, init) = let isfun = is_function_type env ty in + if sto = Storage_register && has_std_alignas env ty then + error loc "alignment specified for 'register' object '%s'" s; if sto = Storage_extern && init <> NO_INIT then - error loc "'extern' declaration variable has an initializer"; + error loc "'extern' declaration variable has an initializer"; if local && isfun then begin match sto with - | Storage_static -> error loc "function declared in block scope cannot have 'static' storage-class"; - | Storage_register -> error loc "invalid 'register' storage-class on function"; + | Storage_static -> + error loc "function declared in block scope cannot have 'static' storage class" + | Storage_auto | Storage_register -> + error loc "illegal storage class %s on function" + (name_of_storage_class sto) | _ -> () end; - (* Local function declarations are always treated as extern *) - let sto1 = if local && isfun then Storage_extern else sto in + if is_qualified_array ty then + error loc "type qualifier used in array declarator outside of function prototype"; + (* Local variable declarations with default storage are treated as 'auto'. + Local function declarations with default storage remain with + default storage. *) + let sto1 = + if local && sto = Storage_default && not isfun + then Storage_auto + else sto in (* enter ident in environment with declared type, because initializer can refer to the ident *) let (id, sto', env1, ty, linkage) = enter_or_refine_ident local loc env s sto1 ty in + if init <> NO_INIT && not local then + add_global_define loc s; if not isfun && is_void_type env ty then fatal_error loc "'%s' has incomplete type" s; (* process the initializer *) @@ -2175,16 +2421,30 @@ let enter_decdefs local loc env sto dl = (* update environment with refined type *) let env2 = Env.add_ident env1 id sto' ty' in (* check for incomplete type *) - if local && sto' <> Storage_extern - && not isfun - && wrap incomplete_type loc env ty' then - error loc "variable has incomplete type %a" (print_typ env) ty'; + if not isfun && wrap incomplete_type loc env ty' then + if not local && sto' = Storage_static then begin + warning loc Tentative_incomplete_static "tentative static definition with incomplete type"; + end else if local && sto' <> Storage_extern then + error loc "variable has incomplete type %a" (print_typ env) ty'; + (* check if alignment is reduced *) + check_reduced_alignment loc env ty'; + (* check for static variables in nonstatic inline functions *) + if local && nonstatic_inline + && sto' = Storage_static + && not (List.mem AConst (attributes_of_type env ty')) then + warning loc Static_in_inline "non-constant static local variable '%s' in inline function may be different in different files" s; if local && not isfun && sto' <> Storage_extern && sto' <> Storage_static then (* Local definition *) ((sto', id, ty', init') :: decls, env2) else begin (* Global definition *) emit_elab ~linkage env2 loc (Gdecl(sto', id, ty', init')); + (* Make sure the initializer is constant. *) + begin match init' with + | Some i when not (Ceval.is_constant_init env2 i) -> + error loc "initializer is not a compile-time constant" + | _ -> () + end; (decls, env2) end in let (decls, env') = List.fold_left enter_decdef ([], env) dl in @@ -2216,7 +2476,7 @@ let elab_KR_function_parameters env params defs loc = (* Check that the declarations only declare parameters *) let extract_name (Init_name(Name(s, dty, attrs, loc') as name, ie)) = if not (List.mem s params) then - error loc' "Declaration of '%s' which is not a function parameter" s; + error loc' "declaration of '%s' which is not a function parameter" s; if ie <> NO_INIT then error loc' "illegal initialization of parameter '%s'" s; name @@ -2225,18 +2485,17 @@ let elab_KR_function_parameters env params defs loc = let elab_param_def env = function | DECDEF((spec', name_init_list), loc') -> let name_list = List.map extract_name name_init_list in - let (paramsenv, sto) = elab_name_group true loc' env (spec', name_list) in - begin match sto with - | Storage_extern -> - error loc' "invalid 'extern' storage-class specifier for function parameter" - | Storage_static -> - error loc' "invalid 'static' storage-class specifier for function parameter" - | _ -> () - end; + if name_list = [] then + error loc' "declaration does not declare a parameter"; + let (paramsenv, sto) = elab_name_group loc' env (spec', name_list) in + if sto <> Storage_default && sto <> Storage_register then + error loc' (* NB: 'auto' not allowed *) + "invalid storage class %s for function parameter" + (name_of_storage_class sto); paramsenv | d -> (* Should never be produced by the parser *) fatal_error (Cabshelper.get_definitionloc d) - "Illegal declaration of function parameter" in + "illegal declaration of function parameter" in let kr_params_defs,paramsenv = let params,paramsenv = mmap elab_param_def env defs in List.concat params,paramsenv in @@ -2296,11 +2555,22 @@ let inherit_vararg env s sto ty = (* Function definitions *) -let elab_fundef env spec name defs body loc = - let (s, sto, inline, noret, ty, kr_params, env1) = - elab_fundef_name true env spec name in - if sto = Storage_register then - fatal_error loc "invalid 'register' storage-class on function"; +let elab_fundef genv spec name defs body loc = + (* We maintain two environments: + - genv is the "global", file-scope environment. It is enriched + with the declaration of the function, and also with + structs and unions defined as part of its return type. + - lenv is the "local" environment used to elaborate the function body. + It contains everything that genv contains, including + a declaration for the function, so as to support recursive calls. + In addition, it contains declarations for function parameters + and structs and unions defined in the parameter list. *) + let (fun_id, sto, inline, noret, ty, kr_params, genv, lenv) = + elab_fundef_name genv spec name in + let s = fun_id.C.name in + if sto = Storage_auto || sto = Storage_register then + fatal_error loc "invalid storage class %s on function" + (name_of_storage_class sto); begin match kr_params, defs with | None, d::_ -> error (Cabshelper.get_definitionloc d) @@ -2310,54 +2580,77 @@ let elab_fundef env spec name defs body loc = (* Process the parameters and the K&R declarations, if any, to obtain: - [ty]: the full, prototyped type of the function - [extra_decls]: extra declarations to be inserted at the - beginning of the function *) - let (ty, extra_decls,env1) = + beginning of the function + - [lenv]: a first cut at the local environment, containing in particular + the structs and unions defined in the parameter list. *) + let (ty, extra_decls, lenv) = match ty, kr_params with | TFun(ty_ret, None, vararg, attr), None -> - (TFun(ty_ret, Some [], vararg, attr), [],env1) + (TFun(ty_ret, Some [], vararg, attr), [], lenv) | ty, None -> - (ty, [],env1) + (ty, [], lenv) | TFun(ty_ret, None, false, attr), Some params -> warning loc CompCert_conformance "non-prototype, pre-standard function definition, converting to prototype form"; - let (params', extra_decls,env) = - elab_KR_function_parameters env params defs loc in - (TFun(ty_ret, Some params', inherit_vararg env s sto ty, attr), extra_decls,env) + let (params', extra_decls, lenv) = + elab_KR_function_parameters lenv params defs loc in + (TFun(ty_ret, Some params', inherit_vararg genv s sto ty, attr), extra_decls, lenv) | _, Some params -> assert false in - (* Extract infos from the type of the function *) + (* Extract infos from the type of the function. + Checks on the return type must be done in the global environment. *) let (ty_ret, params, vararg, attr) = match ty with | TFun(ty_ret, Some params, vararg, attr) -> - if wrap incomplete_type loc env1 ty_ret && not (is_void_type env ty_ret) then + if has_std_alignas genv ty then + error loc "alignment specified for function '%s'" s; + if wrap incomplete_type loc genv ty_ret && not (is_void_type genv ty_ret) then fatal_error loc "incomplete result type %a in function definition" - (print_typ env) ty_ret; + (print_typ genv) ty_ret; (ty_ret, params, vararg, attr) | _ -> fatal_error loc "wrong type for function definition" in - (* Enter function in the environment, for recursive references *) - let (fun_id, sto1, env1, _, _) = - enter_or_refine_ident false loc env1 s sto ty in - let incomplete_param env ty = + (* Enter function in the global environment *) + let (fun_id, sto1, genv, new_ty, _) = + enter_or_refine_function loc genv fun_id sto ty in + add_global_define loc s; + (* Also enter it in the local environment, for recursive references *) + let lenv = Env.add_ident lenv fun_id sto new_ty in + (* Take into account attributes from previous declarations of the function *) + let attr = attributes_of_type genv new_ty in + (* Additional checks on function parameters. They should have a complete type + and additionally they should have an identifier. In both cases a fatal + error is raised in order to avoid problems at later places. *) + let add_param env (id, ty) = if wrap incomplete_type loc env ty then - fatal_error loc "parameter has incomplete type" in - (* Enter parameters and extra declarations in the environment *) - let env2 = - List.fold_left (fun e (id, ty) -> incomplete_param e ty; - Env.add_ident e id Storage_default ty) - (Env.new_scope env1) params in - let env2 = + fatal_error loc "parameter has incomplete type"; + if id.C.name = "" then + fatal_error loc "parameter name omitted"; + Env.add_ident env id Storage_default ty + in + (* Enter parameters and extra declarations in the local environment. + For K&R functions this hasn't been done yet. + For prototyped functions this has been done by [elab_fundef_name] + already, but some parameter may have been shadowed by the + function name, while it should be the other way around, e.g. + [int f(int f) { return f+1; }], with [f] refering to the + parameter [f] and not to the function [f] within the body of the + function. *) + let lenv = + List.fold_left add_param lenv params in + let lenv = List.fold_left (fun e (sto, id, ty, init) -> Env.add_ident e id sto ty) - env2 extra_decls in - (* Define "__func__" and enter it in the environment *) + lenv extra_decls in + (* Define "__func__" and enter it in the local environment *) let (func_ty, func_init) = __func__type_and_init s in - let (func_id, _, env3, func_ty, _) = - enter_or_refine_ident true loc env2 "__func__" Storage_static func_ty in - emit_elab ~debuginfo:false env3 loc + let (func_id, _, lenv, func_ty, _) = + enter_or_refine_ident true loc lenv "__func__" Storage_static func_ty in + emit_elab ~debuginfo:false lenv loc (Gdecl(Storage_static, func_id, func_ty, Some func_init)); (* Elaborate function body *) - let body1 = !elab_funbody_f ty_ret vararg env3 body in + let body1 = !elab_funbody_f ty_ret vararg (inline && sto <> Storage_static) + lenv body in (* Analyse it for returns *) - let (can_return, can_fallthrough) = Cflow.function_returns env3 body1 in + let (can_return, can_fallthrough) = Cflow.function_returns lenv body1 in (* Special treatment of the "main" function. *) let body2 = if s = "main" then begin @@ -2365,7 +2658,7 @@ let elab_fundef env spec name defs body loc = error loc "'main' is not allowed to be declared inline"; if noret then warning loc Unnamed "'main' is not allowed to be declared _Noreturn"; - match unroll env ty_ret with + match unroll genv ty_ret with | TInt(IInt, []) -> (* Add implicit "return 0;" at end of function body. If we trusted the return analysis, we would do this only if @@ -2378,7 +2671,7 @@ let elab_fundef env spec name defs body loc = end else begin (* For non-"main" functions, warn if the body can fall through and the return type is not "void". *) - if can_fallthrough && not (is_void_type env ty_ret) then + if can_fallthrough && not (is_void_type genv ty_ret) then warning loc Return_type "control reaches end of non-void function"; body1 end in @@ -2407,12 +2700,13 @@ let elab_fundef env spec name defs body loc = fd_vararg = vararg; fd_locals = []; fd_body = body3 } in - emit_elab ~linkage:true env1 loc (Gfundef fn); - env1 + emit_elab ~linkage:true genv loc (Gfundef fn); + genv (* Definitions *) -let rec elab_definition (local: bool) (env: Env.t) (def: Cabs.definition) +let elab_definition (for_loop: bool) (local: bool) (nonstatic_inline: bool) + (env: Env.t) (def: Cabs.definition) : decl list * Env.t = match def with (* "int f(int x) { ... }" *) @@ -2425,44 +2719,32 @@ let rec elab_definition (local: bool) (env: Env.t) (def: Cabs.definition) (* "int x = 12, y[10], *z" *) | DECDEF(init_name_group, loc) -> let ((dl, env1), sto, tydef) = - elab_init_name_group false loc env init_name_group in + elab_init_name_group loc env init_name_group in + if for_loop then begin + let fun_declaration = List.exists (fun (_, ty, _) -> is_function_type env ty) dl in + if fun_declaration || sto = Storage_extern || sto = Storage_static || tydef then + error loc "declaration of non-local variable in 'for' loop" ; + end; if tydef then let env2 = enter_typedefs loc env1 sto dl in ([], env2) else - enter_decdefs local loc env1 sto dl + enter_decdefs local nonstatic_inline loc env1 sto dl (* pragma *) | PRAGMA(s, loc) -> emit_elab env loc (Gpragma s); ([], env) -and elab_definitions local env = function - | [] -> ([], env) - | d1 :: dl -> - let (decl1, env1) = elab_definition local env d1 in - let (decl2, env2) = elab_definitions local env1 dl in - (decl1 @ decl2, env2) - (* Extended asm *) -let elab_asm_operand vararg loc env (ASMOPERAND(label, wide, chars, e)) = +let elab_asm_operand ctx loc env (ASMOPERAND(label, wide, chars, e)) = let s = elab_simple_string loc wide chars in - let e',env = elab_expr vararg loc env e in + let e',env = elab_expr ctx loc env e in (label, s, e'),env -(* Contexts for elaborating statements *) - -module StringSet = Set.Make(String) - -type stmt_context = { - ctx_return_typ: typ; (**r return type for the function *) - ctx_labels: StringSet.t; (**r all labels defined in the function *) - ctx_break: bool; (**r is 'break' allowed? *) - ctx_continue: bool; (**r is 'continue' allowed? *) - ctx_vararg: bool; (**r is this a vararg function? *) -} +(* Operations over contexts *) let stmt_labels stmt = let lbls = ref StringSet.empty in @@ -2487,7 +2769,48 @@ let stmt_labels stmt = let ctx_loop ctx = { ctx with ctx_break = true; ctx_continue = true } -let ctx_switch ctx = { ctx with ctx_break = true } +let ctx_switch ctx = { ctx with ctx_break = true; ctx_in_switch = true } + +(* Check the uniqueness of 'case' and 'default' in a 'switch' *) + +module Int64Set = Set.Make(Int64) + +let check_switch_cases switch_body = + let cases = ref Int64Set.empty + and default = ref false in + let rec check s = + match s.sdesc with + | Sskip -> () + | Sdo _ -> () + | Sseq(s1, s2) -> check s1; check s2 + | Sif(_, s1, s2) -> check s1; check s2 + | Swhile(_, s1) -> check s1 + | Sdowhile(s1, _) -> check s1 + | Sfor(s1, _, s2, s3) -> check s1; check s2; check s3 + | Sbreak -> () + | Scontinue -> () + | Sswitch(_, _) -> () (* already checked during elaboration of this switch *) + | Slabeled(lbl, s1) -> + begin match lbl with + | Slabel _ -> () + | Scase(_, n) -> + if Int64Set.mem n !cases then + Diagnostics.error s.sloc "duplicate case value '%Ld'" n + else + cases := Int64Set.add n !cases + | Sdefault -> + if !default then + Diagnostics.error s.sloc "multiple default labels in one switch" + else + default := true + end; + check s1 + | Sgoto _ -> () + | Sreturn _ -> () + | Sblock sl -> List.iter check sl + | Sdecl _ -> () + | Sasm _ -> () + in check switch_body (* Elaboration of statements *) @@ -2498,7 +2821,7 @@ let rec elab_stmt env ctx s = (* 6.8.3 Expression statements *) | COMPUTATION(a, loc) -> - let a,env = (elab_expr ctx.ctx_vararg loc env a) in + let a,env = elab_expr ctx loc env a in { sdesc = Sdo a; sloc = elab_loc loc },env (* 6.8.1 Labeled statements *) @@ -2508,16 +2831,20 @@ let rec elab_stmt env ctx s = { sdesc = Slabeled(Slabel lbl, s1); sloc = elab_loc loc },env | CASE(a, s1, loc) -> - let a',env = elab_expr ctx.ctx_vararg loc env a in - begin match Ceval.integer_expr env a' with + if not ctx.ctx_in_switch then + error loc "'case' statement not in switch statement"; + let a',env = elab_expr ctx loc env a in + let n = + match Ceval.integer_expr env a' with | None -> - error loc "expression of 'case' label is not an integer constant expression" - | Some n -> () - end; + error loc "expression of 'case' label is not an integer constant expression"; 0L + | Some n -> n in let s1,env = elab_stmt env ctx s1 in - { sdesc = Slabeled(Scase a', s1); sloc = elab_loc loc },env + { sdesc = Slabeled(Scase(a', n), s1); sloc = elab_loc loc },env | DEFAULT(s1, loc) -> + if not ctx.ctx_in_switch then + error loc "'case' statement not in switch statement"; let s1,env = elab_stmt env ctx s1 in { sdesc = Slabeled(Sdefault, s1); sloc = elab_loc loc },env @@ -2529,7 +2856,7 @@ let rec elab_stmt env ctx s = (* 6.8.4 Conditional statements *) | If(a, s1, s2, loc) -> - let a',env = elab_expr ctx.ctx_vararg loc env a in + let a',env = elab_expr ctx loc env a in if not (is_scalar_type env a'.etyp) then error loc "controlling expression of 'if' does not have scalar type (%a invalid)" (print_typ env) a'.etyp; @@ -2544,7 +2871,7 @@ let rec elab_stmt env ctx s = (* 6.8.5 Iterative statements *) | WHILE(a, s1, loc) -> - let a',env = elab_expr ctx.ctx_vararg loc env a in + let a',env = elab_expr ctx loc env a in if not (is_scalar_type env a'.etyp) then error loc "controlling expression of 'while' does not have scalar type (%a invalid)" (print_typ env) a'.etyp; @@ -2553,7 +2880,7 @@ let rec elab_stmt env ctx s = | DOWHILE(a, s1, loc) -> let s1',env = elab_stmt env (ctx_loop ctx) s1 in - let a',env = elab_expr ctx.ctx_vararg loc env a in + let a',env = elab_expr ctx loc env a in if not (is_scalar_type env a'.etyp) then error loc "controlling expression of 'while' does not have scalar type (%a invalid)" (print_typ env) a'.etyp; @@ -2563,24 +2890,25 @@ let rec elab_stmt env ctx s = let (a1', env_decls, decls') = match fc with | Some (FC_EXP a1) -> - let a1,env = elab_for_expr ctx.ctx_vararg loc env (Some a1) in + let a1,env = elab_for_expr ctx loc env (Some a1) in (a1, env, None) | None -> - let a1,env = elab_for_expr ctx.ctx_vararg loc env None in + let a1,env = elab_for_expr ctx loc env None in (a1, env, None) | Some (FC_DECL def) -> - let (dcl, env') = elab_definition true (Env.new_scope env) def in + let (dcl, env') = elab_definition true true ctx.ctx_nonstatic_inline + (Env.new_scope env) def in let loc = elab_loc (Cabshelper.get_definitionloc def) in (sskip, env', Some(List.map (fun d -> {sdesc = Sdecl d; sloc = loc}) dcl)) in let a2',env_test = match a2 with | None -> intconst 1L IInt,env_decls - | Some a2 -> elab_expr ctx.ctx_vararg loc env_decls a2 + | Some a2 -> elab_expr ctx loc env_decls a2 in if not (is_scalar_type env_test a2'.etyp) then error loc "controlling expression of 'for' does not have scalar type (%a invalid)" (print_typ env) a2'.etyp; - let a3',env_for = elab_for_expr ctx.ctx_vararg loc env_test a3 in + let a3',env_for = elab_for_expr ctx loc env_test a3 in let s1',env_body = elab_stmt env_for (ctx_loop ctx) s1 in let sfor = { sdesc = Sfor(a1', a2', a3', s1'); sloc = elab_loc loc } in begin match decls' with @@ -2590,11 +2918,12 @@ let rec elab_stmt env ctx s = (* 6.8.4 Switch statement *) | SWITCH(a, s1, loc) -> - let a',env = elab_expr ctx.ctx_vararg loc env a in + let a',env = elab_expr ctx loc env a in if not (is_integer_type env a'.etyp) then error loc "controlling expression of 'switch' does not have integer type (%a invalid)" (print_typ env) a'.etyp; let s1',env = elab_stmt env (ctx_switch ctx) s1 in + check_switch_cases s1'; { sdesc = Sswitch(a', s1'); sloc = elab_loc loc },env (* 6.8.6 Break and continue statements *) @@ -2609,7 +2938,7 @@ let rec elab_stmt env ctx s = (* 6.8.6 Return statements *) | RETURN(a, loc) -> - let a',env = elab_opt_expr ctx.ctx_vararg loc env a in + let a',env = elab_opt_expr ctx loc env a in begin match (unroll env ctx.ctx_return_typ, a') with | TVoid _, None -> () | TVoid _, Some _ -> @@ -2628,7 +2957,7 @@ let rec elab_stmt env ctx s = (print_typ env) b.etyp (print_typ env) ctx.ctx_return_typ else warning loc Unnamed - "incompatible conversion returning %a from a function with result type %a" + "incompatible conversion: returning %a from a function with result type %a" (print_typ env) b.etyp (print_typ env) ctx.ctx_return_typ else error loc @@ -2652,8 +2981,13 @@ let rec elab_stmt env ctx s = | ASM(cv_specs, wide, chars, outputs, inputs, flags, loc) -> let a = elab_cvspecs env cv_specs in let s = elab_simple_string loc wide chars in - let outputs,env = mmap (elab_asm_operand ctx.ctx_vararg loc) env outputs in - let inputs ,env= mmap (elab_asm_operand ctx.ctx_vararg loc) env inputs in + let outputs,env = mmap (elab_asm_operand ctx loc) env outputs in + List.iter + (fun (lbl, cst, e) -> + if not (is_modifiable_lvalue env e) then + error loc "asm output is not a modifiable l-value";) + outputs; + let inputs ,env= mmap (elab_asm_operand ctx loc) env inputs in let flags = List.map (fun (w,c) -> elab_simple_string loc w c) flags in { sdesc = Sasm(a, s, outputs, inputs, flags); sloc = elab_loc loc },env @@ -2672,7 +3006,8 @@ and elab_block_body env ctx sl = | [] -> [],env | DEFINITION def :: sl1 -> - let (dcl, env') = elab_definition true env def in + let (dcl, env') = + elab_definition false true ctx.ctx_nonstatic_inline env def in let loc = elab_loc (Cabshelper.get_definitionloc def) in let dcl = List.map (fun ((sto,id,ty,_) as d) -> Debug.insert_local_declaration sto id ty loc; @@ -2686,14 +3021,24 @@ and elab_block_body env ctx sl = (* Elaboration of a function body. Return the corresponding C statement. *) -let elab_funbody return_typ vararg env b = +let elab_funbody return_typ vararg nonstatic_inline env b = let ctx = { ctx_return_typ = return_typ; ctx_labels = stmt_labels b; ctx_break = false; ctx_continue = false; - ctx_vararg = vararg;} in - fst(elab_stmt env ctx b) + ctx_in_switch = false; + ctx_vararg = vararg; + ctx_nonstatic_inline = nonstatic_inline } in + (* The function body appears as a block in the AST but should not create + a new scope. Instead, the scope used for function parameters must be + used for the body. *) + match b with + | BLOCK (b,loc) -> + let b',_ = elab_block_body env ctx b in + { sdesc = Sblock b'; sloc = elab_loc loc } + | _ -> + assert false (* Filling in forward declaration *) let _ = elab_funbody_f := elab_funbody @@ -2703,7 +3048,9 @@ let _ = elab_funbody_f := elab_funbody let elab_file prog = reset(); - ignore (elab_definitions false (Builtins.environment()) prog); + let env = Builtins.environment () in + let elab_def env d = snd (elab_definition false false false env d) in + ignore (List.fold_left elab_def env prog); let p = elaborated_program () in Checks.unused_variables p; Checks.unknown_attrs_program p; diff --git a/cparser/ExtendedAsm.ml b/cparser/ExtendedAsm.ml index 6cd95aec..257e9cf7 100644 --- a/cparser/ExtendedAsm.ml +++ b/cparser/ExtendedAsm.ml @@ -73,7 +73,7 @@ let set_label_const lbl pos n subst = let is_reg_pair env ty = match unroll env ty with - | TInt(ik, _) -> sizeof_ikind ik > !config.sizeof_ptr + | TInt(ik, _) -> sizeof_ikind ik > !config.sizeof_intreg | _ -> false (* Transform the input operands: @@ -126,8 +126,6 @@ let transf_outputs loc env = function | [] -> (None, [], StringMap.empty, 0, 0) | [(lbl, cstr, e)] -> - if not (is_modifiable_lvalue env e) then - error loc "asm output is not a modifiable l-value"; let valid = Str.string_match re_valid_output cstr 0 in if valid && String.contains cstr 'r' then if is_reg_pair env e.etyp then diff --git a/cparser/GNUmakefile b/cparser/GNUmakefile index a2646c7b..ce326463 100644 --- a/cparser/GNUmakefile +++ b/cparser/GNUmakefile @@ -164,11 +164,11 @@ concrete: $(DATABASE).raw deLexer # We declare a type name "t", which the de-lexer uses as a type name. @ f=0 ; \ while read -r line ; do \ - filename=`printf "tests/generated/%03d.c" $$f` ; \ + filename=`printf "tests/generated/parser_%03d.c" $$f` ; \ rm -f $$filename ; \ echo "typedef int t;" >> $$filename ; \ echo "$$line" \ - | $(CUT) --fields="1" --delimiter=" " --complement \ + | $(CUT) -f 2- -d " " \ | ./deLexer \ >> $$filename ; \ f=$$((f+1)) ; \ diff --git a/cparser/Lexer.mll b/cparser/Lexer.mll index cf8788c5..b2a668f0 100644 --- a/cparser/Lexer.mll +++ b/cparser/Lexer.mll @@ -21,7 +21,7 @@ open Pre_parser_aux module SSet = Set.Make(String) let lexicon : (string, Cabs.cabsloc -> token) Hashtbl.t = Hashtbl.create 17 -let ignored_keyworkds : SSet.t ref = ref SSet.empty +let ignored_keywords : SSet.t ref = ref SSet.empty let () = List.iter (fun (key, builder) -> Hashtbl.add lexicon key builder) @@ -85,7 +85,7 @@ let () = ("while", fun loc -> WHILE loc)]; if Configuration.system <> "diab" then (* We can ignore the __extension__ GCC keyword. *) - ignored_keyworkds := SSet.add "__extension__" !ignored_keyworkds + ignored_keywords := SSet.add "__extension__" !ignored_keywords let init_ctx = SSet.singleton "__builtin_va_list" let types_context : SSet.t ref = ref init_ctx @@ -135,7 +135,7 @@ let error lb fmt = let warning lb fmt = Diagnostics.warning - (lb.lex_curr_p.pos_fname,lb.lex_curr_p.pos_lnum) Diagnostics.Unnamed ("warning: " ^^ fmt) + (lb.lex_curr_p.pos_fname,lb.lex_curr_p.pos_lnum) Diagnostics.Unnamed fmt (* Simple character escapes *) @@ -329,7 +329,7 @@ rule initial = parse | "," { COMMA(currentLoc lexbuf) } | "." { DOT(currentLoc lexbuf) } | identifier as id { - if SSet.mem id !ignored_keyworkds then + if SSet.mem id !ignored_keywords then initial lexbuf else try Hashtbl.find lexicon id (currentLoc lexbuf) diff --git a/cparser/Machine.ml b/cparser/Machine.ml index bd524cf8..28c6f8a6 100644 --- a/cparser/Machine.ml +++ b/cparser/Machine.ml @@ -44,6 +44,7 @@ type t = { wchar_signed: bool; sizeof_size_t: int; sizeof_ptrdiff_t: int; + sizeof_intreg: int; alignof_ptr: int; alignof_short: int; alignof_int: int; @@ -78,6 +79,7 @@ let ilp32ll64 = { wchar_signed = true; sizeof_size_t = 4; sizeof_ptrdiff_t = 4; + sizeof_intreg = 4; alignof_ptr = 4; alignof_short = 2; alignof_int = 4; @@ -112,6 +114,7 @@ let i32lpll64 = { wchar_signed = true; sizeof_size_t = 8; sizeof_ptrdiff_t = 8; + sizeof_intreg = 8; alignof_ptr = 8; alignof_short = 2; alignof_int = 4; @@ -146,6 +149,7 @@ let il32pll64 = { wchar_signed = true; sizeof_size_t = 8; sizeof_ptrdiff_t = 8; + sizeof_intreg = 8; alignof_ptr = 8; alignof_short = 2; alignof_int = 4; @@ -202,11 +206,20 @@ let ppc_32_bigendian = struct_passing_style = SP_ref_caller; struct_return_style = SR_int1to8; } +let ppc_32_r64_bigendian = + { ppc_32_bigendian with sizeof_intreg = 8;} + let ppc_32_diab_bigendian = { ppc_32_bigendian with sizeof_wchar = 2; wchar_signed = false } +let ppc_32_r64_diab_bigendian = + { ppc_32_diab_bigendian with sizeof_intreg = 8;} + let ppc_32_linux_bigendian = {ppc_32_bigendian with struct_return_style = SR_ref;} +let ppc_32_r64_linux_bigendian = + { ppc_32_linux_bigendian with sizeof_intreg = 8;} + let arm_littleendian = { ilp32ll64 with name = "arm"; struct_passing_style = SP_split_args; struct_return_style = SR_int1to4;} @@ -260,6 +273,7 @@ let undef = { wchar_signed = true; sizeof_size_t = 0; sizeof_ptrdiff_t = 0; + sizeof_intreg = 0; alignof_ptr = 0; alignof_short = 0; alignof_int = 0; diff --git a/cparser/Machine.mli b/cparser/Machine.mli index 32f9a4de..56d8d0b9 100644 --- a/cparser/Machine.mli +++ b/cparser/Machine.mli @@ -43,6 +43,7 @@ type t = { wchar_signed: bool; sizeof_size_t: int; sizeof_ptrdiff_t: int; + sizeof_intreg: int; alignof_ptr: int; alignof_short: int; alignof_int: int; @@ -78,6 +79,9 @@ val win64 : t val ppc_32_bigendian : t val ppc_32_diab_bigendian : t val ppc_32_linux_bigendian : t +val ppc_32_r64_bigendian : t +val ppc_32_r64_diab_bigendian : t +val ppc_32_r64_linux_bigendian : t val arm_littleendian : t val arm_bigendian : t val rv32 : t diff --git a/cparser/validator/Alphabet.v b/cparser/MenhirLib/Alphabet.v index a13f69b0..a13f69b0 100644 --- a/cparser/validator/Alphabet.v +++ b/cparser/MenhirLib/Alphabet.v diff --git a/cparser/validator/Automaton.v b/cparser/MenhirLib/Automaton.v index fc995298..fc995298 100644 --- a/cparser/validator/Automaton.v +++ b/cparser/MenhirLib/Automaton.v diff --git a/cparser/validator/Grammar.v b/cparser/MenhirLib/Grammar.v index 8e427cd9..8e427cd9 100644 --- a/cparser/validator/Grammar.v +++ b/cparser/MenhirLib/Grammar.v diff --git a/cparser/validator/Interpreter.v b/cparser/MenhirLib/Interpreter.v index 4ac02693..4ac02693 100644 --- a/cparser/validator/Interpreter.v +++ b/cparser/MenhirLib/Interpreter.v diff --git a/cparser/validator/Interpreter_complete.v b/cparser/MenhirLib/Interpreter_complete.v index f76731d5..2e64b8da 100644 --- a/cparser/validator/Interpreter_complete.v +++ b/cparser/MenhirLib/Interpreter_complete.v @@ -220,7 +220,7 @@ Lemma ptlz_past_ptlz_prod: (ptlz:ptl_zipper hole_symbs hole_word hole_sems), rev_append hole_symbs (ptlz_past ptlz) = prod_rhs_rev (ptlz_prod ptlz). Proof. -fix 4. +fix ptlz_past_ptlz_prod 4. destruct ptlz; simpl. rewrite <- rev_alt, rev_involutive; reflexivity. apply (ptlz_past_ptlz_prod _ _ _ ptlz). @@ -298,7 +298,7 @@ Lemma build_pt_dot_cost: (ptlz:ptl_zipper hole_symbs hole_word hole_sems), ptd_cost (build_pt_dot ptl ptlz) = ptl_size ptl + ptlz_cost ptlz. Proof. -fix 4. +fix build_pt_dot_cost 4. destruct ptl; intros. reflexivity. destruct p. @@ -313,7 +313,7 @@ Lemma build_pt_dot_buffer: (ptlz:ptl_zipper hole_symbs hole_word hole_sems), ptd_buffer (build_pt_dot ptl ptlz) = hole_word ++ ptlz_buffer ptlz. Proof. -fix 4. +fix build_pt_dot_buffer 4. destruct ptl; intros. reflexivity. destruct p. @@ -330,7 +330,7 @@ Lemma ptd_stack_compat_build_pt_dot: ptlz_stack_compat ptlz stack -> ptd_stack_compat (build_pt_dot ptl ptlz) stack. Proof. -fix 4. +fix ptd_stack_compat_build_pt_dot 4. destruct ptl; intros. eauto. destruct p. @@ -375,7 +375,7 @@ Lemma pop_ptlz_cost: let 'existT _ word (existT _ sem (ptz, pt)) := pop_ptlz ptl ptlz in ptlz_cost ptlz = ptz_cost ptz. Proof. -fix 5. +fix pop_ptlz_cost 5. destruct ptlz. reflexivity. simpl; apply pop_ptlz_cost. @@ -388,7 +388,7 @@ Lemma pop_ptlz_buffer: let 'existT _ word (existT _ sem (ptz, pt)) := pop_ptlz ptl ptlz in ptlz_buffer ptlz = ptz_buffer ptz. Proof. -fix 5. +fix pop_ptlz_buffer 5. destruct ptlz. reflexivity. simpl; apply pop_ptlz_buffer. @@ -428,7 +428,7 @@ Lemma pop_ptlz_pop_stack_compat: end. Proof. Opaque AlphabetComparable AlphabetComparableUsualEq. -fix 5. +fix pop_ptlz_pop_stack_compat 5. destruct ptlz. intros; simpl. split. apply H. @@ -591,7 +591,7 @@ Lemma parse_fix_complete: | Err => True end. Proof. -fix 3. +fix parse_fix_complete 3. destruct n_steps; intros; simpl. apply Nat.lt_0_succ. apply step_next_ptd in H. diff --git a/cparser/validator/Interpreter_correct.v b/cparser/MenhirLib/Interpreter_correct.v index 1263d4e3..1263d4e3 100644 --- a/cparser/validator/Interpreter_correct.v +++ b/cparser/MenhirLib/Interpreter_correct.v diff --git a/cparser/validator/Interpreter_safe.v b/cparser/MenhirLib/Interpreter_safe.v index a1aa35b8..a1aa35b8 100644 --- a/cparser/validator/Interpreter_safe.v +++ b/cparser/MenhirLib/Interpreter_safe.v diff --git a/cparser/validator/Main.v b/cparser/MenhirLib/Main.v index 1a17e988..1a17e988 100644 --- a/cparser/validator/Main.v +++ b/cparser/MenhirLib/Main.v diff --git a/cparser/validator/Tuples.v b/cparser/MenhirLib/Tuples.v index 3fd2ec03..3fd2ec03 100644 --- a/cparser/validator/Tuples.v +++ b/cparser/MenhirLib/Tuples.v diff --git a/cparser/validator/Validator_complete.v b/cparser/MenhirLib/Validator_complete.v index a9823278..a9823278 100644 --- a/cparser/validator/Validator_complete.v +++ b/cparser/MenhirLib/Validator_complete.v diff --git a/cparser/validator/Validator_safe.v b/cparser/MenhirLib/Validator_safe.v index 183d661b..183d661b 100644 --- a/cparser/validator/Validator_safe.v +++ b/cparser/MenhirLib/Validator_safe.v diff --git a/cparser/PackedStructs.ml b/cparser/PackedStructs.ml index e1287eb8..a2c91c0a 100644 --- a/cparser/PackedStructs.ml +++ b/cparser/PackedStructs.ml @@ -81,47 +81,33 @@ let transf_field_decl mfa swapped loc env struct_id f = (* Rewriting struct declarations *) let transf_struct_decl mfa msa swapped loc env struct_id attrs ml = + let attrs' = + remove_custom_attributes ["packed";"__packed__"] attrs in let ml' = List.map (transf_field_decl mfa swapped loc env struct_id) ml in - if msa = 0 then (attrs, ml') else begin - let al' = (* natural alignment of the transformed struct *) - List.fold_left - (fun a f' -> max a (safe_alignof loc env f'.fld_typ)) - 1 ml' in - (set_alignas_attr (max msa al') attrs, ml') + if msa = 0 then (attrs', ml') else begin + (* [Cutil.composite_info_def] takes packing parameters into account. + Hence the alignment it returns is the correct alignment for + the transformed struct. *) + let ci = Cutil.composite_info_def env Struct attrs ml in + match ci.ci_alignof with + | None -> error loc "incomplete struct"; (attrs', ml') + | Some al -> (set_alignas_attr al attrs', ml') end (* Rewriting composite declarations *) -let is_pow2 n = n > 0 && n land (n - 1) = 0 - -let packed_param_value loc n = - let m = Int64.to_int n in - if n <> Int64.of_int m then - (error loc "__packed__ parameter `%Ld' is too large" n; 0) - else if m = 0 || is_pow2 m then - m - else - (error loc "__packed__ parameter `%Ld' must be a power of 2" n; 0) - let transf_composite loc env su id attrs ml = match su with | Union -> (attrs, ml) | Struct -> let (mfa, msa, swapped) = match find_custom_attributes ["packed";"__packed__"] attrs with - | [] -> (0L, 0L, false) - | [[]] -> (1L, 0L, false) - | [[AInt n]] -> (n, 0L, false) - | [[AInt n; AInt p]] -> (n, p, false) - | [[AInt n; AInt p; AInt q]] -> (n, p, q <> 0L) - | _ -> - error loc "ill-formed or ambiguous __packed__ attribute"; - (0L, 0L, false) in - let mfa = packed_param_value loc mfa in - let msa = packed_param_value loc msa in - let attrs' = remove_custom_attributes ["packed";"__packed__"] attrs in - transf_struct_decl mfa msa swapped loc env id attrs' ml + | [] -> (0, 0, false) + | [_] -> Cutil.packing_parameters attrs + | _ -> error loc "multiple __packed__ attributes"; + (0, 0, false) in + transf_struct_decl mfa msa swapped loc env id attrs ml (* Accessor functions *) diff --git a/cparser/Parse.ml b/cparser/Parse.ml index b2c83698..154e3dcf 100644 --- a/cparser/Parse.ml +++ b/cparser/Parse.ml @@ -69,7 +69,7 @@ let preprocessed_file transfs name sourcefile = | Parser.Parser.Inter.Fail_pr -> (* Theoretically impossible : implies inconsistencies between grammars. *) - Diagnostics.fatal_error Diagnostics.no_loc "Internal error while parsing" + Diagnostics.fatal_error Diagnostics.no_loc "internal error while parsing" | Parser.Parser.Inter.Timeout_pr -> assert false | Parser.Parser.Inter.Parsed_pr (ast, _ ) -> ast) in let p1 = Timing.time "Elaboration" Elab.elab_file ast in diff --git a/cparser/Parser.vy b/cparser/Parser.vy index 7fe686f1..79e3793d 100644 --- a/cparser/Parser.vy +++ b/cparser/Parser.vy @@ -172,10 +172,8 @@ unary_expression: | loc = SIZEOF LPAREN typ = type_name RPAREN { (TYPE_SIZEOF typ, loc) } (* Non-standard *) -| loc = ALIGNOF expr = unary_expression - { (EXPR_ALIGNOF (fst expr), loc) } | loc = ALIGNOF LPAREN typ = type_name RPAREN - { (TYPE_ALIGNOF typ, loc) } + { (ALIGNOF typ, loc) } unary_operator: | loc = AND @@ -546,7 +544,7 @@ attribute_specifier: | loc = ALIGNAS LPAREN args = argument_expression_list RPAREN { (ALIGNAS_ATTR (rev' args) loc, loc) } | loc = ALIGNAS LPAREN typ = type_name RPAREN - { (ALIGNAS_ATTR [TYPE_ALIGNOF typ] loc, loc) } + { (ALIGNAS_ATTR [ALIGNOF typ] loc, loc) } gcc_attribute_list: | a = gcc_attribute @@ -562,7 +560,7 @@ gcc_attribute: | w = gcc_attribute_word LPAREN RPAREN { GCC_ATTR_ARGS w [] } | w = gcc_attribute_word LPAREN args = argument_expression_list RPAREN - { GCC_ATTR_ARGS w args } + { GCC_ATTR_ARGS w (rev' args) } gcc_attribute_word: | i = OTHER_NAME diff --git a/cparser/Rename.ml b/cparser/Rename.ml index d63fa47d..eb31eaf0 100644 --- a/cparser/Rename.ml +++ b/cparser/Rename.ml @@ -188,7 +188,7 @@ and stmt_or_decl env s = (stmt env s, env) and slabel env = function - | Scase e -> Scase(exp env e) + | Scase(e, n) -> Scase(exp env e, n) | sl -> sl let fundef env f = diff --git a/cparser/Unblock.ml b/cparser/Unblock.ml index 5df2e2cf..da8049a5 100644 --- a/cparser/Unblock.ml +++ b/cparser/Unblock.ml @@ -31,7 +31,7 @@ let rec local_initializer env path init k = let (ty_elt, sz) = match unroll env path.etyp with | TArray(ty_elt, Some sz, _) -> (ty_elt, sz) - | _ -> Diagnostics.fatal_error Diagnostics.no_loc "Wrong type for array initializer" in + | _ -> Diagnostics.fatal_error Diagnostics.no_loc "wrong type for array initializer" in let rec array_init pos il = if pos >= sz then k else begin let (i1, il') = diff --git a/cparser/deLexer.ml b/cparser/deLexer.ml index 3aa168da..de0e9b6e 100644 --- a/cparser/deLexer.ml +++ b/cparser/deLexer.ml @@ -115,6 +115,7 @@ let delex (symbol : string) : string = | "COMMA" -> "," | "DOT" -> "." | "PRAGMA" -> "#pragma \n" + | "BUILTIN_OFFSETOF" -> "__builtin_offsetof" | "EOF" -> "" (* this should be ok *) | _ -> raise Not_found (* this should not happen *) diff --git a/cparser/handcrafted.messages b/cparser/handcrafted.messages index 567fdd6b..95077739 100644 --- a/cparser/handcrafted.messages +++ b/cparser/handcrafted.messages @@ -181,7 +181,7 @@ translation_unit_file: ALIGNAS LPAREN INT XOR_ASSIGN ## -## Ends in an error in state: 341. +## Ends in an error in state: 314. ## ## attribute_specifier -> ALIGNAS LPAREN type_name . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED NORETURN MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ] ## @@ -192,9 +192,9 @@ translation_unit_file: ALIGNAS LPAREN INT XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 156, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) -## In state 330, spurious reduction of production option(abstract_declarator(type_name)) -> -## In state 336, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) +## In state 67, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) +## In state 306, spurious reduction of production option(abstract_declarator(type_name)) -> +## In state 312, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) ## # Maybe the type name was not complete, but we have reduced anyway @@ -216,7 +216,6 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ ALIGNOF LPAREN VOID XOR_ASSIGN ## ## Ends in an error in state: 304. ## -## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## unary_expression -> ALIGNOF LPAREN type_name . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## ## The known suffix of the stack is as follows: @@ -226,13 +225,13 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ ALIGNOF LPAREN VOID XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 156, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) -## In state 330, spurious reduction of production option(abstract_declarator(type_name)) -> -## In state 336, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) +## In state 67, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) +## In state 306, spurious reduction of production option(abstract_declarator(type_name)) -> +## In state 312, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) ## translation_unit_file: INT PRE_NAME VAR_NAME EQ SIZEOF LPAREN VOID XOR_ASSIGN ## -## Ends in an error in state: 389. +## Ends in an error in state: 388. ## ## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## unary_expression -> SIZEOF LPAREN type_name . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -244,9 +243,9 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ SIZEOF LPAREN VOID XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 156, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) -## In state 330, spurious reduction of production option(abstract_declarator(type_name)) -> -## In state 336, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) +## In state 67, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) +## In state 306, spurious reduction of production option(abstract_declarator(type_name)) -> +## In state 312, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) ## Ill-formed use of $2. @@ -259,7 +258,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME VAR_NAME COMMA VOID XOR_ASSIGN ## -## Ends in an error in state: 353. +## Ends in an error in state: 333. ## ## postfix_expression -> BUILTIN_VA_ARG LPAREN assignment_expression COMMA type_name . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -270,9 +269,9 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME V ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 156, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) -## In state 330, spurious reduction of production option(abstract_declarator(type_name)) -> -## In state 336, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) +## In state 67, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) +## In state 306, spurious reduction of production option(abstract_declarator(type_name)) -> +## In state 312, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) ## Ill-formed use of __builtin_va_arg. @@ -285,7 +284,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ INC LPAREN VOID XOR_ASSIGN ## -## Ends in an error in state: 383. +## Ends in an error in state: 363. ## ## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -296,9 +295,9 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ INC LPAREN VOID XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 156, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) -## In state 330, spurious reduction of production option(abstract_declarator(type_name)) -> -## In state 336, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) +## In state 67, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) +## In state 306, spurious reduction of production option(abstract_declarator(type_name)) -> +## In state 312, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) ## # gcc simply says it expects a closing parenthesis, @@ -314,7 +313,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN VOID XOR_ASSIGN ## -## Ends in an error in state: 386. +## Ends in an error in state: 385. ## ## cast_expression -> LPAREN type_name . RPAREN cast_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## postfix_expression -> LPAREN type_name . RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -326,9 +325,9 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN VOID XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 156, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) -## In state 330, spurious reduction of production option(abstract_declarator(type_name)) -> -## In state 336, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) +## In state 67, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) +## In state 306, spurious reduction of production option(abstract_declarator(type_name)) -> +## In state 312, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) ## # gcc and clang say they expect a closing parenthesis. @@ -342,7 +341,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: ALIGNAS LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 343. +## Ends in an error in state: 316. ## ## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ] ## attribute_specifier -> ALIGNAS LPAREN argument_expression_list . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED NORETURN MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ] @@ -354,21 +353,21 @@ translation_unit_file: ALIGNAS LPAREN PRE_NAME VAR_NAME SEMICOLON ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 143, spurious reduction of production argument_expression_list -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 230, spurious reduction of production argument_expression_list -> assignment_expression ## # We are trying to recognize an alignas specifier. @@ -392,7 +391,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: ALIGNAS LPAREN INT LBRACK RPAREN ## -## Ends in an error in state: 240. +## Ends in an error in state: 151. ## ## direct_abstract_declarator -> option(direct_abstract_declarator) LBRACK option(type_qualifier_list) . optional(assignment_expression,RBRACK) [ RPAREN LPAREN LBRACK COMMA ] ## type_qualifier_list -> option(type_qualifier_list) . type_qualifier_noattr [ VOLATILE TILDE STRING_LITERAL STAR SIZEOF RESTRICT RBRACK PRE_NAME PLUS PACKED MINUS LPAREN INC DEC CONSTANT CONST BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG ATTRIBUTE AND ALIGNOF ALIGNAS ] @@ -514,7 +513,7 @@ At this point, a closing parenthesis ')' is expected. translation_unit_file: ALIGNAS LPAREN INT LPAREN XOR_ASSIGN ## -## Ends in an error in state: 331. +## Ends in an error in state: 307. ## ## direct_abstract_declarator -> LPAREN . save_context abstract_declarator(type_name) RPAREN [ RPAREN LPAREN LBRACK COMMA ] ## direct_abstract_declarator -> LPAREN . option(context_parameter_type_list) RPAREN [ RPAREN LPAREN LBRACK COMMA ] @@ -537,7 +536,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT LPAREN XOR_ASSIGN ## -## Ends in an error in state: 234. +## Ends in an error in state: 145. ## ## direct_abstract_declarator -> LPAREN . save_context abstract_declarator(type_name) RPAREN [ RPAREN LPAREN LBRACK COMMA ] ## direct_abstract_declarator -> LPAREN . option(context_parameter_type_list) RPAREN [ RPAREN LPAREN LBRACK COMMA ] @@ -625,7 +624,7 @@ At this point, an opening parenthesis '(' is expected. translation_unit_file: ATTRIBUTE LPAREN LPAREN COMMA XOR_ASSIGN ## -## Ends in an error in state: 365. +## Ends in an error in state: 345. ## ## gcc_attribute_list -> gcc_attribute_list COMMA . gcc_attribute [ RPAREN COMMA ] ## @@ -647,7 +646,7 @@ At this point, a gcc attribute is expected. translation_unit_file: ATTRIBUTE LPAREN LPAREN RPAREN XOR_ASSIGN ## -## Ends in an error in state: 363. +## Ends in an error in state: 343. ## ## attribute_specifier -> ATTRIBUTE LPAREN LPAREN gcc_attribute_list RPAREN . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED NORETURN MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ] ## @@ -662,7 +661,7 @@ At this point, a second closing parenthesis ')' is expected. translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN RPAREN XOR_ASSIGN ## -## Ends in an error in state: 362. +## Ends in an error in state: 342. ## ## attribute_specifier -> ATTRIBUTE LPAREN LPAREN gcc_attribute_list . RPAREN RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED NORETURN MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ] ## gcc_attribute_list -> gcc_attribute_list . COMMA gcc_attribute [ RPAREN COMMA ] @@ -685,7 +684,7 @@ At this point, one of the following is expected: translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME COMMA PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 358. +## Ends in an error in state: 338. ## ## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ] ## gcc_attribute -> gcc_attribute_word LPAREN typedef_name COMMA argument_expression_list . RPAREN [ RPAREN COMMA ] @@ -697,21 +696,21 @@ translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN PRE_NAME ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 143, spurious reduction of production argument_expression_list -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 230, spurious reduction of production argument_expression_list -> assignment_expression ## # We know for sure that we are parsing a gcc attribute. @@ -729,7 +728,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 357. +## Ends in an error in state: 337. ## ## gcc_attribute -> gcc_attribute_word LPAREN typedef_name COMMA . argument_expression_list RPAREN [ RPAREN COMMA ] ## @@ -746,7 +745,7 @@ At this point, an expression is expected. translation_unit_file: ATTRIBUTE LPAREN LPAREN PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 356. +## Ends in an error in state: 336. ## ## gcc_attribute -> gcc_attribute_word LPAREN typedef_name . COMMA argument_expression_list RPAREN [ RPAREN COMMA ] ## @@ -861,7 +860,7 @@ At this point, two opening parentheses '((' are expected. translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 373. +## Ends in an error in state: 353. ## ## enumerator_list -> enumerator_list COMMA . declare_varname(enumerator) [ RBRACE COMMA ] ## option(COMMA) -> COMMA . [ RBRACE ] @@ -882,7 +881,7 @@ At this point, an enumerator is expected. translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME EQ CONSTANT SEMICOLON ## -## Ends in an error in state: 372. +## Ends in an error in state: 352. ## ## enum_specifier -> ENUM attribute_specifier_list option(other_identifier) LBRACE enumerator_list . option(COMMA) RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] ## enumerator_list -> enumerator_list . COMMA declare_varname(enumerator) [ RBRACE COMMA ] @@ -894,22 +893,22 @@ translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME EQ CONSTANT SEMICOLON ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 67, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 377, spurious reduction of production enumerator -> enumeration_constant EQ conditional_expression -## In state 374, spurious reduction of production declare_varname(enumerator) -> enumerator -## In state 381, spurious reduction of production enumerator_list -> declare_varname(enumerator) +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 154, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 357, spurious reduction of production enumerator -> enumeration_constant EQ conditional_expression +## In state 354, spurious reduction of production declare_varname(enumerator) -> enumerator +## In state 361, spurious reduction of production enumerator_list -> declare_varname(enumerator) ## # # At first sight, it seems that the last enumerator that we have recognized @@ -940,7 +939,7 @@ then at this point, a closing brace '}' is expected. translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME EQ XOR_ASSIGN ## -## Ends in an error in state: 376. +## Ends in an error in state: 356. ## ## enumerator -> enumeration_constant EQ . conditional_expression [ RBRACE COMMA ] ## @@ -955,7 +954,7 @@ At this point, a constant expression is expected. translation_unit_file: ENUM LBRACE PRE_NAME VAR_NAME XOR_ASSIGN ## -## Ends in an error in state: 375. +## Ends in an error in state: 355. ## ## enumerator -> enumeration_constant . [ RBRACE COMMA ] ## enumerator -> enumeration_constant . EQ conditional_expression [ RBRACE COMMA ] @@ -976,7 +975,7 @@ At this point, one of the following is expected: translation_unit_file: ENUM LBRACE XOR_ASSIGN ## -## Ends in an error in state: 370. +## Ends in an error in state: 350. ## ## enum_specifier -> ENUM attribute_specifier_list option(other_identifier) LBRACE . enumerator_list option(COMMA) RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] ## @@ -994,7 +993,7 @@ At this point, an enumerator is expected. translation_unit_file: ENUM XOR_ASSIGN ## -## Ends in an error in state: 368. +## Ends in an error in state: 348. ## ## enum_specifier -> ENUM attribute_specifier_list . option(other_identifier) LBRACE enumerator_list option(COMMA) RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] ## enum_specifier -> ENUM attribute_specifier_list . general_identifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -1023,8 +1022,6 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ ALIGNOF LPAREN XOR_ASSIGN ## ## Ends in an error in state: 65. ## -## postfix_expression -> LPAREN . type_name RPAREN LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] -## primary_expression -> LPAREN . expression RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## unary_expression -> ALIGNOF LPAREN . type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## ## The known suffix of the stack is as follows: @@ -1058,12 +1055,18 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ ALIGNOF XOR_ASSIGN ## ## Ends in an error in state: 64. ## -## unary_expression -> ALIGNOF . unary_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## unary_expression -> ALIGNOF . LPAREN type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## ## The known suffix of the stack is as follows: ## ALIGNOF ## + +Ill-formed use of $0. +At this point, an opening parenthesis '(' is expected, +followed with a type name. + +# ------------------------------------------------------------------------------ + translation_unit_file: INT PRE_NAME VAR_NAME EQ SIZEOF XOR_ASSIGN ## ## Ends in an error in state: 23. @@ -1075,7 +1078,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ SIZEOF XOR_ASSIGN ## SIZEOF ## -# Let's not reveal that _Alignof and sizeof can be used without parentheses. +# Let's not reveal that sizeof can be used without parentheses. # gcc and clang say they expect an expression, which seems both surprising # (they don't request a parenthesis) and incomplete (they don't allow a type name). @@ -1088,7 +1091,7 @@ followed with an expression or a type name. translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 351. +## Ends in an error in state: 331. ## ## postfix_expression -> BUILTIN_VA_ARG LPAREN assignment_expression . COMMA type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1099,20 +1102,20 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME V ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression ## Ill-formed use of $2. @@ -1125,7 +1128,7 @@ then at this point, a comma ',' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ BUILTIN_VA_ARG LPAREN PRE_NAME VAR_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 352. +## Ends in an error in state: 332. ## ## postfix_expression -> BUILTIN_VA_ARG LPAREN assignment_expression COMMA . type_name RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1194,7 +1197,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ INC LPAREN INT RPAREN XOR_ASSIGN ## -## Ends in an error in state: 384. +## Ends in an error in state: 364. ## ## postfix_expression -> LPAREN type_name RPAREN . LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1246,7 +1249,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 338. +## Ends in an error in state: 382. ## ## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ] ## primary_expression -> LPAREN expression . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -1258,21 +1261,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN PRE_NAME VAR_NAME SEMICOL ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## # Since we are saying "if this expression is complete", @@ -1290,7 +1293,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN INT RPAREN LBRACE PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 327. +## Ends in an error in state: 379. ## ## initializer_list -> initializer_list . COMMA option(designation) c_initializer [ RBRACE COMMA ] ## postfix_expression -> LPAREN type_name RPAREN LBRACE initializer_list . option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -1302,22 +1305,22 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN INT RPAREN LBRACE PRE_NAM ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 320, spurious reduction of production c_initializer -> assignment_expression -## In state 326, spurious reduction of production initializer_list -> option(designation) c_initializer +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 372, spurious reduction of production c_initializer -> assignment_expression +## In state 378, spurious reduction of production initializer_list -> option(designation) c_initializer ## # Let's ignore the fact that a comma can precede a closing brace. @@ -1332,7 +1335,7 @@ then at this point, a closing brace '}' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN INT RPAREN LBRACE XOR_ASSIGN ## -## Ends in an error in state: 306. +## Ends in an error in state: 365. ## ## postfix_expression -> LPAREN type_name RPAREN LBRACE . initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1349,7 +1352,7 @@ At this point, an initializer is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LPAREN INT RPAREN XOR_ASSIGN ## -## Ends in an error in state: 387. +## Ends in an error in state: 386. ## ## cast_expression -> LPAREN type_name RPAREN . cast_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## postfix_expression -> LPAREN type_name RPAREN . LBRACE initializer_list option(COMMA) RBRACE [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -1393,7 +1396,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME EQ TILDE XOR_ASSIGN ## -## Ends in an error in state: 66. +## Ends in an error in state: 153. ## ## unary_expression -> unary_operator . cast_expression [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LEQ LEFT_ASSIGN LEFT HAT GT GEQ EQEQ EQ DIV_ASSIGN COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1410,7 +1413,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME AND XOR_ASSIGN ## -## Ends in an error in state: 126. +## Ends in an error in state: 213. ## ## and_expression -> and_expression AND . equality_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION HAT COMMA COLON BARBAR BAR ANDAND AND ] ## @@ -1419,7 +1422,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME AND XOR_ASSIGN ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME ANDAND XOR_ASSIGN ## -## Ends in an error in state: 115. +## Ends in an error in state: 202. ## ## logical_and_expression -> logical_and_expression ANDAND . inclusive_or_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION COMMA COLON BARBAR ANDAND ] ## @@ -1428,7 +1431,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME ANDAND XOR_ASS ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME BAR XOR_ASSIGN ## -## Ends in an error in state: 117. +## Ends in an error in state: 204. ## ## inclusive_or_expression -> inclusive_or_expression BAR . exclusive_or_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION COMMA COLON BARBAR BAR ANDAND ] ## @@ -1437,7 +1440,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME BAR XOR_ASSIGN ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME BARBAR XOR_ASSIGN ## -## Ends in an error in state: 138. +## Ends in an error in state: 225. ## ## logical_or_expression -> logical_or_expression BARBAR . logical_and_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION COMMA COLON BARBAR ] ## @@ -1446,7 +1449,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME BARBAR XOR_ASS ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME HAT XOR_ASSIGN ## -## Ends in an error in state: 119. +## Ends in an error in state: 206. ## ## exclusive_or_expression -> exclusive_or_expression HAT . and_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION HAT COMMA COLON BARBAR BAR ANDAND ] ## @@ -1455,7 +1458,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME HAT XOR_ASSIGN ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LT XOR_ASSIGN ## -## Ends in an error in state: 109. +## Ends in an error in state: 196. ## ## relational_expression -> relational_expression relational_operator . shift_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION NEQ LT LEQ HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ] ## @@ -1464,7 +1467,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LT XOR_ASSIGN ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME NEQ XOR_ASSIGN ## -## Ends in an error in state: 123. +## Ends in an error in state: 210. ## ## equality_expression -> equality_expression equality_operator . relational_expression [ SEMICOLON RPAREN RBRACK RBRACE QUESTION NEQ HAT EQEQ COMMA COLON BARBAR BAR ANDAND AND ] ## @@ -1473,7 +1476,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME NEQ XOR_ASSIGN ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME PLUS XOR_ASSIGN ## -## Ends in an error in state: 102. +## Ends in an error in state: 189. ## ## additive_expression -> additive_expression additive_operator . multiplicative_expression [ SEMICOLON RPAREN RIGHT RBRACK RBRACE QUESTION PLUS NEQ MINUS LT LEQ LEFT HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ] ## @@ -1482,7 +1485,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME PLUS XOR_ASSIG ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME RIGHT XOR_ASSIGN ## -## Ends in an error in state: 91. +## Ends in an error in state: 178. ## ## shift_expression -> shift_expression shift_operator . additive_expression [ SEMICOLON RPAREN RIGHT RBRACK RBRACE QUESTION NEQ LT LEQ LEFT HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ] ## @@ -1491,7 +1494,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME RIGHT XOR_ASSI ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME STAR XOR_ASSIGN ## -## Ends in an error in state: 96. +## Ends in an error in state: 183. ## ## multiplicative_expression -> multiplicative_expression multiplicative_operator . cast_expression [ STAR SLASH SEMICOLON RPAREN RIGHT RBRACK RBRACE QUESTION PLUS PERCENT NEQ MINUS LT LEQ LEFT HAT GT GEQ EQEQ COMMA COLON BARBAR BAR ANDAND AND ] ## @@ -1508,7 +1511,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME XOR_ASSIGN XOR_ASSIGN ## -## Ends in an error in state: 87. +## Ends in an error in state: 174. ## ## assignment_expression -> unary_expression assignment_operator . assignment_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ] ## @@ -1525,7 +1528,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 145. +## Ends in an error in state: 232. ## ## argument_expression_list -> argument_expression_list COMMA . assignment_expression [ RPAREN COMMA ] ## @@ -1546,7 +1549,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME DOT XOR_ASSIGN ## -## Ends in an error in state: 151. +## Ends in an error in state: 238. ## ## postfix_expression -> postfix_expression DOT . general_identifier [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1555,7 +1558,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME DOT XOR_ASSIGN ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME PTR XOR_ASSIGN ## -## Ends in an error in state: 72. +## Ends in an error in state: 159. ## ## postfix_expression -> postfix_expression PTR . general_identifier [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1572,7 +1575,7 @@ At this point, the name of a struct or union member is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LBRACK PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 148. +## Ends in an error in state: 235. ## ## expression -> expression . COMMA assignment_expression [ RBRACK COMMA ] ## postfix_expression -> postfix_expression LBRACK expression . RBRACK [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -1584,21 +1587,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LBRACK PRE_NAM ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## # We know for sure that an array subscript expression has begun, and @@ -1617,7 +1620,7 @@ then at this point, a closing bracket ']' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LBRACK XOR_ASSIGN ## -## Ends in an error in state: 147. +## Ends in an error in state: 234. ## ## postfix_expression -> postfix_expression LBRACK . expression RBRACK [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1632,7 +1635,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 144. +## Ends in an error in state: 231. ## ## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ] ## option(argument_expression_list) -> argument_expression_list . [ RPAREN ] @@ -1644,21 +1647,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LPAREN PRE_NAM ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 143, spurious reduction of production argument_expression_list -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 230, spurious reduction of production argument_expression_list -> assignment_expression ## Up to this point, a list of expressions has been recognized: @@ -1670,7 +1673,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME LPAREN XOR_ASSIGN ## -## Ends in an error in state: 74. +## Ends in an error in state: 161. ## ## postfix_expression -> postfix_expression LPAREN . option(argument_expression_list) RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## @@ -1688,7 +1691,7 @@ followed with a closing parenthesis ')', is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION PRE_NAME VAR_NAME COLON XOR_ASSIGN ## -## Ends in an error in state: 135. +## Ends in an error in state: 222. ## ## conditional_expression -> logical_or_expression QUESTION expression COLON . conditional_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ] ## @@ -1697,7 +1700,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION PRE_N ## translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION XOR_ASSIGN ## -## Ends in an error in state: 113. +## Ends in an error in state: 200. ## ## conditional_expression -> logical_or_expression QUESTION . expression COLON conditional_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ] ## @@ -1712,7 +1715,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 131. +## Ends in an error in state: 218. ## ## conditional_expression -> logical_or_expression QUESTION expression . COLON conditional_expression [ SEMICOLON RPAREN RBRACK RBRACE COMMA COLON ] ## expression -> expression . COMMA assignment_expression [ COMMA COLON ] @@ -1724,21 +1727,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ PRE_NAME VAR_NAME QUESTION PRE_N ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## # gcc and clang simply expect a colon. @@ -1755,7 +1758,7 @@ then at this point, a colon ':' is expected. translation_unit_file: PACKED LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 392. +## Ends in an error in state: 391. ## ## argument_expression_list -> argument_expression_list . COMMA assignment_expression [ RPAREN COMMA ] ## attribute_specifier -> PACKED LPAREN argument_expression_list . RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER RBRACK PRE_NAME PLUS PACKED NORETURN MINUS LPAREN LONG LBRACK LBRACE INT INLINE INC FLOAT EXTERN EQ ENUM DOUBLE DEC CONSTANT CONST COMMA COLON CHAR BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG AUTO ATTRIBUTE AND ALIGNOF ALIGNAS ] @@ -1767,21 +1770,21 @@ translation_unit_file: PACKED LPAREN PRE_NAME VAR_NAME SEMICOLON ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 143, spurious reduction of production argument_expression_list -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 230, spurious reduction of production argument_expression_list -> assignment_expression ## Ill-formed $2 attribute. @@ -1872,7 +1875,7 @@ At this point, one of the following is expected: translation_unit_file: TYPEDEF PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 395. +## Ends in an error in state: 394. ## ## declaration_specifiers_typedef -> TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ] @@ -1885,7 +1888,7 @@ translation_unit_file: TYPEDEF PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## translation_unit_file: PRE_NAME TYPEDEF_NAME TYPEDEF XOR_ASSIGN ## -## Ends in an error in state: 404. +## Ends in an error in state: 403. ## ## declaration_specifiers_typedef -> typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ] @@ -1898,7 +1901,7 @@ translation_unit_file: PRE_NAME TYPEDEF_NAME TYPEDEF XOR_ASSIGN ## translation_unit_file: VOLATILE TYPEDEF PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 414. +## Ends in an error in state: 413. ## ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ] @@ -1911,7 +1914,7 @@ translation_unit_file: VOLATILE TYPEDEF PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## translation_unit_file: VOLATILE PRE_NAME TYPEDEF_NAME TYPEDEF XOR_ASSIGN ## -## Ends in an error in state: 420. +## Ends in an error in state: 419. ## ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ] @@ -1924,7 +1927,7 @@ translation_unit_file: VOLATILE PRE_NAME TYPEDEF_NAME TYPEDEF XOR_ASSIGN ## translation_unit_file: TYPEDEF INT XOR_ASSIGN ## -## Ends in an error in state: 397. +## Ends in an error in state: 396. ## ## declaration_specifiers_typedef -> TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -1934,7 +1937,7 @@ translation_unit_file: TYPEDEF INT XOR_ASSIGN ## translation_unit_file: INT TYPEDEF XOR_ASSIGN ## -## Ends in an error in state: 408. +## Ends in an error in state: 407. ## ## declaration_specifiers_typedef -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -1944,7 +1947,7 @@ translation_unit_file: INT TYPEDEF XOR_ASSIGN ## translation_unit_file: VOLATILE TYPEDEF INT XOR_ASSIGN ## -## Ends in an error in state: 416. +## Ends in an error in state: 415. ## ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -1954,7 +1957,7 @@ translation_unit_file: VOLATILE TYPEDEF INT XOR_ASSIGN ## translation_unit_file: VOLATILE INT TYPEDEF XOR_ASSIGN ## -## Ends in an error in state: 424. +## Ends in an error in state: 423. ## ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) TYPEDEF list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -2007,7 +2010,7 @@ translation_unit_file: TYPEDEF XOR_ASSIGN ## translation_unit_file: VOLATILE TYPEDEF XOR_ASSIGN ## -## Ends in an error in state: 412. +## Ends in an error in state: 411. ## ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2041,7 +2044,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE XOR_ASSIGN ## -## Ends in an error in state: 222. +## Ends in an error in state: 133. ## ## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ] ## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ] @@ -2053,7 +2056,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 214, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr +## In state 125, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr ## # Analogous to the above, except we are in the context of a parameter declaration, @@ -2077,7 +2080,7 @@ At this point, one of the following is expected: translation_unit_file: PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 402. +## Ends in an error in state: 401. ## ## declaration_specifiers(declaration(external_declaration)) -> typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2091,7 +2094,7 @@ translation_unit_file: PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## translation_unit_file: VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 418. +## Ends in an error in state: 417. ## ## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2105,7 +2108,7 @@ translation_unit_file: VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## translation_unit_file: INT XOR_ASSIGN ## -## Ends in an error in state: 406. +## Ends in an error in state: 405. ## ## declaration_specifiers(declaration(external_declaration)) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2116,7 +2119,7 @@ translation_unit_file: INT XOR_ASSIGN ## translation_unit_file: VOLATILE INT XOR_ASSIGN ## -## Ends in an error in state: 422. +## Ends in an error in state: 421. ## ## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2177,7 +2180,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 201. +## Ends in an error in state: 112. ## ## declaration_specifiers(parameter_declaration) -> typedef_name list(declaration_specifier_no_type) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ] @@ -2190,7 +2193,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME TYPEDEF_NAME XOR_AS ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 224. +## Ends in an error in state: 135. ## ## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ] @@ -2203,7 +2206,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE PRE_NAME TYPEDEF_NA ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT XOR_ASSIGN ## -## Ends in an error in state: 207. +## Ends in an error in state: 118. ## ## declaration_specifiers(parameter_declaration) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -2213,7 +2216,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT XOR_ASSIGN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN VOLATILE INT XOR_ASSIGN ## -## Ends in an error in state: 226. +## Ends in an error in state: 137. ## ## declaration_specifiers(parameter_declaration) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR RPAREN PRE_NAME LPAREN LBRACK COMMA ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -2262,7 +2265,7 @@ At this point, one of the following is expected: translation_unit_file: VOLATILE XOR_ASSIGN ## -## Ends in an error in state: 410. +## Ends in an error in state: 409. ## ## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers(declaration(external_declaration)) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2278,7 +2281,7 @@ translation_unit_file: VOLATILE XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 214, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr +## In state 125, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr ## # We have seen some specifiers or qualifiers. We have probably seen at least @@ -2307,7 +2310,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE VOLATILE XOR_ASSIGN ## -## Ends in an error in state: 519. +## Ends in an error in state: 518. ## ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2323,7 +2326,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 214, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr +## In state 125, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr ## # Identical to the previous one, except we are not at the top level, # so we know this cannot be the beginning of a function definition. @@ -2338,7 +2341,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME TYPEDEF_NAME VOLATILE XOR_ASSIGN ## -## Ends in an error in state: 516. +## Ends in an error in state: 515. ## ## declaration_specifiers(declaration(block_item)) -> typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2352,7 +2355,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 521. +## Ends in an error in state: 520. ## ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2366,7 +2369,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE INT XOR_ASSIGN ## -## Ends in an error in state: 518. +## Ends in an error in state: 517. ## ## declaration_specifiers(declaration(block_item)) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2377,7 +2380,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE VOLATILE INT XOR_ASSIGN ## -## Ends in an error in state: 523. +## Ends in an error in state: 522. ## ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . TYPEDEF list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -2417,7 +2420,7 @@ At this point, one of the following is expected: translation_unit_file: UNION LBRACE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 181. +## Ends in an error in state: 92. ## ## struct_declaration -> specifier_qualifier_list(struct_declaration) . option(struct_declarator_list) SEMICOLON [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT SIGNED SHORT RESTRICT RBRACE PRE_NAME PACKED LONG INT FLOAT ENUM DOUBLE CONST CHAR ATTRIBUTE ALIGNAS ] ## @@ -2428,7 +2431,7 @@ translation_unit_file: UNION LBRACE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 167, spurious reduction of production specifier_qualifier_list(struct_declaration) -> typedef_name option(type_qualifier_list) +## In state 78, spurious reduction of production specifier_qualifier_list(struct_declaration) -> typedef_name option(type_qualifier_list) ## # We have (spuriously) recognized a specifier_qualifier_list, @@ -2474,19 +2477,19 @@ translation_unit_file: UNION LBRACE LONG COLON CONSTANT RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 67, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 154, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression ## In state 292, spurious reduction of production struct_declarator -> option(declarator) COLON conditional_expression ## In state 294, spurious reduction of production struct_declarator_list -> struct_declarator ## @@ -2573,7 +2576,7 @@ then at this point, one of the following is expected: translation_unit_file: UNION LBRACE VOLATILE ADD_ASSIGN ## -## Ends in an error in state: 175. +## Ends in an error in state: 86. ## ## option(type_qualifier_list) -> type_qualifier_list . [ VOLATILE RESTRICT PACKED CONST ATTRIBUTE ALIGNAS ] ## specifier_qualifier_list(struct_declaration) -> type_qualifier_list . typedef_name option(type_qualifier_list) [ STAR SEMICOLON PRE_NAME LPAREN COLON ] @@ -2596,7 +2599,7 @@ At this point, one of the following is expected: translation_unit_file: UNION LBRACE XOR_ASSIGN ## -## Ends in an error in state: 164. +## Ends in an error in state: 75. ## ## struct_declaration_list -> struct_declaration_list . struct_declaration [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT SIGNED SHORT RESTRICT RBRACE PRE_NAME PACKED LONG INT FLOAT ENUM DOUBLE CONST CHAR ATTRIBUTE ALIGNAS ] ## struct_or_union_specifier -> struct_or_union attribute_specifier_list option(other_identifier) LBRACE struct_declaration_list . RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -2616,7 +2619,7 @@ At this point, one of the following is expected: translation_unit_file: UNION XOR_ASSIGN ## -## Ends in an error in state: 161. +## Ends in an error in state: 72. ## ## struct_or_union_specifier -> struct_or_union attribute_specifier_list . option(other_identifier) LBRACE struct_declaration_list RBRACE [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] ## struct_or_union_specifier -> struct_or_union attribute_specifier_list . general_identifier [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF STRUCT STATIC STAR SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK INT INLINE FLOAT EXTERN ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -2628,7 +2631,7 @@ translation_unit_file: UNION XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 160, spurious reduction of production attribute_specifier_list -> +## In state 71, spurious reduction of production attribute_specifier_list -> ## # gcc expects '{'. @@ -2661,7 +2664,7 @@ translation_unit_file: INT LPAREN PRE_NAME VAR_NAME SEMICOLON ## In state 261, spurious reduction of production declarator -> declarator_noattrend attribute_specifier_list ## -Up to this point, a declarator have been recognized: +Up to this point, a declarator has been recognized: $0 If this declarator is complete, then at this point, a closing parenthesis ')' is expected. @@ -2670,7 +2673,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT LPAREN XOR_ASSIGN ## -## Ends in an error in state: 187. +## Ends in an error in state: 98. ## ## direct_declarator -> LPAREN save_context . declarator RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] ## @@ -2706,7 +2709,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN XOR_ASSIGN ## -## Ends in an error in state: 193. +## Ends in an error in state: 104. ## ## context_parameter_type_list -> save_context . parameter_type_list save_context [ RPAREN ] ## direct_declarator -> direct_declarator LPAREN save_context . option(identifier_list) RPAREN [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -2730,7 +2733,7 @@ followed with a closing parenthesis ')', is expected. translation_unit_file: INT STAR RPAREN ## -## Ends in an error in state: 190. +## Ends in an error in state: 101. ## ## declarator_noattrend -> list(pointer1) STAR option(type_qualifier_list) . direct_declarator [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LONG LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] ## list(pointer1) -> list(pointer1) STAR option(type_qualifier_list) . [ STAR ] @@ -2763,7 +2766,7 @@ At this point, one of the following is expected: translation_unit_file: TYPEDEF INT PRE_NAME VAR_NAME XOR_ASSIGN ## -## Ends in an error in state: 535. +## Ends in an error in state: 534. ## ## option(typedef_declarator_list) -> typedef_declarator_list . [ SEMICOLON ] ## typedef_declarator_list -> typedef_declarator_list . COMMA typedef_declarator [ SEMICOLON COMMA ] @@ -2778,9 +2781,9 @@ translation_unit_file: TYPEDEF INT PRE_NAME VAR_NAME XOR_ASSIGN ## In state 255, spurious reduction of production declarator_noattrend -> direct_declarator ## In state 260, spurious reduction of production attribute_specifier_list -> ## In state 261, spurious reduction of production declarator -> declarator_noattrend attribute_specifier_list -## In state 539, spurious reduction of production declare_typename(declarator) -> declarator -## In state 538, spurious reduction of production typedef_declarator -> declare_typename(declarator) -## In state 540, spurious reduction of production typedef_declarator_list -> typedef_declarator +## In state 538, spurious reduction of production declare_typename(declarator) -> declarator +## In state 537, spurious reduction of production typedef_declarator -> declare_typename(declarator) +## In state 539, spurious reduction of production typedef_declarator_list -> typedef_declarator ## # Because attribute_specifier_list, declarator and declarator_noattrend have been marked @@ -2806,7 +2809,7 @@ then at this point, a semicolon ';' is expected. translation_unit_file: TYPEDEF INT PRE_NAME VAR_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 536. +## Ends in an error in state: 535. ## ## typedef_declarator_list -> typedef_declarator_list COMMA . typedef_declarator [ SEMICOLON COMMA ] ## @@ -2835,7 +2838,7 @@ followed with a closing parenthesis ')', is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM CONST XOR_ASSIGN ## -## Ends in an error in state: 451. +## Ends in an error in state: 450. ## ## asm_attributes -> CONST . asm_attributes [ LPAREN ] ## @@ -2844,7 +2847,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM VOLATILE XOR_ASSIGN ## -## Ends in an error in state: 450. +## Ends in an error in state: 449. ## ## asm_attributes -> VOLATILE . asm_attributes [ LPAREN ] ## @@ -2853,7 +2856,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM XOR_ASSIGN ## -## Ends in an error in state: 449. +## Ends in an error in state: 448. ## ## asm_statement -> ASM . asm_attributes LPAREN string_literals_list asm_arguments RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -2870,7 +2873,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON COLON STRING_LITERAL COMMA XOR_ASSIGN ## -## Ends in an error in state: 475. +## Ends in an error in state: 474. ## ## asm_flags -> asm_flags COMMA . string_literals_list [ RPAREN COMMA ] ## @@ -2882,7 +2885,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN # first(asm_flags) = STRING_LITERAL translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON COLON XOR_ASSIGN ## -## Ends in an error in state: 472. +## Ends in an error in state: 471. ## ## asm_arguments -> COLON asm_operands COLON asm_operands COLON . asm_flags [ RPAREN ] ## @@ -2902,7 +2905,7 @@ Examples of clobbered resources: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON COLON STRING_LITERAL XOR_ASSIGN ## -## Ends in an error in state: 474. +## Ends in an error in state: 473. ## ## asm_arguments -> COLON asm_operands COLON asm_operands COLON asm_flags . [ RPAREN ] ## asm_flags -> asm_flags . COMMA string_literals_list [ RPAREN COMMA ] @@ -2914,7 +2917,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 473, spurious reduction of production asm_flags -> string_literals_list +## In state 472, spurious reduction of production asm_flags -> string_literals_list ## # Let's ignore the possibility of concatenating string literals. @@ -2931,7 +2934,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN CONSTANT RPAREN XOR_ASSIGN ## -## Ends in an error in state: 469. +## Ends in an error in state: 468. ## ## asm_arguments -> COLON asm_operands . [ RPAREN ] ## asm_arguments -> COLON asm_operands . COLON asm_operands [ RPAREN ] @@ -2944,7 +2947,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 461, spurious reduction of production asm_operands -> asm_operands_ne +## In state 460, spurious reduction of production asm_operands -> asm_operands_ne ## # We have seen one COLON, hence the outputs. (The list of outputs may be empty.) @@ -2961,7 +2964,7 @@ then at this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON COLON XOR_ASSIGN ## -## Ends in an error in state: 471. +## Ends in an error in state: 470. ## ## asm_arguments -> COLON asm_operands COLON asm_operands . [ RPAREN ] ## asm_arguments -> COLON asm_operands COLON asm_operands . COLON asm_flags [ RPAREN ] @@ -2973,7 +2976,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 470, spurious reduction of production asm_operands -> +## In state 469, spurious reduction of production asm_operands -> ## # We have seen two COLONs, hence the outputs and inputs. (The list of inputs may be empty.) @@ -2993,7 +2996,7 @@ then at this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON LBRACK PRE_NAME VAR_NAME RBRACK XOR_ASSIGN ## -## Ends in an error in state: 464. +## Ends in an error in state: 463. ## ## asm_operand -> asm_op_name . string_literals_list LPAREN expression RPAREN [ RPAREN COMMA COLON ] ## @@ -3012,7 +3015,7 @@ At this point, a string literal, representing a constraint, is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON LBRACK PRE_NAME VAR_NAME XOR_ASSIGN ## -## Ends in an error in state: 459. +## Ends in an error in state: 458. ## ## asm_op_name -> LBRACK general_identifier . RBRACK [ STRING_LITERAL ] ## @@ -3027,7 +3030,7 @@ At this point, a closing bracket ']' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON LBRACK XOR_ASSIGN ## -## Ends in an error in state: 458. +## Ends in an error in state: 457. ## ## asm_op_name -> LBRACK . general_identifier RBRACK [ STRING_LITERAL ] ## @@ -3042,7 +3045,7 @@ At this point, an identifier is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN CONSTANT RPAREN COMMA XOR_ASSIGN ## -## Ends in an error in state: 462. +## Ends in an error in state: 461. ## ## asm_operands_ne -> asm_operands_ne COMMA . asm_operand [ RPAREN COMMA COLON ] ## @@ -3059,7 +3062,7 @@ At this point, an assembly operand is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 467. +## Ends in an error in state: 466. ## ## asm_operand -> asm_op_name string_literals_list LPAREN expression . RPAREN [ RPAREN COMMA COLON ] ## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ] @@ -3071,21 +3074,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## Ill-formed assembly operand. @@ -3098,7 +3101,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL LPAREN XOR_ASSIGN ## -## Ends in an error in state: 466. +## Ends in an error in state: 465. ## ## asm_operand -> asm_op_name string_literals_list LPAREN . expression RPAREN [ RPAREN COMMA COLON ] ## @@ -3113,7 +3116,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL COLON STRING_LITERAL XOR_ASSIGN ## -## Ends in an error in state: 465. +## Ends in an error in state: 464. ## ## asm_operand -> asm_op_name string_literals_list . LPAREN expression RPAREN [ RPAREN COMMA COLON ] ## string_literals_list -> string_literals_list . STRING_LITERAL [ STRING_LITERAL LPAREN ] @@ -3133,7 +3136,7 @@ followed with an expression and a closing parenthesis ')', is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL XOR_ASSIGN ## -## Ends in an error in state: 456. +## Ends in an error in state: 455. ## ## asm_statement -> ASM asm_attributes LPAREN string_literals_list . asm_arguments RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## string_literals_list -> string_literals_list . STRING_LITERAL [ STRING_LITERAL RPAREN COLON ] @@ -3155,7 +3158,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN XOR_ASSIGN ## -## Ends in an error in state: 455. +## Ends in an error in state: 454. ## ## asm_statement -> ASM asm_attributes LPAREN . string_literals_list asm_arguments RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3170,7 +3173,7 @@ At this point, a string literal, representing an instruction, is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE BREAK XOR_ASSIGN ## -## Ends in an error in state: 447. +## Ends in an error in state: 446. ## ## jump_statement -> BREAK . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3179,7 +3182,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CONTINUE XOR_ASSIGN ## -## Ends in an error in state: 442. +## Ends in an error in state: 441. ## ## jump_statement -> CONTINUE . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3188,7 +3191,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN ## -## Ends in an error in state: 566. +## Ends in an error in state: 565. ## ## iteration_statement -> save_context do_statement1 WHILE LPAREN expression RPAREN . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3197,7 +3200,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE GOTO PRE_NAME VAR_NAME XOR_ASSIGN ## -## Ends in an error in state: 438. +## Ends in an error in state: 437. ## ## jump_statement -> GOTO general_identifier . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3206,7 +3209,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE ASM LPAREN STRING_LITERAL RPAREN XOR_ASSIGN ## -## Ends in an error in state: 479. +## Ends in an error in state: 478. ## ## asm_statement -> ASM asm_attributes LPAREN string_literals_list asm_arguments RPAREN . SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3221,7 +3224,7 @@ At this point, a semicolon ';' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CASE CONSTANT COLON XOR_ASSIGN ## -## Ends in an error in state: 446. +## Ends in an error in state: 445. ## ## labeled_statement -> CASE conditional_expression COLON . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3230,7 +3233,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DEFAULT COLON XOR_ASSIGN ## -## Ends in an error in state: 441. +## Ends in an error in state: 440. ## ## labeled_statement -> DEFAULT COLON . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3239,7 +3242,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME VAR_NAME COLON XOR_ASSIGN ## -## Ends in an error in state: 495. +## Ends in an error in state: 494. ## ## labeled_statement -> general_identifier COLON . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3256,7 +3259,7 @@ At this point, a statement is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CASE CONSTANT SEMICOLON ## -## Ends in an error in state: 445. +## Ends in an error in state: 444. ## ## labeled_statement -> CASE conditional_expression . COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3267,19 +3270,19 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 67, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 154, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression ## Ill-formed labeled statement. @@ -3292,7 +3295,7 @@ then at this point, a colon ':' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE CASE XOR_ASSIGN ## -## Ends in an error in state: 444. +## Ends in an error in state: 443. ## ## labeled_statement -> CASE . conditional_expression COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3307,7 +3310,7 @@ At this point, a constant expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DEFAULT XOR_ASSIGN ## -## Ends in an error in state: 440. +## Ends in an error in state: 439. ## ## labeled_statement -> DEFAULT . COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3316,7 +3319,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 494. +## Ends in an error in state: 493. ## ## labeled_statement -> general_identifier . COLON statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3333,7 +3336,7 @@ At this point, a colon ':' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 565. +## Ends in an error in state: 564. ## ## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ] ## iteration_statement -> save_context do_statement1 WHILE LPAREN expression . RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] @@ -3345,21 +3348,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## Ill-formed 'do' ... 'while' statement. @@ -3372,7 +3375,7 @@ then at this point, a closing parenthesis ')' and a semicolon ';' are expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE LPAREN XOR_ASSIGN ## -## Ends in an error in state: 564. +## Ends in an error in state: 563. ## ## iteration_statement -> save_context do_statement1 WHILE LPAREN . expression RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3387,7 +3390,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON WHILE XOR_ASSIGN ## -## Ends in an error in state: 563. +## Ends in an error in state: 562. ## ## iteration_statement -> save_context do_statement1 WHILE . LPAREN expression RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3402,7 +3405,7 @@ At this point, an opening parenthesis '(' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO SEMICOLON XOR_ASSIGN ## -## Ends in an error in state: 562. +## Ends in an error in state: 561. ## ## iteration_statement -> save_context do_statement1 . WHILE LPAREN expression RPAREN SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3423,7 +3426,7 @@ At this point, a 'while' keyword is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO XOR_ASSIGN ## -## Ends in an error in state: 558. +## Ends in an error in state: 557. ## ## do_statement1 -> save_context DO . statement [ WHILE ] ## @@ -3440,7 +3443,7 @@ At this point, a statement (the loop body) is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON SEMICOLON RPAREN XOR_ASSIGN ## -## Ends in an error in state: 528. +## Ends in an error in state: 527. ## ## iteration_statement -> save_context FOR LPAREN for_statement_header optional(expression,SEMICOLON) optional(expression,RPAREN) . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3455,7 +3458,7 @@ At this point, a statement (the loop body) is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON SEMICOLON PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 530. +## Ends in an error in state: 529. ## ## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ] ## optional(expression,RPAREN) -> expression . RPAREN [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG ASM AND ALIGNOF ] @@ -3467,21 +3470,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## # The use of optional(expression,RPAREN) tells us that we are in a FOR statement. @@ -3497,7 +3500,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON SEMICOLON XOR_ASSIGN ## -## Ends in an error in state: 526. +## Ends in an error in state: 525. ## ## iteration_statement -> save_context FOR LPAREN for_statement_header optional(expression,SEMICOLON) . optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3517,7 +3520,7 @@ followed with a closing parenthesis ')', is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN SEMICOLON XOR_ASSIGN ## -## Ends in an error in state: 525. +## Ends in an error in state: 524. ## ## iteration_statement -> save_context FOR LPAREN for_statement_header . optional(expression,SEMICOLON) optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3536,7 +3539,7 @@ followed with a semicolon ';', is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN PRE_NAME VAR_NAME RPAREN ## -## Ends in an error in state: 532. +## Ends in an error in state: 531. ## ## expression -> expression . COMMA assignment_expression [ SEMICOLON COMMA ] ## optional(expression,SEMICOLON) -> expression . SEMICOLON [ TILDE STRING_LITERAL STAR SIZEOF SEMICOLON RPAREN PRE_NAME PLUS MINUS LPAREN INC DEC CONSTANT BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG AND ALIGNOF ] @@ -3548,21 +3551,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## # At the time of writing, optional(expression,SEMICOLON) is used only in FOR @@ -3578,7 +3581,7 @@ then at this point, a semicolon ';' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR LPAREN XOR_ASSIGN ## -## Ends in an error in state: 513. +## Ends in an error in state: 512. ## ## iteration_statement -> save_context FOR LPAREN . for_statement_header optional(expression,SEMICOLON) optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3599,7 +3602,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE FOR XOR_ASSIGN ## -## Ends in an error in state: 512. +## Ends in an error in state: 511. ## ## iteration_statement -> save_context FOR . LPAREN for_statement_header optional(expression,SEMICOLON) optional(expression,RPAREN) statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3614,7 +3617,7 @@ At this point, an opening parenthesis '(' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE GOTO XOR_ASSIGN ## -## Ends in an error in state: 437. +## Ends in an error in state: 436. ## ## jump_statement -> GOTO . general_identifier SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3629,7 +3632,7 @@ At this point, an identifier (a 'goto' label) is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE DO IF LPAREN CONSTANT RPAREN SEMICOLON ELSE XOR_ASSIGN ## -## Ends in an error in state: 560. +## Ends in an error in state: 559. ## ## selection_statement -> save_context ifelse_statement1 . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3644,7 +3647,7 @@ At this point, a statement is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN ## -## Ends in an error in state: 509. +## Ends in an error in state: 508. ## ## ifelse_statement1 -> IF LPAREN expression RPAREN save_context . statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG ASM AND ALIGNOF ] ## selection_statement -> save_context IF LPAREN expression RPAREN save_context . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] @@ -3660,7 +3663,7 @@ At this point, a statement is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 507. +## Ends in an error in state: 506. ## ## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ] ## ifelse_statement1 -> IF LPAREN expression . RPAREN save_context statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG ASM AND ALIGNOF ] @@ -3673,21 +3676,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## Ill-formed 'if' statement. @@ -3700,7 +3703,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF LPAREN XOR_ASSIGN ## -## Ends in an error in state: 506. +## Ends in an error in state: 505. ## ## ifelse_statement1 -> IF LPAREN . expression RPAREN save_context statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG ASM AND ALIGNOF ] ## selection_statement -> save_context IF LPAREN . expression RPAREN save_context statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] @@ -3716,7 +3719,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE IF XOR_ASSIGN ## -## Ends in an error in state: 505. +## Ends in an error in state: 504. ## ## ifelse_statement1 -> IF . LPAREN expression RPAREN save_context statement ELSE [ WHILE TILDE SWITCH STRING_LITERAL STAR SIZEOF SEMICOLON RETURN PRE_NAME PLUS MINUS LPAREN LBRACE INC IF GOTO FOR DO DEFAULT DEC CONTINUE CONSTANT CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG ASM AND ALIGNOF ] ## selection_statement -> save_context IF . LPAREN expression RPAREN save_context statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] @@ -3732,7 +3735,7 @@ At this point, an opening parenthesis '(' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN ## -## Ends in an error in state: 503. +## Ends in an error in state: 502. ## ## selection_statement -> save_context SWITCH LPAREN expression RPAREN . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3756,7 +3759,7 @@ enclosed within braces '{' and '}'. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 502. +## Ends in an error in state: 501. ## ## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ] ## selection_statement -> save_context SWITCH LPAREN expression . RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] @@ -3768,21 +3771,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## Ill-formed 'switch' statement. @@ -3795,7 +3798,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH LPAREN XOR_ASSIGN ## -## Ends in an error in state: 501. +## Ends in an error in state: 500. ## ## selection_statement -> save_context SWITCH LPAREN . expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3810,7 +3813,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE SWITCH XOR_ASSIGN ## -## Ends in an error in state: 500. +## Ends in an error in state: 499. ## ## selection_statement -> save_context SWITCH . LPAREN expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3825,7 +3828,7 @@ At this point, an opening parenthesis '(' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE LPAREN PRE_NAME VAR_NAME RPAREN XOR_ASSIGN ## -## Ends in an error in state: 487. +## Ends in an error in state: 486. ## ## iteration_statement -> save_context WHILE LPAREN expression RPAREN . statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3840,7 +3843,7 @@ At this point, a statement (the loop body) is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE LPAREN PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 486. +## Ends in an error in state: 485. ## ## expression -> expression . COMMA assignment_expression [ RPAREN COMMA ] ## iteration_statement -> save_context WHILE LPAREN expression . RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] @@ -3852,21 +3855,21 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## Ill-formed 'while' statement. @@ -3879,7 +3882,7 @@ then at this point, a closing parenthesis ')' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE LPAREN XOR_ASSIGN ## -## Ends in an error in state: 485. +## Ends in an error in state: 484. ## ## iteration_statement -> save_context WHILE LPAREN . expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3894,7 +3897,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE WHILE XOR_ASSIGN ## -## Ends in an error in state: 484. +## Ends in an error in state: 483. ## ## iteration_statement -> save_context WHILE . LPAREN expression RPAREN statement [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3909,7 +3912,7 @@ At this point, an opening parenthesis '(' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE XOR_ASSIGN ## -## Ends in an error in state: 428. +## Ends in an error in state: 427. ## ## block_item_list -> option(block_item_list) . block_item [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## compound_statement -> save_context LBRACE option(block_item_list) . RBRACE [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN EOF ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] @@ -3937,7 +3940,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE RETURN XOR_ASSIGN ## -## Ends in an error in state: 429. +## Ends in an error in state: 428. ## ## jump_statement -> RETURN . option(expression) SEMICOLON [ WHILE VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL TYPEDEF TILDE SWITCH STRUCT STRING_LITERAL STATIC STAR SIZEOF SIGNED SHORT SEMICOLON RETURN RESTRICT REGISTER RBRACE PRE_NAME PRAGMA PLUS PACKED NORETURN MINUS LPAREN LONG LBRACE INT INLINE INC IF GOTO FOR FLOAT EXTERN ENUM ELSE DOUBLE DO DEFAULT DEC CONTINUE CONSTANT CONST CHAR CASE BUILTIN_VA_ARG BUILTIN_OFFSETOF BREAK BANG AUTO ATTRIBUTE ASM AND ALIGNOF ALIGNAS ] ## @@ -3956,7 +3959,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE STRING_LITERAL RPAREN ## -## Ends in an error in state: 432. +## Ends in an error in state: 431. ## ## expression -> expression . COMMA assignment_expression [ SEMICOLON COMMA ] ## option(expression) -> expression . [ SEMICOLON ] @@ -3968,23 +3971,23 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 68, spurious reduction of production primary_expression -> string_literals_list -## In state 70, spurious reduction of production postfix_expression -> primary_expression -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 137, spurious reduction of production expression -> assignment_expression +## In state 155, spurious reduction of production primary_expression -> string_literals_list +## In state 157, spurious reduction of production postfix_expression -> primary_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 224, spurious reduction of production expression -> assignment_expression ## Up to this point, an expression has been recognized: @@ -3996,7 +3999,7 @@ then at this point, a semicolon ';' is expected. translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 569. +## Ends in an error in state: 568. ## ## declaration_specifiers(declaration(block_item)) -> typedef_name . list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers_typedef -> typedef_name . list(declaration_specifier_no_type) TYPEDEF list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -4031,7 +4034,7 @@ at this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME RPAREN LBRACE PRE_NAME VAR_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 132. +## Ends in an error in state: 219. ## ## expression -> expression COMMA . assignment_expression [ SEMICOLON RPAREN RBRACK COMMA COLON ] ## @@ -4046,7 +4049,7 @@ At this point, an expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME COMMA PRE_NAME VAR_NAME RPAREN ## -## Ends in an error in state: 546. +## Ends in an error in state: 545. ## ## init_declarator_list -> init_declarator_list . COMMA init_declarator [ SEMICOLON COMMA ] ## option(init_declarator_list) -> init_declarator_list . [ SEMICOLON ] @@ -4059,11 +4062,11 @@ translation_unit_file: INT PRE_NAME VAR_NAME COMMA PRE_NAME VAR_NAME RPAREN ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 255, spurious reduction of production declarator_noattrend -> direct_declarator -## In state 554, spurious reduction of production declare_varname(declarator_noattrend) -> declarator_noattrend -## In state 549, spurious reduction of production save_context -> -## In state 550, spurious reduction of production attribute_specifier_list -> -## In state 551, spurious reduction of production init_declarator -> declare_varname(declarator_noattrend) save_context attribute_specifier_list -## In state 548, spurious reduction of production init_declarator_list -> init_declarator_list COMMA init_declarator +## In state 553, spurious reduction of production declare_varname(declarator_noattrend) -> declarator_noattrend +## In state 548, spurious reduction of production save_context -> +## In state 549, spurious reduction of production attribute_specifier_list -> +## In state 550, spurious reduction of production init_declarator -> declare_varname(declarator_noattrend) save_context attribute_specifier_list +## In state 547, spurious reduction of production init_declarator_list -> init_declarator_list COMMA init_declarator ## Up to this point, a list of declarators has been recognized: @@ -4075,7 +4078,7 @@ then at this point, a semicolon ';' is expected. translation_unit_file: INT PRE_NAME VAR_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 547. +## Ends in an error in state: 546. ## ## init_declarator_list -> init_declarator_list COMMA . init_declarator [ SEMICOLON COMMA ] ## @@ -4090,7 +4093,7 @@ At this point, an init declarator is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE DOT PRE_NAME VAR_NAME EQ ALIGNAS ## -## Ends in an error in state: 314. +## Ends in an error in state: 366. ## ## initializer_list -> option(designation) . c_initializer [ RBRACE COMMA ] ## @@ -4099,7 +4102,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE DOT PRE_NAME VAR_NAME EQ ## translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE PRE_NAME VAR_NAME COMMA DOT PRE_NAME VAR_NAME EQ ALIGNAS ## -## Ends in an error in state: 318. +## Ends in an error in state: 370. ## ## initializer_list -> initializer_list COMMA option(designation) . c_initializer [ RBRACE COMMA ] ## @@ -4114,7 +4117,7 @@ At this point, an initializer is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE DOT PRE_NAME VAR_NAME XOR_ASSIGN ## -## Ends in an error in state: 321. +## Ends in an error in state: 373. ## ## designation -> designator_list . EQ [ TILDE STRING_LITERAL STAR SIZEOF PRE_NAME PLUS MINUS LPAREN LBRACE INC DEC CONSTANT BUILTIN_VA_ARG BUILTIN_OFFSETOF BANG AND ALIGNOF ] ## option(designator_list) -> designator_list . [ LBRACK DOT ] @@ -4136,7 +4139,7 @@ then at this point, an equals sign '=' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE DOT XOR_ASSIGN ## -## Ends in an error in state: 311. +## Ends in an error in state: 326. ## ## designator -> DOT . general_identifier [ RPAREN LBRACK EQ DOT ] ## @@ -4153,7 +4156,7 @@ At this point, the name of a struct or union member is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE LBRACK PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 309. +## Ends in an error in state: 324. ## ## designator -> LBRACK conditional_expression . RBRACK [ RPAREN LBRACK EQ DOT ] ## @@ -4164,19 +4167,19 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE LBRACK PRE_NAME VAR_NAME ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 67, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 154, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression ## Ill-formed designator. @@ -4189,7 +4192,7 @@ then at this point, a closing bracket ']' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE LBRACK XOR_ASSIGN ## -## Ends in an error in state: 308. +## Ends in an error in state: 323. ## ## designator -> LBRACK . conditional_expression RBRACK [ RPAREN LBRACK EQ DOT ] ## @@ -4204,7 +4207,7 @@ At this point, a constant expression is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE PRE_NAME VAR_NAME COMMA XOR_ASSIGN ## -## Ends in an error in state: 317. +## Ends in an error in state: 369. ## ## initializer_list -> initializer_list COMMA . option(designation) c_initializer [ RBRACE COMMA ] ## option(COMMA) -> COMMA . [ RBRACE ] @@ -4225,7 +4228,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE CONSTANT SEMICOLON ## -## Ends in an error in state: 316. +## Ends in an error in state: 368. ## ## c_initializer -> LBRACE initializer_list . option(COMMA) RBRACE [ SEMICOLON RBRACE COMMA ] ## initializer_list -> initializer_list . COMMA option(designation) c_initializer [ RBRACE COMMA ] @@ -4237,22 +4240,22 @@ translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE CONSTANT SEMICOLON ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression -## In state 320, spurious reduction of production c_initializer -> assignment_expression -## In state 326, spurious reduction of production initializer_list -> option(designation) c_initializer +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression +## In state 372, spurious reduction of production c_initializer -> assignment_expression +## In state 378, spurious reduction of production initializer_list -> option(designation) c_initializer ## # Omitting the fact that the closing brace can be preceded with a comma. @@ -4267,7 +4270,7 @@ then at this point, a closing brace '}' is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ LBRACE XOR_ASSIGN ## -## Ends in an error in state: 315. +## Ends in an error in state: 367. ## ## c_initializer -> LBRACE . initializer_list option(COMMA) RBRACE [ SEMICOLON RBRACE COMMA ] ## @@ -4288,7 +4291,7 @@ followed with an initializer, is expected. translation_unit_file: INT PRE_NAME VAR_NAME EQ XOR_ASSIGN ## -## Ends in an error in state: 552. +## Ends in an error in state: 551. ## ## init_declarator -> declare_varname(declarator_noattrend) save_context attribute_specifier_list EQ . c_initializer [ SEMICOLON COMMA ] ## @@ -4316,20 +4319,20 @@ translation_unit_file: INT PRE_NAME VAR_NAME LBRACK CONSTANT SEMICOLON ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 71, spurious reduction of production unary_expression -> postfix_expression -## In state 75, spurious reduction of production cast_expression -> unary_expression -## In state 98, spurious reduction of production multiplicative_expression -> cast_expression -## In state 92, spurious reduction of production additive_expression -> multiplicative_expression -## In state 111, spurious reduction of production shift_expression -> additive_expression -## In state 88, spurious reduction of production relational_expression -> shift_expression -## In state 104, spurious reduction of production equality_expression -> relational_expression -## In state 120, spurious reduction of production and_expression -> equality_expression -## In state 128, spurious reduction of production exclusive_or_expression -> and_expression -## In state 129, spurious reduction of production inclusive_or_expression -> exclusive_or_expression -## In state 130, spurious reduction of production logical_and_expression -> inclusive_or_expression -## In state 114, spurious reduction of production logical_or_expression -> logical_and_expression -## In state 112, spurious reduction of production conditional_expression -> logical_or_expression -## In state 133, spurious reduction of production assignment_expression -> conditional_expression +## In state 158, spurious reduction of production unary_expression -> postfix_expression +## In state 162, spurious reduction of production cast_expression -> unary_expression +## In state 185, spurious reduction of production multiplicative_expression -> cast_expression +## In state 179, spurious reduction of production additive_expression -> multiplicative_expression +## In state 198, spurious reduction of production shift_expression -> additive_expression +## In state 175, spurious reduction of production relational_expression -> shift_expression +## In state 191, spurious reduction of production equality_expression -> relational_expression +## In state 207, spurious reduction of production and_expression -> equality_expression +## In state 215, spurious reduction of production exclusive_or_expression -> and_expression +## In state 216, spurious reduction of production inclusive_or_expression -> exclusive_or_expression +## In state 217, spurious reduction of production logical_and_expression -> inclusive_or_expression +## In state 201, spurious reduction of production logical_or_expression -> logical_and_expression +## In state 199, spurious reduction of production conditional_expression -> logical_or_expression +## In state 220, spurious reduction of production assignment_expression -> conditional_expression ## # At the time of writing, optional(expression,RBRACK) is used only in direct @@ -4380,7 +4383,7 @@ The following type name is used as a K&R parameter name: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN INT XOR_ASSIGN ## -## Ends in an error in state: 587. +## Ends in an error in state: 586. ## ## declaration_specifiers(declaration(block_item)) -> type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -4390,7 +4393,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN INT ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOLATILE INT XOR_ASSIGN ## -## Ends in an error in state: 592. +## Ends in an error in state: 591. ## ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_typedef_name) -> list(declaration_specifier_no_typedef_name) . declaration_specifier_no_typedef_name [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC STAR SIGNED SHORT SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ] @@ -4400,7 +4403,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOL ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 585. +## Ends in an error in state: 584. ## ## declaration_specifiers(declaration(block_item)) -> typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ] @@ -4413,7 +4416,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN PRE ## translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOLATILE PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 590. +## Ends in an error in state: 589. ## ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) typedef_name list(declaration_specifier_no_type) . [ STAR SEMICOLON PRE_NAME LPAREN ] ## list(declaration_specifier_no_type) -> list(declaration_specifier_no_type) . storage_class_specifier_no_typedef [ VOLATILE STATIC STAR SEMICOLON RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN INLINE EXTERN CONST AUTO ATTRIBUTE ALIGNAS ] @@ -4438,7 +4441,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOLATILE XOR_ASSIGN ## -## Ends in an error in state: 588. +## Ends in an error in state: 587. ## ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . typedef_name list(declaration_specifier_no_type) [ STAR SEMICOLON PRE_NAME LPAREN ] ## declaration_specifiers(declaration(block_item)) -> rlist(declaration_specifier_no_type) . type_specifier_no_typedef_name list(declaration_specifier_no_typedef_name) [ STAR SEMICOLON PRE_NAME LPAREN ] @@ -4450,7 +4453,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN VOL ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 214, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr +## In state 125, spurious reduction of production rlist(declaration_specifier_no_type) -> type_qualifier_noattr ## Ill-formed K&R parameter declaration. @@ -4463,7 +4466,7 @@ At this point, one of the following is expected: translation_unit_file: VOID PRE_NAME TYPEDEF_NAME PACKED LPAREN CONSTANT RPAREN XOR_ASSIGN ## -## Ends in an error in state: 601. +## Ends in an error in state: 600. ## ## attribute_specifier_list -> attribute_specifier . attribute_specifier_list [ SEMICOLON LBRACE EQ COMMA ] ## rlist(declaration_specifier_no_type) -> attribute_specifier . [ VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT SIGNED SHORT PRE_NAME LONG INT FLOAT ENUM DOUBLE CHAR ] @@ -4496,7 +4499,7 @@ If this is the parameter declaration of a K&R function definition, translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT COMMA XOR_ASSIGN ## -## Ends in an error in state: 230. +## Ends in an error in state: 141. ## ## parameter_list -> parameter_list COMMA . parameter_declaration [ RPAREN COMMA ] ## parameter_type_list -> parameter_list COMMA . ELLIPSIS [ RPAREN ] @@ -4513,7 +4516,7 @@ At this point, one of the following is expected: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME SEMICOLON ## -## Ends in an error in state: 229. +## Ends in an error in state: 140. ## ## parameter_list -> parameter_list . COMMA parameter_declaration [ RPAREN COMMA ] ## parameter_type_list -> parameter_list . [ RPAREN ] @@ -4531,7 +4534,7 @@ translation_unit_file: INT PRE_NAME VAR_NAME LPAREN INT PRE_NAME VAR_NAME SEMICO ## In state 261, spurious reduction of production declarator -> declarator_noattrend attribute_specifier_list ## In state 277, spurious reduction of production declare_varname(declarator) -> declarator ## In state 276, spurious reduction of production parameter_declaration -> declaration_specifiers(parameter_declaration) declare_varname(declarator) -## In state 237, spurious reduction of production parameter_list -> parameter_declaration +## In state 148, spurious reduction of production parameter_list -> parameter_declaration ## # We omit the possibility of an ellipsis. @@ -4567,7 +4570,7 @@ The following identifier is used as a type, but has not been defined as such: translation_unit_file: INT PRE_NAME VAR_NAME LPAREN PRE_NAME VAR_NAME RPAREN INT SEMICOLON XOR_ASSIGN ## -## Ends in an error in state: 597. +## Ends in an error in state: 596. ## ## declaration_list -> declaration_list . kr_param_declaration [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT RESTRICT REGISTER PRE_NAME PACKED NORETURN LONG LBRACE INT INLINE FLOAT EXTERN ENUM DOUBLE CONST CHAR AUTO ATTRIBUTE ALIGNAS ] ## function_definition1 -> declaration_specifiers(declaration(external_declaration)) declare_varname(declarator_noattrend) save_context declaration_list . [ LBRACE ] @@ -4618,7 +4621,7 @@ At this point, a struct or union name is expected. translation_unit_file: PACKED LPAREN BUILTIN_OFFSETOF LPAREN VOID XOR_ASSIGN ## -## Ends in an error in state: 345. +## Ends in an error in state: 318. ## ## postfix_expression -> BUILTIN_OFFSETOF LPAREN type_name . COMMA general_identifier RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## postfix_expression -> BUILTIN_OFFSETOF LPAREN type_name . COMMA general_identifier designator_list RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -4630,9 +4633,9 @@ translation_unit_file: PACKED LPAREN BUILTIN_OFFSETOF LPAREN VOID XOR_ASSIGN ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 156, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) -## In state 330, spurious reduction of production option(abstract_declarator(type_name)) -> -## In state 336, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) +## In state 67, spurious reduction of production specifier_qualifier_list(type_name) -> type_specifier_no_typedef_name list(specifier_qualifier_no_typedef_name) +## In state 306, spurious reduction of production option(abstract_declarator(type_name)) -> +## In state 312, spurious reduction of production type_name -> specifier_qualifier_list(type_name) option(abstract_declarator(type_name)) ## Ill-formed __builtin_offsetof. @@ -4642,7 +4645,7 @@ At this point, a colon ',' is expected translation_unit_file: PACKED LPAREN BUILTIN_OFFSETOF LPAREN VOID COMMA XOR_ASSIGN ## -## Ends in an error in state: 346. +## Ends in an error in state: 319. ## ## postfix_expression -> BUILTIN_OFFSETOF LPAREN type_name COMMA . general_identifier RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## postfix_expression -> BUILTIN_OFFSETOF LPAREN type_name COMMA . general_identifier designator_list RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -4658,7 +4661,7 @@ At this point, a member-designator is expected. translation_unit_file: PACKED LPAREN BUILTIN_OFFSETOF LPAREN VOID COMMA PRE_NAME TYPEDEF_NAME XOR_ASSIGN ## -## Ends in an error in state: 347. +## Ends in an error in state: 320. ## ## postfix_expression -> BUILTIN_OFFSETOF LPAREN type_name COMMA general_identifier . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] ## postfix_expression -> BUILTIN_OFFSETOF LPAREN type_name COMMA general_identifier . designator_list RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -4674,7 +4677,7 @@ At this point, a member-designator is expected. translation_unit_file: PACKED LPAREN BUILTIN_OFFSETOF LPAREN VOID COMMA PRE_NAME TYPEDEF_NAME LBRACK STRING_LITERAL RBRACK XOR_ASSIGN ## -## Ends in an error in state: 349. +## Ends in an error in state: 329. ## ## option(designator_list) -> designator_list . [ LBRACK DOT ] ## postfix_expression -> BUILTIN_OFFSETOF LPAREN type_name COMMA general_identifier designator_list . RPAREN [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RPAREN RIGHT_ASSIGN RIGHT RBRACK RBRACE QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA COLON BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -4701,7 +4704,7 @@ translation_unit_file: ALIGNAS LPAREN PRE_NAME XOR_ASSIGN ## translation_unit_file: ALIGNAS LPAREN VOID LPAREN VOID LPAREN PRE_NAME XOR_ASSIGN ## -## Ends in an error in state: 236. +## Ends in an error in state: 147. ## ## declarator_identifier -> PRE_NAME . low_prec TYPEDEF_NAME [ RPAREN PACKED LPAREN LBRACK ATTRIBUTE ALIGNAS ] ## declarator_identifier -> PRE_NAME . VAR_NAME [ RPAREN PACKED LPAREN LBRACK ATTRIBUTE ALIGNAS ] @@ -4722,7 +4725,7 @@ translation_unit_file: UNION PRE_NAME XOR_ASSIGN ## translation_unit_file: VOID PRE_NAME TYPEDEF_NAME LBRACE PRE_NAME XOR_ASSIGN ## -## Ends in an error in state: 434. +## Ends in an error in state: 433. ## ## general_identifier -> PRE_NAME . VAR_NAME [ COLON ] ## primary_expression -> PRE_NAME . VAR_NAME [ XOR_ASSIGN SUB_ASSIGN STAR SLASH SEMICOLON RIGHT_ASSIGN RIGHT QUESTION PTR PLUS PERCENT OR_ASSIGN NEQ MUL_ASSIGN MOD_ASSIGN MINUS LT LPAREN LEQ LEFT_ASSIGN LEFT LBRACK INC HAT GT GEQ EQEQ EQ DOT DIV_ASSIGN DEC COMMA BARBAR BAR AND_ASSIGN ANDAND AND ADD_ASSIGN ] @@ -4733,7 +4736,7 @@ translation_unit_file: VOID PRE_NAME TYPEDEF_NAME LBRACE PRE_NAME XOR_ASSIGN ## translation_unit_file: VOID PRE_NAME TYPEDEF_NAME LPAREN PRE_NAME XOR_ASSIGN ## -## Ends in an error in state: 194. +## Ends in an error in state: 105. ## ## identifier_list -> PRE_NAME . VAR_NAME [ RPAREN COMMA ] ## typedef_name -> PRE_NAME . TYPEDEF_NAME [ VOLATILE STATIC STAR RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LBRACK INLINE EXTERN CONST COMMA AUTO ATTRIBUTE ALIGNAS ] @@ -4743,7 +4746,7 @@ translation_unit_file: VOID PRE_NAME TYPEDEF_NAME LPAREN PRE_NAME XOR_ASSIGN ## translation_unit_file: VOID PRE_NAME XOR_ASSIGN ## -## Ends in an error in state: 182. +## Ends in an error in state: 93. ## ## declarator_identifier -> PRE_NAME . low_prec TYPEDEF_NAME [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] ## declarator_identifier -> PRE_NAME . VAR_NAME [ VOLATILE VOID UNSIGNED UNION UNDERSCORE_BOOL STRUCT STATIC SIGNED SHORT SEMICOLON RPAREN RESTRICT REGISTER PRE_NAME PACKED NORETURN LPAREN LONG LBRACK LBRACE INT INLINE FLOAT EXTERN EQ ENUM DOUBLE CONST COMMA COLON CHAR AUTO ATTRIBUTE ALIGNAS ] diff --git a/cparser/pre_parser.mly b/cparser/pre_parser.mly index 04fbcb94..71eaf419 100644 --- a/cparser/pre_parser.mly +++ b/cparser/pre_parser.mly @@ -275,7 +275,6 @@ unary_expression: | unary_operator cast_expression | SIZEOF unary_expression | SIZEOF LPAREN type_name RPAREN -| ALIGNOF unary_expression | ALIGNOF LPAREN type_name RPAREN {} diff --git a/debug/DwarfPrinter.ml b/debug/DwarfPrinter.ml index 09694d0b..a45fff0c 100644 --- a/debug/DwarfPrinter.ml +++ b/debug/DwarfPrinter.ml @@ -241,7 +241,7 @@ module DwarfPrinter(Target: DWARF_TARGET): let abbrev = !curr_abbrev in incr curr_abbrev;abbrev - (* Mapping from abbreviation string to abbrevaiton id *) + (* Mapping from abbreviation string to abbreviaton id *) let abbrev_mapping: (string,int) Hashtbl.t = Hashtbl.create 7 (* Look up the id of the abbreviation and add it if it is missing *) diff --git a/doc/ccomp.1 b/doc/ccomp.1 index 301b0b5f..374bd2e7 100644 --- a/doc/ccomp.1 +++ b/doc/ccomp.1 @@ -365,7 +365,7 @@ CompCert supports the following warning classes: .sp \fIc11\-extensions\fP: Feature specific to C11. -Enabled by default. +Disabled by default. .sp \fIcompare\-distinct\-pointer\-types\fP: Comparison of different pointer types. @@ -379,10 +379,22 @@ Disabled by default. Dangerous conversion of constants, e.g. literals that are too large for the given type. Enabled by default. .sp +\fIextern\-after\-definition\fP: +Extern declarations after non-extern definitions. +Enabled by default. +.sp +\fIflexible\-array\-extensions\fP: +Use of structs with flexible arrays nexted within structs or arrays. +Disabled by default. +.sp \fIgnu\-empty\-struct\fP: GNU extension for empty structs. Enabled by default. .sp +\fIignored\-attributes\fP: +Attribute declarations after definitions. +Enabled by default. +.sp \fIimplicit\-function\-declaration\fP: Deprecated implicit function declarations. Enabled by default. @@ -391,6 +403,10 @@ Enabled by default. Type of parameter or return type is implicitly assumed to be int. Enabled by default. .sp +\fIinline\-asm\-sdump\fP: +Use of unsupported features in combination with dump of abstract syntax tree. +Enabled by default. +.sp \fIint\-conversion\fP: Conversion between pointer and integer. Enabled by default. @@ -407,14 +423,30 @@ Enabled by default. Wrong return type for main. Enabled by default. .sp +\fImissing\-declarations\fP: +Declations which do not declare anything. +Enabled by default. +.sp \fIpointer\-type\-mismatch\fP: Use of incompatible pointer types in conditional expressions. Enabled by default. .sp +\fIreduced\-alignment\fP: +Alignment specifications lower than natural alignment. +Disabled by default. +.sp \fIreturn\-type\fP: Void-return statement in non-void function. Enabled by default. .sp +\fIstatic\-in\-inline\fP: +Use of static variables in non-static inline functions. +Enabled by default. +.sp +\fItentative\-incomplete\-static\fP: +Use of tentative static definitions with incomplete type. +Disabled by default. +.sp \fIunknown\-attributes\fP: Use of unsupported or unknown attributes. Enabled by default. @@ -423,6 +455,14 @@ Enabled by default. Use of unsupported or unknown pragmas. Disabled by default. .sp +\fIunused\-ais\-parameter\fP: +Unused parameter for embedded program annotations. +Disabled by default. +.sp +\fIunused\-variable\fP: +Unused local variables. +Enabled by default. +.sp \fIvarargs\fP: Promotable vararg arguments. Enabled by default. @@ -434,10 +474,6 @@ Enabled by default. \fIzero\-length\-array\fP: GNU extension for zero length arrays. Disabled by default. -.sp -\fIinline\-asm\-sdump\fP: -Use of unsupported features in combination with dump of abstract syntax tree. -Enabled by default. . .TP .B \-Wno-<warning> @@ -524,10 +560,6 @@ Save generated assembly in <file>.s. Save all generated intermediate files in <file>.<ext>. . .TP -.B \-doptions -Save the compiler configuration in <file>.opt.json. -. -.TP .B \-sdump Save abstract syntax tree of generated assembly for post-linking validation tool in <file>.json. . diff --git a/doc/coq2html.css b/doc/coq2html.css deleted file mode 100644 index c5627bfb..00000000 --- a/doc/coq2html.css +++ /dev/null @@ -1,97 +0,0 @@ -/* Classes: - h1.title the title of the page - div.coq encloses all generated body - div.doc contents of (** *) comments - div.footer footer - div.togglescript "Proof." line - div.proofscript contents of proof script - span.docright contents of (**r *) comments - span.bracket contents of [ ] within comments - span.comment contents of (* *) comments - span.kwd Coq keyword - span.tactic Coq tactic - span.id any other identifier -*/ - -body { - color: black; - background: white; -} - -h1.title { - font-size: 2em; - text-align: center -} - -h1 { - font-size: 1.5em; -} -h2 { - font-size: 1.17em; -} -h3 { - font-size: 1em; -} - -h1, h2, h3 { - font-family: sans-serif; - margin-left: -5%; -} - -div.coq { - margin-left: 15%; - margin-right: 5%; - font-family: monospace; -} - -div.doc { - margin-left: -5%; - margin-top: 0.2em; - margin-bottom: 0.5em; - font-family: serif; -} - -div.toggleproof { - font-size: 0.8em; - text-decoration: underline; -} - -div.toggleproof:hover { - cursor: pointer; -} - -div.proofscript { - font-size: 0.8em; -} - -div.footer { - margin-top: 1em; - margin-bottom: 1em; - font-size: 0.8em; - font-style: italic; -} - -span.docright { - position: absolute; - left: 60%; - width: 40%; - font-family: serif; -} - -span.bracket { - font-family: monospace; - color: #008000; -} - -span.kwd { - color: #cf1d1d; -} - -span.comment { - color: #008000; -} - -a:visited {color : #416DFF; text-decoration : none; } -a:link {color : #416DFF; text-decoration : none; } -a:hover {text-decoration : none; } -a:active {text-decoration : none; } diff --git a/doc/coq2html.js b/doc/coq2html.js deleted file mode 100644 index a840b004..00000000 --- a/doc/coq2html.js +++ /dev/null @@ -1,24 +0,0 @@ -function toggleDisplay(id) -{ - var elt = document.getElementById(id); - if (elt.style.display == 'none') { - elt.style.display = 'block'; - } else { - elt.style.display = 'none'; - } -} - -function hideAll(cls) -{ - var testClass = new RegExp("(^|s)" + cls + "(s|$)"); - var tag = tag || "*"; - var elements = document.getElementsByTagName("div"); - var current; - var length = elements.length; - for(var i=0; i<length; i++){ - current = elements[i]; - if(testClass.test(current.className)) { - current.style.display = 'none'; - } - } -} diff --git a/doc/coq2html.mll b/doc/coq2html.mll deleted file mode 100644 index a5b284e2..00000000 --- a/doc/coq2html.mll +++ /dev/null @@ -1,454 +0,0 @@ -(* *********************************************************************) -(* *) -(* The Compcert verified compiler *) -(* *) -(* Xavier Leroy, INRIA Paris-Rocquencourt *) -(* *) -(* Copyright Institut National de Recherche en Informatique et en *) -(* Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU General Public License as published by *) -(* the Free Software Foundation, either version 2 of the License, or *) -(* (at your option) any later version. This file is also distributed *) -(* under the terms of the INRIA Non-Commercial License Agreement. *) -(* *) -(* *********************************************************************) - -{ -open Printf - -(** Cross-referencing *) - -let current_module = ref "" - -type xref = - | Def of string * string (* path, type *) - | Ref of string * string * string (* unit, path, type *) - -let xref_table : (string * int, xref) Hashtbl.t = Hashtbl.create 273 -let xref_modules : (string, unit) Hashtbl.t = Hashtbl.create 29 - -let path sp id = - match sp, id with - | "<>", "<>" -> "" - | "<>", _ -> id - | _ , "<>" -> sp - | _ , _ -> sp ^ "." ^ id - -let add_module m = - (*eprintf "add_module %s\n" m;*) - Hashtbl.add xref_modules m () - -let add_reference curmod pos dp sp id ty = - (*eprintf "add_reference %s %d %s %s %s %s\n" curmod pos dp sp id ty;*) - if not (Hashtbl.mem xref_table (curmod, pos)) - then Hashtbl.add xref_table (curmod, pos) (Ref(dp, path sp id, ty)) - -let add_definition curmod pos sp id ty = - if not (Hashtbl.mem xref_table (curmod, pos)) - then Hashtbl.add xref_table (curmod, pos) (Def(path sp id, ty)) - -type link = Link of string | Anchor of string | Nolink - -let coqlib_url = "http://coq.inria.fr/library/" - -let re_coqlib = Str.regexp "Coq\\." -let re_sane_path = Str.regexp "[A-Za-z0-9_.]+$" -let re_shortname = Str.regexp "^.*\\." - -let shortname m = Str.replace_first re_shortname "" m - -let crossref m pos = - (*eprintf "crossref %s %d\n" m pos;*) - try match Hashtbl.find xref_table (m, pos) with - | Def(p, _) -> - Anchor p - | Ref(m', p, _) -> - let url = - if Hashtbl.mem xref_modules m' then - shortname m' ^ ".html" - else if Str.string_match re_coqlib m' 0 then - coqlib_url ^ m' ^ ".html" - else - raise Not_found in - if p = "" then - Link url - else if Str.string_match re_sane_path p 0 then - Link(url ^ "#" ^ p) - else - Nolink - with Not_found -> - Nolink - -(** Keywords, etc *) - -module StringSet = Set.Make(String) - -let mkset l = List.fold_right StringSet.add l StringSet.empty - -let coq_keywords = mkset [ - "forall"; "match"; "as"; "in"; "return"; "with"; "end"; "let"; - "dest"; "fun"; "if"; "then"; "else"; "Prop"; "Set"; "Type"; ":="; - "where"; "struct"; "wf"; "measure"; - "AddPath"; "Axiom"; "Abort"; "Boxed"; "Chapter"; "Check"; - "Coercion"; "CoFixpoint"; "CoInductive"; "Corollary"; "Defined"; - "Definition"; "End"; "Eval"; "Example"; "Export"; "Fact"; "Fix"; - "Fixpoint"; "Global"; "Grammar"; "Goal"; "Hint"; "Hypothesis"; - "Hypotheses"; "Resolve"; "Unfold"; "Immediate"; "Extern"; - "Implicit"; "Import"; "Inductive"; "Infix"; "Lemma"; "Let"; "Load"; - "Local"; "Ltac"; "Module"; "Module Type"; "Declare Module"; - "Include"; "Mutual"; "Parameter"; "Parameters"; "Print"; "Proof"; - "Qed"; "Record"; "Recursive"; "Remark"; "Require"; - "Save"; "Scheme"; "Induction"; "for"; "Sort"; "Section"; "Show"; - "Structure"; "Syntactic"; "Syntax"; "Tactic"; "Theorem"; "Set"; - "Types"; "Undo"; "Unset"; "Variable"; "Variables"; "Context"; - "Notation"; "Reserved"; "Tactic"; "Delimit"; "Bind"; "Open"; - "Scope"; "Boxed"; "Unboxed"; "Inline"; "Implicit Arguments"; "Add"; - "Strict"; "Typeclasses"; "Instance"; "Global Instance"; "Class"; - "Instantiation"; "subgoal"; "Program"; "Example"; "Obligation"; - "Obligations"; "Solve"; "using"; "Next"; "Instance"; "Equations"; - "Equations_nocomp" -] - -let coq_tactics = mkset [ - "intro"; "intros"; "apply"; "rewrite"; "refine"; "case"; "clear"; - "injection"; "elimtype"; "progress"; "setoid_rewrite"; "destruct"; - "destruction"; "destruct_call"; "dependent"; "elim"; - "extensionality"; "f_equal"; "generalize"; "generalize_eqs"; - "generalize_eqs_vars"; "induction"; "rename"; "move"; "omega"; - "set"; "assert"; "do"; "repeat"; "cut"; "assumption"; "exact"; - "split"; "subst"; "try"; "discriminate"; "simpl"; "unfold"; "red"; - "compute"; "at"; "in"; "by"; "reflexivity"; "symmetry"; - "transitivity"; "replace"; "setoid_replace"; "inversion"; - "inversion_clear"; "pattern"; "intuition"; "congruence"; "fail"; - "fresh"; "trivial"; "exact"; "tauto"; "firstorder"; "ring"; - "clapply"; "program_simpl"; "program_simplify"; "eapply"; "auto"; - "eauto" -] - -(** HTML generation *) - -let oc = ref stdout - -let character = function - | '<' -> output_string !oc "<" - | '>' -> output_string !oc ">" - | '&' -> output_string !oc "&" - | c -> output_char !oc c - -let section_level = function - | "*" -> 1 - | "**" -> 2 - | _ -> 3 - -let start_section sect = - fprintf !oc "<h%d>" (section_level sect) -let end_section sect = - fprintf !oc "</h%d>\n" (section_level sect) - -let start_doc_right () = - fprintf !oc "<span class=\"docright\">(* " -let end_doc_right () = - fprintf !oc " *)</span>" - -let enum_depth = ref 0 - -let set_enum_depth d = - if !enum_depth < d then begin - fprintf !oc "<ul>\n"; - fprintf !oc "<li>\n"; - incr enum_depth; - end - else if !enum_depth > d then begin - fprintf !oc "</li>\n"; - fprintf !oc "</ul>\n"; - decr enum_depth; - end - else if !enum_depth > 0 then begin - fprintf !oc "</li>\n"; - fprintf !oc "<li>\n" - end - -let start_doc () = - fprintf !oc "<div class=\"doc\">" -let end_doc () = - set_enum_depth 0; - fprintf !oc "</div>\n" - -let ident pos id = - if StringSet.mem id coq_keywords then - fprintf !oc "<span class=\"kwd\">%s</span>" id - else if StringSet.mem id coq_tactics then - fprintf !oc "<span class=\"tactic\">%s</span>" id - else match crossref !current_module pos with - | Nolink -> - fprintf !oc "<span class=\"id\">%s</span>" id - | Link p -> - fprintf !oc "<span class=\"id\"><a href=\"%s\">%s</a></span>" p id - | Anchor p -> - fprintf !oc "<span class=\"id\"><a name=\"%s\">%s</a></span>" p id - -let space s = - for _ = 1 to String.length s do fprintf !oc " " done - -let newline () = - fprintf !oc "<br/>\n" - -let dashes = function - | "-" -> set_enum_depth 1 - | "--" -> set_enum_depth 2 - | "---" -> set_enum_depth 3 - | "----" -> set_enum_depth 4 - | _ -> fprintf !oc "<hr/>\n" - -let start_verbatim () = - fprintf !oc "<pre>\n" - -let end_verbatim () = - fprintf !oc "</pre>\n" - -let start_comment () = - fprintf !oc "<span class=\"comment\">(*" - -let end_comment () = - fprintf !oc "*)</span>" - -let start_bracket () = - fprintf !oc "<span class=\"bracket\">" - -let end_bracket () = - fprintf !oc "</span>" - -let in_proof = ref false -let proof_counter = ref 0 - -let start_proof kwd = - in_proof := true; - incr proof_counter; - fprintf !oc - "<div class=\"toggleproof\" onclick=\"toggleDisplay('proof%d')\">%s</div>\n" - !proof_counter kwd; - fprintf !oc "<div class=\"proofscript\" id=\"proof%d\">\n" !proof_counter - -let end_proof kwd = - fprintf !oc "%s</div>\n" kwd; - in_proof := false - -let start_html_page modname = - fprintf !oc "\ -<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> -<html xmlns=\"http://www.w3.org/1999/xhtml\"> - -<head> -<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> -<title>Module %s</title> -<meta name=\"description\" content=\"Documentation of Coq module %s\" /> -<link href=\"coq2html.css\" rel=\"stylesheet\" type=\"text/css\" /> -<script type=\"text/javascript\" src=\"coq2html.js\"> </script> -</head> - -<body onload=\"hideAll('proofscript')\"> -<h1 class=\"title\">Module %s</h1> -<div class=\"coq\"> -" modname modname modname - -let end_html_page () = - fprintf !oc "\ -</div> -<div class=\"footer\"><hr/>Generated by coq2html</div> -</body> -</html> -" - -} - -let space = [' ' '\t'] -let ident = ['A'-'Z' 'a'-'z' '_'] ['A'-'Z' 'a'-'z' '0'-'9' '_']* -let path = ident ("." ident)* -let start_proof = ("Proof" space* ".") | ("Proof" space+ "with") | ("Next" space+ "Obligation.") -let end_proof = "Qed." | "Defined." | "Save." | "Admitted." | "Abort." - -let xref = ['A'-'Z' 'a'-'z' '0'-'9' '_' '.']+ | "<>" -let integer = ['0'-'9']+ - -rule coq_bol = parse - | space* (start_proof as sp) - { start_proof sp; - skip_newline lexbuf } - | space* "(** " ("*"+ as sect) - { start_section sect; - doc lexbuf; - end_section sect; - skip_newline lexbuf } - | space* "(** " - { start_doc(); - doc lexbuf; - end_doc(); - skip_newline lexbuf } - | space* "(*" - { comment lexbuf; - skip_newline lexbuf } - | eof - { () } - | space* as s - { space s; - coq lexbuf } - -and skip_newline = parse - | space* "\n" - { coq_bol lexbuf } - | "" - { coq lexbuf } - -and coq = parse - | end_proof as ep - { end_proof ep; - skip_newline lexbuf } - | "(**r " - { start_doc_right(); - doc lexbuf; - end_doc_right(); - coq lexbuf } - | "(*" - { if !in_proof then start_comment(); - comment lexbuf; - coq lexbuf } - | path as id - { ident (Lexing.lexeme_start lexbuf) id; coq lexbuf } - | "\n" - { newline(); coq_bol lexbuf } - | eof - { () } - | _ as c - { character c; coq lexbuf } - -and bracket = parse - | ']' - { () } - | '[' - { character '['; bracket lexbuf; character ']'; bracket lexbuf } - | path as id - { ident (Lexing.lexeme_start lexbuf) id; bracket lexbuf } - | eof - { () } - | _ as c - { character c; bracket lexbuf } - -and comment = parse - | "*)" - { if !in_proof then end_comment() } - | "(*" - { if !in_proof then start_comment(); - comment lexbuf; comment lexbuf } - | eof - { () } - | "\n" - { if !in_proof then newline(); - comment lexbuf } - | space* as s - { if !in_proof then space s; - comment lexbuf } - | eof - { () } - | _ as c - { if !in_proof then character c; - comment lexbuf } - -and doc_bol = parse - | "<<" space* "\n" - { start_verbatim(); - verbatim lexbuf; - end_verbatim(); - doc_bol lexbuf } - | "-"+ as d - { dashes d; doc lexbuf } - | "\n" - { set_enum_depth 0; doc_bol lexbuf } - | "" - { doc lexbuf } - -and doc = parse - | "*)" - { () } - | "\n" - { character '\n'; doc_bol lexbuf } - | "[" - { start_bracket(); bracket lexbuf; end_bracket(); doc lexbuf } - | "$" [^ '\n' '$']* "$" - { doc lexbuf } - | "#" ([^ '\n' '#']* as html) "#" - { output_string !oc html; doc lexbuf } - | eof - { () } - | _ as c - { character c; doc lexbuf } - -and verbatim = parse - | "\n>>" space* "\n" - { () } - | eof - { () } - | _ as c - { character c; verbatim lexbuf } - -and globfile = parse - | eof - { () } - | "F" (path as m) space* "\n" - { current_module := m; add_module m; - globfile lexbuf } - | "R" (integer as pos) ":" (integer) - space+ (xref as dp) - space+ (xref as sp) - space+ (xref as id) - space+ (ident as ty) - space* "\n" - { add_reference !current_module (int_of_string pos) dp sp id ty; - globfile lexbuf } - | (ident as ty) - space+ (integer as pos) ":" (integer) - space+ (xref as sp) - space+ (xref as id) - space* "\n" - { add_definition !current_module (int_of_string pos) sp id ty; - globfile lexbuf } - | [^ '\n']* "\n" - { globfile lexbuf } - -{ - -let output_name = ref "-" - -let process_file f = - if Filename.check_suffix f ".v" then begin - let pref_f = Filename.chop_suffix f ".v" in - let base_f = Filename.basename pref_f in - current_module := - "compcert." ^ Str.global_replace (Str.regexp "/") "." pref_f; - let ic = open_in f in - if !output_name = "-" then - oc := stdout - else - oc := open_out (Str.global_replace (Str.regexp "%") base_f !output_name); - start_html_page base_f; - coq_bol (Lexing.from_channel ic); - end_html_page(); - if !output_name <> "-" then (close_out !oc; oc := stdout); - close_in ic - end else - if Filename.check_suffix f ".glob" then begin - current_module := ""; - let ic = open_in f in - globfile (Lexing.from_channel ic); - close_in ic - end else begin - eprintf "Don't know what to do with file %s\n" f; - exit 2 - end - -let _ = - Arg.parse [ - "-o", Arg.String (fun s -> output_name := s), - " <output> Set output file ('%' replaced by module name)" - ] process_file - "Usage: coq2html [options] <file.glob> file.v\nOptions are:" -} diff --git a/doc/coqdoc.css b/doc/coqdoc.css deleted file mode 100644 index f2ae96da..00000000 --- a/doc/coqdoc.css +++ /dev/null @@ -1,62 +0,0 @@ -body { - color: black; - background: white; - margin-left: 15%; - margin-right: 5%; -} - -#main a.idref:visited {color : #416DFF; text-decoration : none; } -#main a.idref:link {color : #416DFF; text-decoration : none; } -#main a.idref:hover {text-decoration : none; } -#main a.idref:active {text-decoration : none; } - -#main a.modref:visited {color : #416DFF; text-decoration : none; } -#main a.modref:link {color : #416DFF; text-decoration : none; } -#main a.modref:hover {text-decoration : none; } -#main a.modref:active {text-decoration : none; } - -#main .keyword { color : #cf1d1d } - -#main .doc { - margin-left: -5%; -} - -#main span.docright { - position: absolute; - left: 60%; - width: 40% -} - -h1.libtitle { - font-size: 2em; - margin-left: -15%; - margin-right: -5%; - text-align: center -} - -h1 { - font-size: 1.5em; -} -h2 { - font-size: 1.17em; -} - -h1, h2 { - font-family: sans-serif; -} - -.doc code { - color: #008000; -} - -/* Pied de page */ - -hr { margin-left: -15%; margin-right:-5%; } - -#footer { font-size: 0.83em; - font-family: sans-serif; } - -#footer a:visited { color: blue; } -#footer a:link { text-decoration: none; - color: #888888; } - diff --git a/doc/index.html b/doc/index.html index 34583bd3..72875e1a 100644 --- a/doc/index.html +++ b/doc/index.html @@ -24,7 +24,7 @@ a:active {color : Red; text-decoration : underline; } <H1 align="center">The CompCert verified compiler</H1> <H2 align="center">Commented Coq development</H2> -<H3 align="center">Version 3.2, 2018-01-15</H3> +<H3 align="center">Version 3.4, 2018-09-17</H3> <H2>Introduction</H2> @@ -69,73 +69,73 @@ following <A HREF="LICENSE">license</A>. <H3>General-purpose libraries, data structures and algorithms</H3> <UL> -<LI> <A HREF="html/Coqlib.html">Coqlib</A>: addendum to the Coq standard library. -<LI> <A HREF="html/Maps.html">Maps</A>: finite maps. -<LI> <A HREF="html/Integers.html">Integers</A>: machine integers. -<LI> <A HREF="html/Floats.html">Floats</A>: machine floating-point numbers. -<LI> <A HREF="html/Iteration.html">Iteration</A>: various forms of "while" loops. -<LI> <A HREF="html/Ordered.html">Ordered</A>: construction of +<LI> <A HREF="html/compcert.lib.Coqlib.html">Coqlib</A>: addendum to the Coq standard library. +<LI> <A HREF="html/compcert.lib.Maps.html">Maps</A>: finite maps. +<LI> <A HREF="html/compcert.lib.Integers.html">Integers</A>: machine integers. +<LI> <A HREF="html/compcert.lib.Floats.html">Floats</A>: machine floating-point numbers. +<LI> <A HREF="html/compcert.lib.Iteration.html">Iteration</A>: various forms of "while" loops. +<LI> <A HREF="html/compcert.lib.Ordered.html">Ordered</A>: construction of ordered types. -<LI> <A HREF="html/Lattice.html">Lattice</A>: construction of +<LI> <A HREF="html/compcert.lib.Lattice.html">Lattice</A>: construction of semi-lattices. -<LI> <A HREF="html/Kildall.html">Kildall</A>: resolution of dataflow +<LI> <A HREF="html/compcert.backend.Kildall.html">Kildall</A>: resolution of dataflow inequations by fixpoint iteration. -<LI> <A HREF="html/UnionFind.html">UnionFind</A>: a persistent union-find data structure. -<LI> <A HREF="html/Postorder.html">Postorder</A>: postorder numbering of a directed graph. +<LI> <A HREF="html/compcert.lib.UnionFind.html">UnionFind</A>: a persistent union-find data structure. +<LI> <A HREF="html/compcert.lib.Postorder.html">Postorder</A>: postorder numbering of a directed graph. </UL> <H3>Definitions and theorems used in many parts of the development</H3> <UL> -<LI> <A HREF="html/Errors.html">Errors</A>: the Error monad. -<LI> <A HREF="html/AST.html">AST</A>: identifiers, whole programs and other +<LI> <A HREF="html/compcert.common.Errors.html">Errors</A>: the Error monad. +<LI> <A HREF="html/compcert.common.AST.html">AST</A>: identifiers, whole programs and other common elements of abstract syntaxes. -<LI> <A HREF="html/Linking.html">Linking</A>: generic framework to define syntactic linking over the CompCert languages. -<LI> <A HREF="html/Values.html">Values</A>: run-time values. -<LI> <A HREF="html/Events.html">Events</A>: observable events and traces. -<LI> <A HREF="html/Memory.html">Memory</A>: memory model. <BR> -See also: <A HREF="html/Memdata.html">Memdata</A> (in-memory representation of data). -<LI> <A HREF="html/Globalenvs.html">Globalenvs</A>: global execution environments. -<LI> <A HREF="html/Smallstep.html">Smallstep</A>: tools for small-step semantics. -<LI> <A HREF="html/Behaviors.html">Behaviors</A>: from small-step semantics to observable behaviors of programs. -<LI> <A HREF="html/Determinism.html">Determinism</A>: determinism properties of small-step semantics. -<LI> <A HREF="html/Op.html"><I>Op</I></A>: operators, addressing modes and their +<LI> <A HREF="html/compcert.common.Linking.html">Linking</A>: generic framework to define syntactic linking over the CompCert languages. +<LI> <A HREF="html/compcert.common.Values.html">Values</A>: run-time values. +<LI> <A HREF="html/compcert.common.Events.html">Events</A>: observable events and traces. +<LI> <A HREF="html/compcert.common.Memory.html">Memory</A>: memory model. <BR> +See also: <A HREF="html/compcert.common.Memdata.html">Memdata</A> (in-memory representation of data). +<LI> <A HREF="html/compcert.common.Globalenvs.html">Globalenvs</A>: global execution environments. +<LI> <A HREF="html/compcert.common.Smallstep.html">Smallstep</A>: tools for small-step semantics. +<LI> <A HREF="html/compcert.common.Behaviors.html">Behaviors</A>: from small-step semantics to observable behaviors of programs. +<LI> <A HREF="html/compcert.common.Determinism.html">Determinism</A>: determinism properties of small-step semantics. +<LI> <A HREF="html/compcert.powerpc.Op.html"><I>Op</I></A>: operators, addressing modes and their semantics. -<LI> <A HREF="html/Unityping.html">Unityping</A>: a solver for atomic unification constraints. +<LI> <A HREF="html/compcert.common.Unityping.html">Unityping</A>: a solver for atomic unification constraints. </UL> <H3>Source, intermediate and target languages: syntax and semantics</H3> <UL> <LI> The CompCert C source language: -<A HREF="html/Csyntax.html">syntax</A> and -<A HREF="html/Csem.html">semantics</A> and -<A HREF="html/Cstrategy.html">determinized semantics</A> and -<A HREF="html/Ctyping.html">type system</A>.<BR> -See also: <A HREF="html/Ctypes.html">type expressions</A> and -<A HREF="html/Cop.html">operators (syntax and semantics)</A>.<BR> -See also: <A HREF="html/Cexec.html">reference interpreter</A>. -<LI> <A HREF="html/Clight.html">Clight</A>: a simpler version of CompCert C where expressions contain no side-effects. -<LI> <A HREF="html/Csharpminor.html">Csharpminor</A>: low-level +<A HREF="html/compcert.cfrontend.Csyntax.html">syntax</A> and +<A HREF="html/compcert.cfrontend.Csem.html">semantics</A> and +<A HREF="html/compcert.cfrontend.Cstrategy.html">determinized semantics</A> and +<A HREF="html/compcert.cfrontend.Ctyping.html">type system</A>.<BR> +See also: <A HREF="html/compcert.cfrontend.Ctypes.html">type expressions</A> and +<A HREF="html/compcert.cfrontend.Cop.html">operators (syntax and semantics)</A>.<BR> +See also: <A HREF="html/compcert.cfrontend.Cexec.html">reference interpreter</A>. +<LI> <A HREF="html/compcert.cfrontend.Clight.html">Clight</A>: a simpler version of CompCert C where expressions contain no side-effects. +<LI> <A HREF="html/compcert.cfrontend.Csharpminor.html">Csharpminor</A>: low-level structured language. -<LI> <A HREF="html/Cminor.html">Cminor</A>: low-level structured +<LI> <A HREF="html/compcert.backend.Cminor.html">Cminor</A>: low-level structured language, with explicit stack allocation of certain local variables. -<LI> <A HREF="html/CminorSel.html">CminorSel</A>: like Cminor, +<LI> <A HREF="html/compcert.backend.CminorSel.html">CminorSel</A>: like Cminor, with machine-specific operators and addressing modes. -<LI> <A HREF="html/RTL.html">RTL</A>: register transfer language (3-address +<LI> <A HREF="html/compcert.backend.RTL.html">RTL</A>: register transfer language (3-address code, control-flow graph, infinitely many pseudo-registers). <BR> -See also: <A HREF="html/Registers.html">Registers</A> (representation of +See also: <A HREF="html/compcert.backend.Registers.html">Registers</A> (representation of pseudo-registers). -<LI> <A HREF="html/LTL.html">LTL</A>: location transfer language (3-address +<LI> <A HREF="html/compcert.backend.LTL.html">LTL</A>: location transfer language (3-address code, control-flow graph of basic blocks, finitely many physical registers, infinitely many stack slots). <BR> -See also: <A HREF="html/Locations.html">Locations</A> (representation of -locations) and <A HREF="html/Machregs.html"><I>Machregs</I></A> (description of processor registers). -<LI> <A HREF="html/Linear.html">Linear</A>: like LTL, but the CFG is +See also: <A HREF="html/compcert.backend.Locations.html">Locations</A> (representation of +locations) and <A HREF="html/compcert.powerpc.Machregs.html"><I>Machregs</I></A> (description of processor registers). +<LI> <A HREF="html/compcert.backend.Linear.html">Linear</A>: like LTL, but the CFG is replaced by a linear list of instructions with explicit branches and labels. -<LI> <A HREF="html/Mach.html">Mach</A>: like Linear, with a more concrete +<LI> <A HREF="html/compcert.backend.Mach.html">Mach</A>: like Linear, with a more concrete view of the activation record. -<LI> <A HREF="html/Asm.html"><I>Asm</I></A>: abstract syntax for PowerPC assembly +<LI> <A HREF="html/compcert.powerpc.Asm.html"><I>Asm</I></A>: abstract syntax for PowerPC assembly code. </UL> @@ -153,170 +153,170 @@ code. <TD>Pulling side-effects out of expressions;<br> fixing an evaluation order</TD> <TD>CompCert C to Clight</TD> - <TD><A HREF="html/SimplExpr.html">SimplExpr</A></TD> - <TD><A HREF="html/SimplExprspec.html">SimplExprspec</A><br> - <A HREF="html/SimplExprproof.html">SimplExprproof</A></TD> + <TD><A HREF="html/compcert.cfrontend.SimplExpr.html">SimplExpr</A></TD> + <TD><A HREF="html/compcert.cfrontend.SimplExprspec.html">SimplExprspec</A><br> + <A HREF="html/compcert.cfrontend.SimplExprproof.html">SimplExprproof</A></TD> </TR> <TR valign="top"> <TD>Pulling non-adressable scalar local variables out of memory</TD> <TD>Clight to Clight</TD> - <TD><A HREF="html/SimplLocals.html">SimplLocals</A></TD> - <TD><A HREF="html/SimplLocalsproof.html">SimplLocalsproof</A></TD> + <TD><A HREF="html/compcert.cfrontend.SimplLocals.html">SimplLocals</A></TD> + <TD><A HREF="html/compcert.cfrontend.SimplLocalsproof.html">SimplLocalsproof</A></TD> </TR> <TR valign="top"> <TD>Simplification of control structures; <br> explication of type-dependent computations</TD> <TD>Clight to Csharpminor</TD> - <TD><A HREF="html/Cshmgen.html">Cshmgen</A></TD> - <TD><A HREF="html/Cshmgenproof.html">Cshmgenproof</A></TD> + <TD><A HREF="html/compcert.cfrontend.Cshmgen.html">Cshmgen</A></TD> + <TD><A HREF="html/compcert.cfrontend.Cshmgenproof.html">Cshmgenproof</A></TD> </TR> <TR valign="top"> <TD>Stack allocation of local variables<br> whose address is taken;<br> simplification of switch statements</TD> <TD>Csharpminor to Cminor</TD> - <TD><A HREF="html/Cminorgen.html">Cminorgen</A></TD> - <TD><A HREF="html/Cminorgenproof.html">Cminorgenproof</A></TD> + <TD><A HREF="html/compcert.cfrontend.Cminorgen.html">Cminorgen</A></TD> + <TD><A HREF="html/compcert.cfrontend.Cminorgenproof.html">Cminorgenproof</A></TD> </TR> <TR valign="top"> <TD>Recognition of operators<br>and addressing modes</TD> <TD>Cminor to CminorSel</TD> - <TD><A HREF="html/Selection.html">Selection</A><br> - <A HREF="html/SelectOp.html"><I>SelectOp</I></A><br> - <A HREF="html/SelectLong.html"><I>SelectLong</I></A><br> - <A HREF="html/SelectDiv.html">SelectDiv</A><br> - <A HREF="html/SplitLong.html">SplitLong</A></TD> - <TD><A HREF="html/Selectionproof.html">Selectionproof</A><br> - <A HREF="html/SelectOpproof.html"><I>SelectOpproof</I></A><br> - <A HREF="html/SelectLongproof.html"><I>SelectLongproof</I></A><br> - <A HREF="html/SelectDivproof.html">SelectDivproof</A><br> - <A HREF="html/SplitLongproof.html">SplitLongproof</A></TD> + <TD><A HREF="html/compcert.backend.Selection.html">Selection</A><br> + <A HREF="html/Selectcompcert.powerpc.Op.html"><I>SelectOp</I></A><br> + <A HREF="html/compcert.powerpc.SelectLong.html"><I>SelectLong</I></A><br> + <A HREF="html/compcert.backend.SelectDiv.html">SelectDiv</A><br> + <A HREF="html/compcert.backend.SplitLong.html">SplitLong</A></TD> + <TD><A HREF="html/compcert.backend.Selectionproof.html">Selectionproof</A><br> + <A HREF="html/compcert.powerpc.SelectOpproof.html"><I>SelectOpproof</I></A><br> + <A HREF="html/compcert.powerpc.SelectLongproof.html"><I>SelectLongproof</I></A><br> + <A HREF="html/compcert.backend.SelectDivproof.html">SelectDivproof</A><br> + <A HREF="html/compcert.backend.SplitLongproof.html">SplitLongproof</A></TD> </TR> <TR valign="top"> <TD>Construction of the CFG, <br>3-address code generation</TD> <TD>CminorSel to RTL</TD> - <TD><A HREF="html/RTLgen.html">RTLgen</A></TD> - <TD><A HREF="html/RTLgenspec.html">RTLgenspec</A><BR> - <A HREF="html/RTLgenproof.html">RTLgenproof</A></TD> + <TD><A HREF="html/compcert.backend.RTLgen.html">RTLgen</A></TD> + <TD><A HREF="html/compcert.backend.RTLgenspec.html">RTLgenspec</A><BR> + <A HREF="html/compcert.backend.RTLgenproof.html">RTLgenproof</A></TD> </TR> <TR valign="top"> <TD>Recognition of tail calls</TD> <TD>RTL to RTL</TD> - <TD><A HREF="html/Tailcall.html">Tailcall</A></TD> - <TD><A HREF="html/Tailcallproof.html">Tailcallproof</A></TD> + <TD><A HREF="html/compcert.backend.Tailcall.html">Tailcall</A></TD> + <TD><A HREF="html/compcert.backend.Tailcallproof.html">Tailcallproof</A></TD> </TR> <TR valign="top"> <TD>Function inlining</TD> <TD>RTL to RTL</TD> - <TD><A HREF="html/Inlining.html">Inlining</A></TD> - <TD><A HREF="html/Inliningspec.html">Inliningspec</A><BR> - <A HREF="html/Inliningproof.html">Inliningproof</A></TD> + <TD><A HREF="html/compcert.backend.Inlining.html">Inlining</A></TD> + <TD><A HREF="html/compcert.backend.Inliningspec.html">Inliningspec</A><BR> + <A HREF="html/compcert.backend.Inliningproof.html">Inliningproof</A></TD> </TR> <TR valign="top"> <TD>Postorder renumbering of the CFG</TD> <TD>RTL to RTL</TD> - <TD><A HREF="html/Renumber.html">Renumber</A></TD> - <TD><A HREF="html/Renumberproof.html">Renumberproof</A></TD> + <TD><A HREF="html/compcert.backend.Renumber.html">Renumber</A></TD> + <TD><A HREF="html/compcert.backend.Renumberproof.html">Renumberproof</A></TD> </TR> <TR valign="top"> <TD>Constant propagation</TD> <TD>RTL to RTL</TD> - <TD><A HREF="html/Constprop.html">Constprop</A><br> - <A HREF="html/ConstpropOp.html"><I>ConstpropOp</I></A></TD> - <TD><A HREF="html/Constpropproof.html">Constpropproof</A><br> - <A HREF="html/ConstpropOpproof.html"><I>ConstproppOproof</I></A></TD> + <TD><A HREF="html/compcert.backend.Constprop.html">Constprop</A><br> + <A HREF="html/compcert.powerpc.Constpropcompcert.powerpc.Op.html"><I>ConstpropOp</I></A></TD> + <TD><A HREF="html/compcert.backend.Constpropproof.html">Constpropproof</A><br> + <A HREF="html/compcert.powerpc.ConstpropOpproof.html"><I>ConstproppOproof</I></A></TD> </TR> <TR valign="top"> <TD>Common subexpression elimination</TD> <TD>RTL to RTL</TD> - <TD><A HREF="html/CSE.html">CSE</A><BR> - <A HREF="html/CombineOp.html"><I>CombineOp</I></A></TD> - <TD><A HREF="html/CSEproof.html">CSEproof</A><BR> - <A HREF="html/CombineOpproof.html"><I>CombineOpproof</I></A></TD> + <TD><A HREF="html/compcert.backend.CSE.html">CSE</A><BR> + <A HREF="html/compcert.powerpc.Combinecompcert.powerpc.Op.html"><I>CombineOp</I></A></TD> + <TD><A HREF="html/compcert.backend.CSEproof.html">CSEproof</A><BR> + <A HREF="html/compcert.powerpc.CombineOpproof.html"><I>CombineOpproof</I></A></TD> </TR> <TR valign="top"> <TD>Redundancy elimination</TD> <TD>RTL to RTL</TD> - <TD><A HREF="html/Deadcode.html">Deadcode</A></TD> - <TD><A HREF="html/Deadcodeproof.html">Deadcodeproof</A></TD> + <TD><A HREF="html/compcert.backend.Deadcode.html">Deadcode</A></TD> + <TD><A HREF="html/compcert.backend.Deadcodeproof.html">Deadcodeproof</A></TD> </TR> <TR valign="top"> <TD>Removal of unused static globals</TD> <TD>RTL to RTL</TD> - <TD><A HREF="html/Unusedglob.html">Unusedglob</A></TD> - <TD><A HREF="html/Unusedglobproof.html">Unusedglobproof</A></TD> + <TD><A HREF="html/compcert.backend.Unusedglob.html">Unusedglob</A></TD> + <TD><A HREF="html/compcert.backend.Unusedglobproof.html">Unusedglobproof</A></TD> </TR> <TR valign="top"> <TD>Register allocation (validation a posteriori)</TD> <TD>RTL to LTL</TD> - <TD><A HREF="html/Allocation.html">Allocation</A></TD> - <TD><A HREF="html/Allocproof.html">Allocproof</A></TD> + <TD><A HREF="html/compcert.backend.Allocation.html">Allocation</A></TD> + <TD><A HREF="html/compcert.backend.Allocproof.html">Allocproof</A></TD> </TR> <TR valign="top"> <TD>Branch tunneling</TD> <TD>LTL to LTL</TD> - <TD><A HREF="html/Tunneling.html">Tunneling</A></TD> - <TD><A HREF="html/Tunnelingproof.html">Tunnelingproof</A></TD> + <TD><A HREF="html/compcert.backend.Tunneling.html">Tunneling</A></TD> + <TD><A HREF="html/compcert.backend.Tunnelingproof.html">Tunnelingproof</A></TD> </TR> <TR valign="top"> <TD>Linearization of the CFG</TD> <TD>LTL to Linear</TD> - <TD><A HREF="html/Linearize.html">Linearize</A></TD> - <TD><A HREF="html/Linearizeproof.html">Linearizeproof</A></TD> + <TD><A HREF="html/compcert.backend.Linearize.html">Linearize</A></TD> + <TD><A HREF="html/compcert.backend.Linearizeproof.html">Linearizeproof</A></TD> </TR> <TR valign="top"> <TD>Removal of unreferenced labels</TD> <TD>Linear to Linear</TD> - <TD><A HREF="html/CleanupLabels.html">CleanupLabels</A></TD> - <TD><A HREF="html/CleanupLabelsproof.html">CleanupLabelsproof</A></TD> + <TD><A HREF="html/compcert.backend.CleanupLabels.html">CleanupLabels</A></TD> + <TD><A HREF="html/compcert.backend.CleanupLabelsproof.html">CleanupLabelsproof</A></TD> </TR> <TR valign="top"> <TD>Synthesis of debugging information</TD> <TD>Linear to Linear</TD> - <TD><A HREF="html/Debugvar.html">Debugvar</A></TD> - <TD><A HREF="html/Debugvarproof.html">Debugvarproof</A></TD> + <TD><A HREF="html/compcert.backend.Debugvar.html">Debugvar</A></TD> + <TD><A HREF="html/compcert.backend.Debugvarproof.html">Debugvarproof</A></TD> </TR> <TR valign="top"> <TD>Laying out the activation records</TD> <TD>Linear to Mach</TD> - <TD><A HREF="html/Stacking.html">Stacking</A><BR> - <A HREF="html/Bounds.html">Bounds</A><BR> - <A HREF="html/Stacklayout.html"><I>Stacklayout</I></A></TD> - <TD><A HREF="html/Stackingproof.html">Stackingproof</A><br> - <A HREF="html/Separation.html">Separation</A></TD> + <TD><A HREF="html/compcert.backend.Stacking.html">Stacking</A><BR> + <A HREF="html/compcert.backend.Bounds.html">Bounds</A><BR> + <A HREF="html/compcert.powerpc.Stacklayout.html"><I>Stacklayout</I></A></TD> + <TD><A HREF="html/compcert.backend.Stackingproof.html">Stackingproof</A><br> + <A HREF="html/compcert.common.Separation.html">Separation</A></TD> </TR> <TR valign="top"> <TD>Emission of assembly code</TD> <TD>Mach to Asm</TD> - <TD><A HREF="html/Asmgen.html"><I>Asmgen</I></A></TD> - <TD><A HREF="html/Asmgenproof0.html"><I>Asmgenproof0</I></A><BR> - <A HREF="html/Asmgenproof1.html"><I>Asmgenproof1</I></A><BR> - <A HREF="html/Asmgenproof.html"><I>Asmgenproof</I></A></TD> + <TD><A HREF="html/compcert.powerpc.Asmgen.html"><I>Asmgen</I></A></TD> + <TD><A HREF="html/compcert.backend.Asmgenproof0.html"><I>Asmgenproof0</I></A><BR> + <A HREF="html/compcert.powerpc.Asmgenproof1.html"><I>Asmgenproof1</I></A><BR> + <A HREF="html/compcert.powerpc.Asmgenproof.html"><I>Asmgenproof</I></A></TD> </TR> </TABLE> <H3>All together</H3> <UL> -<LI> <A HREF="html/Compiler.html">Compiler</A>: composing the passes together; +<LI> <A HREF="html/compcert.driver.Compiler.html">Compiler</A>: composing the passes together; whole-compiler semantic preservation theorems. -<LI> <A HREF="html/Complements.html">Complements</A>: interesting consequences of the semantic preservation theorems. +<LI> <A HREF="html/compcert.driver.Complements.html">Complements</A>: interesting consequences of the semantic preservation theorems. </UL> <H3>Static analyses</H3> @@ -325,23 +325,23 @@ The following static analyses are performed over the RTL intermediate representation to support optimizations such as constant propagation, CSE, and dead code elimination. <UL> -<LI> <A HREF="html/Liveness.html">Liveness</A>: liveness analysis</A>. -<LI> <A HREF="html/ValueAnalysis.html">ValueAnalysis</A>: value and alias analysis</A> <BR> -See also: <A HREF="html/ValueDomain.html">ValueDomain</A>: the abstract domain for value analysis.<BR> -See also: <A HREF="html/ValueAOp.html"><I>ValueAOp</I></A>: processor-dependent parts of value analysis. -<LI> <A HREF="html/Deadcode.html">Deadcode</A>: neededness analysis</A> <BR> -See also: <A HREF="html/NeedDomain.html">NeedDomain</A>: the abstract domain for neededness analysis.<BR> -See also: <A HREF="html/NeedOp.html"><I>NeedOp</I></A>: processor-dependent parts of neededness analysis. +<LI> <A HREF="html/compcert.backend.Liveness.html">Liveness</A>: liveness analysis</A>. +<LI> <A HREF="html/compcert.backend.ValueAnalysis.html">ValueAnalysis</A>: value and alias analysis</A> <BR> +See also: <A HREF="html/compcert.backend.ValueDomain.html">ValueDomain</A>: the abstract domain for value analysis.<BR> +See also: <A HREF="html/ValueAcompcert.powerpc.Op.html"><I>ValueAOp</I></A>: processor-dependent parts of value analysis. +<LI> <A HREF="html/compcert.backend.Deadcode.html">Deadcode</A>: neededness analysis</A> <BR> +See also: <A HREF="html/compcert.backend.NeedDomain.html">NeedDomain</A>: the abstract domain for neededness analysis.<BR> +See also: <A HREF="html/compcert.powerpc.Needcompcert.powerpc.Op.html"><I>NeedOp</I></A>: processor-dependent parts of neededness analysis. </UL> <H3>Type systems</H3> -The <A HREF="html/Ctyping.html">type system of CompCert C</A> is fully formalized. For some intermediate languages of the back-end, simpler type systems are used to statically capture well-formedness conditions. +The <A HREF="html/compcert.cfrontend.Ctyping.html">type system of CompCert C</A> is fully formalized. For some intermediate languages of the back-end, simpler type systems are used to statically capture well-formedness conditions. <UL> -<LI> <A HREF="html/Ctyping.html">RTLtyping</A>: typing for CompCert C + type-checking functions. -<LI> <A HREF="html/RTLtyping.html">RTLtyping</A>: typing for RTL + type +<LI> <A HREF="html/compcert.cfrontend.Ctyping.html">Ctyping</A>: typing for CompCert C + type-checking functions. +<LI> <A HREF="html/compcert.backend.RTLtyping.html">RTLtyping</A>: typing for RTL + type reconstruction. -<LI> <A HREF="html/Lineartyping.html">Lineartyping</A>: typing for Linear. +<LI> <A HREF="html/compcert.backend.Lineartyping.html">Lineartyping</A>: typing for Linear. </UL> <HR> diff --git a/driver/Assembler.mli b/driver/Assembler.mli index d8a4e32b..4f2e95ae 100644 --- a/driver/Assembler.mli +++ b/driver/Assembler.mli @@ -15,7 +15,7 @@ val assemble: string -> string -> unit (** From asm to object file *) val assembler_actions: (Commandline.pattern * Commandline.action) list - (** Commandline optins affecting the assembler *) + (** Commandline options affecting the assembler *) val assembler_help: string (** Commandline help description *) diff --git a/driver/Commandline.ml b/driver/Commandline.ml index f139212d..75ca1683 100644 --- a/driver/Commandline.ml +++ b/driver/Commandline.ml @@ -74,7 +74,7 @@ let parse_array spec argv first last = with Not_found -> find_action s inexact_cases in match optact with | None -> - let msg = sprintf "Unknown argument `%s'" s in + let msg = sprintf "unknown argument `%s'" s in raise (CmdError msg) | Some(Set r) -> r := true; parse (i+1) @@ -86,7 +86,7 @@ let parse_array spec argv first last = if i + 1 <= last then begin fn argv.(i+1); parse (i+2) end else begin - let msg = sprintf "Option `%s' expects an argument" s in + let msg = sprintf "option `%s' expects an argument" s in raise (CmdError msg) end | Some(Integer fn) -> @@ -95,19 +95,19 @@ let parse_array spec argv first last = try int_of_string argv.(i+1) with Failure _ -> - let msg = sprintf "Argument to option `%s' must be an integer" s in + let msg = sprintf "argument to option `%s' must be an integer" s in raise (CmdError msg) in fn n; parse (i+2) end else begin - let msg = sprintf "Option `%s' expects an argument" s in + let msg = sprintf "option `%s' expects an argument" s in raise (CmdError msg) end | Some (Ignore) -> if i + 1 <= last then begin parse (i+2) end else begin - let msg = sprintf "Option `%s' expects an argument" s in + let msg = sprintf "option `%s' expects an argument" s in raise (CmdError msg) end | Some (Unit f) -> f (); parse (i+1) @@ -131,7 +131,7 @@ let long_int_action key s = try int_of_string s with Failure _ -> - let msg = sprintf "Argument to option `%s' must be an integer" key in + let msg = sprintf "argument to option `%s' must be an integer" key in raise (CmdError msg) let longopt_int key f = diff --git a/driver/Complements.v b/driver/Complements.v index d1bea1b3..3660fff0 100644 --- a/driver/Complements.v +++ b/driver/Complements.v @@ -13,30 +13,20 @@ (** Corollaries of the main semantic preservation theorem. *) Require Import Classical. -Require Import Coqlib. -Require Import AST. -Require Import Integers. -Require Import Values. -Require Import Events. -Require Import Globalenvs. -Require Import Smallstep. -Require Import Behaviors. -Require Import Csyntax. -Require Import Csem. -Require Import Cstrategy. -Require Import Clight. -Require Import Cminor. -Require Import RTL. -Require Import Asm. +Require Import Coqlib Errors. +Require Import AST Linking Events Smallstep Behaviors. +Require Import Csyntax Csem Cstrategy Asm. Require Import Compiler. -Require Import Errors. (** * Preservation of whole-program behaviors *) (** From the simulation diagrams proved in file [Compiler]. it follows that whole-program observable behaviors are preserved in the following sense. First, every behavior of the generated assembly code is matched by - a behavior of the source C code. *) + a behavior of the source C code. The behavior [beh] of the assembly + code is either identical to the behavior [beh'] of the source C code + or ``improves upon'' [beh'] by replacing a ``going wrong'' behavior + with a more defined behavior. *) Theorem transf_c_program_preservation: forall p tp beh, @@ -48,8 +38,9 @@ Proof. apply transf_c_program_correct; auto. Qed. -(** As a corollary, if the source C code cannot go wrong, the behavior of the - generated assembly code is one of the possible behaviors of the source C code. *) +(** As a corollary, if the source C code cannot go wrong, i.e. is free of + undefined behaviors, the behavior of the generated assembly code is + one of the possible behaviors of the source C code. *) Theorem transf_c_program_is_refinement: forall p tp, @@ -124,83 +115,190 @@ Qed. (** * Satisfaction of specifications *) (** The second additional results shows that if all executions - of the source C program satisfies a given specification - (a predicate on the observable behavior of the program), + of the source C program satisfies a given specification, then all executions of the produced Asm program satisfy - this specification as well. - - We first show this result for specifications that are stable - under the [behavior_improves] relation. *) - -Section SPECS_PRESERVED. - -Variable spec: program_behavior -> Prop. + this specification as well. *) + +(** The specifications we consider here are sets of observable + behaviors, representing the good behaviors a program is expected + to have. A specification can be as simple as + ``the program does not go wrong'' or as precise as + ``the program prints a prime number then terminates with code 0''. + As usual in Coq, sets of behaviors are represented as predicates + [program_behavior -> Prop]. *) + +Definition specification := program_behavior -> Prop. + +(** A program satisfies a specification if all its observable behaviors + are in the specification. *) + +Definition c_program_satisfies_spec (p: Csyntax.program) (spec: specification): Prop := + forall beh, program_behaves (Csem.semantics p) beh -> spec beh. +Definition asm_program_satisfies_spec (p: Asm.program) (spec: specification): Prop := + forall beh, program_behaves (Asm.semantics p) beh -> spec beh. + +(** It is not always the case that if the source program satisfies a + specification, then the generated assembly code satisfies it as + well. For example, if the specification is ``the program goes wrong + on an undefined behavior'', a C source that goes wrong satisfies + this specification but can be compiled into Asm code that does not + go wrong and therefore does not satisfy the specification. + + For this reason, we restrict ourselves to safety-enforcing specifications: + specifications that exclude ``going wrong'' behaviors and are satisfied + only by programs that execute safely. *) + +Definition safety_enforcing_specification (spec: specification): Prop := + forall beh, spec beh -> not_wrong beh. -Hypothesis spec_stable: - forall beh1 beh2, behavior_improves beh1 beh2 -> spec beh1 -> spec beh2. +(** As the main result of this section, we show that CompCert + compilation preserves safety-enforcing specifications: + any such specification that is satisfied by the source C program is + always satisfied by the generated assembly code. *) Theorem transf_c_program_preserves_spec: - forall p tp, + forall p tp spec, transf_c_program p = OK tp -> - (forall beh, program_behaves (Csem.semantics p) beh -> spec beh) -> - (forall beh, program_behaves (Asm.semantics tp) beh -> spec beh). + safety_enforcing_specification spec -> + c_program_satisfies_spec p spec -> + asm_program_satisfies_spec tp spec. Proof. - intros. - exploit transf_c_program_preservation; eauto. intros [beh' [A B]]. - apply spec_stable with beh'; auto. + intros p tp spec TRANSF SES CSAT; red; intros beh AEXEC. + exploit transf_c_program_preservation; eauto. intros (beh' & CEXEC & IMPR). + apply CSAT in CEXEC. destruct IMPR as [EQ | [t [A B]]]. +- congruence. +- subst beh'. apply SES in CEXEC. contradiction. Qed. -End SPECS_PRESERVED. +(** Safety-enforcing specifications are not the only good properties + of source programs that are preserved by compilation. Another example + of a property that is preserved is the ``initial trace'' property: + all executions of the program start by producing an expected trace + of I/O actions, representing the good behavior expected from the program. + After that, the program may terminate, or continue running, or go wrong + on an undefined behavior. What matters is that the program produced + the expected trace at the beginning of its execution. This is a typical + liveness property, and it is preserved by compilation. *) + +Definition c_program_has_initial_trace (p: Csyntax.program) (t: trace): Prop := + forall beh, program_behaves (Csem.semantics p) beh -> behavior_prefix t beh. +Definition asm_program_has_initial_trace (p: Asm.program) (t: trace): Prop := + forall beh, program_behaves (Asm.semantics p) beh -> behavior_prefix t beh. + +Theorem transf_c_program_preserves_initial_trace: + forall p tp t, + transf_c_program p = OK tp -> + c_program_has_initial_trace p t -> + asm_program_has_initial_trace tp t. +Proof. + intros p tp t TRANSF CTRACE; red; intros beh AEXEC. + exploit transf_c_program_preservation; eauto. intros (beh' & CEXEC & IMPR). + apply CTRACE in CEXEC. destruct IMPR as [EQ | [t' [A B]]]. +- congruence. +- destruct CEXEC as (beh1' & EQ'). + destruct B as (beh1 & EQ). + subst beh'. destruct beh1'; simpl in A; inv A. + exists (behavior_app t0 beh1). apply behavior_app_assoc. +Qed. -(** As a corollary, we obtain preservation of safety specifications: - specifications that exclude "going wrong" behaviors. *) +(** * Extension to separate compilation *) -Section SAFETY_PRESERVED. +(** The results above were given in terms of whole-program compilation. + They also extend to separate compilation followed by linking. *) -Variable spec: program_behavior -> Prop. +Section SEPARATE_COMPILATION. -Hypothesis spec_safety: - forall beh, spec beh -> not_wrong beh. +(** The source: a list of C compilation units *) +Variable c_units: nlist Csyntax.program. -Theorem transf_c_program_preserves_safety_spec: - forall p tp, - transf_c_program p = OK tp -> - (forall beh, program_behaves (Csem.semantics p) beh -> spec beh) -> - (forall beh, program_behaves (Asm.semantics tp) beh -> spec beh). +(** The compiled code: a list of Asm compilation units, obtained by separate compilation *) +Variable asm_units: nlist Asm.program. +Hypothesis separate_compilation_succeeds: + nlist_forall2 (fun cu tcu => transf_c_program cu = OK tcu) c_units asm_units. + +(** We assume that the source C compilation units can be linked together + to obtain a monolithic C program [c_program]. *) +Variable c_program: Csyntax.program. +Hypothesis source_linking: link_list c_units = Some c_program. + +(** Then, linking the Asm units obtained by separate compilation succeeds. *) +Lemma compiled_linking_succeeds: + { asm_program | link_list asm_units = Some asm_program }. Proof. - intros. eapply transf_c_program_preserves_spec; eauto. - intros. destruct H2. congruence. destruct H2 as [t [EQ1 EQ2]]. - subst beh1. elim (spec_safety _ H3). + destruct (link_list asm_units) eqn:E. +- exists p; auto. +- exfalso. + exploit separate_transf_c_program_correct; eauto. intros (a & P & Q). + congruence. Qed. -End SAFETY_PRESERVED. +(** Let asm_program be the result of linking the Asm units. *) +Let asm_program: Asm.program := proj1_sig compiled_linking_succeeds. +Let compiled_linking: link_list asm_units = Some asm_program := proj2_sig compiled_linking_succeeds. + +(** Then, [asm_program] preserves the semantics and the specifications of + [c_program], in the following sense. + First, every behavior of [asm_program] improves upon one of the possible + behaviors of [c_program]. *) -(** We also have preservation of liveness specifications: - specifications that assert the existence of a prefix of the observable - trace satisfying some conditions. *) +Theorem separate_transf_c_program_preservation: + forall beh, + program_behaves (Asm.semantics asm_program) beh -> + exists beh', program_behaves (Csem.semantics c_program) beh' /\ behavior_improves beh' beh. +Proof. + intros. exploit separate_transf_c_program_correct; eauto. intros (a & P & Q). + assert (a = asm_program) by congruence. subst a. + eapply backward_simulation_behavior_improves; eauto. +Qed. -Section LIVENESS_PRESERVED. +(** As a corollary, if [c_program] is free of undefined behaviors, + the behavior of [asm_program] is one of the possible behaviors of [c_program]. *) -Variable spec: trace -> Prop. +Theorem separate_transf_c_program_is_refinement: + (forall beh, program_behaves (Csem.semantics c_program) beh -> not_wrong beh) -> + (forall beh, program_behaves (Asm.semantics asm_program) beh -> program_behaves (Csem.semantics c_program) beh). +Proof. + intros. exploit separate_transf_c_program_preservation; eauto. intros (beh' & P & Q). + assert (not_wrong beh') by auto. + inv Q. +- auto. +- destruct H2 as (t & U & V). subst beh'. elim H1. +Qed. -Definition liveness_spec_satisfied (b: program_behavior) : Prop := - exists t, behavior_prefix t b /\ spec t. +(** We now show that if all executions of [c_program] satisfy a specification, + then all executions of [asm_program] also satisfy the specification, provided + the specification is of the safety-enforcing kind. *) -Theorem transf_c_program_preserves_liveness_spec: - forall p tp, - transf_c_program p = OK tp -> - (forall beh, program_behaves (Csem.semantics p) beh -> liveness_spec_satisfied beh) -> - (forall beh, program_behaves (Asm.semantics tp) beh -> liveness_spec_satisfied beh). +Theorem separate_transf_c_program_preserves_spec: + forall spec, + safety_enforcing_specification spec -> + c_program_satisfies_spec c_program spec -> + asm_program_satisfies_spec asm_program spec. Proof. - intros. eapply transf_c_program_preserves_spec; eauto. - intros. destruct H3 as [t1 [A B]]. destruct H2. - subst. exists t1; auto. - destruct H2 as [t [C D]]. subst. - destruct A as [b1 E]. destruct D as [b2 F]. - destruct b1; simpl in E; inv E. - exists t1; split; auto. - exists (behavior_app t0 b2); apply behavior_app_assoc. + intros spec SES CSAT; red; intros beh AEXEC. + exploit separate_transf_c_program_preservation; eauto. intros (beh' & CEXEC & IMPR). + apply CSAT in CEXEC. destruct IMPR as [EQ | [t [A B]]]. +- congruence. +- subst beh'. apply SES in CEXEC. contradiction. Qed. -End LIVENESS_PRESERVED. +(** As another corollary of [separate_transf_c_program_preservation], + if all executions of [c_program] have a trace [t] as initial trace, + so do all executions of [asm_program]. *) + +Theorem separate_transf_c_program_preserves_initial_trace: + forall t, + c_program_has_initial_trace c_program t -> + asm_program_has_initial_trace asm_program t. +Proof. + intros t CTRACE; red; intros beh AEXEC. + exploit separate_transf_c_program_preservation; eauto. intros (beh' & CEXEC & IMPR). + apply CTRACE in CEXEC. destruct IMPR as [EQ | [t' [A B]]]. +- congruence. +- destruct CEXEC as (beh1' & EQ'). + destruct B as (beh1 & EQ). + subst beh'. destruct beh1'; simpl in A; inv A. + exists (behavior_app t0 beh1). apply behavior_app_assoc. +Qed. +End SEPARATE_COMPILATION. diff --git a/driver/Driver.ml b/driver/Driver.ml index 0ad820ea..8ab8557c 100644 --- a/driver/Driver.ml +++ b/driver/Driver.ml @@ -404,7 +404,7 @@ let _ = parse_cmdline cmdline_actions; DebugInit.init (); (* Initialize the debug functions *) if nolink () && !option_o <> None && !num_source_files >= 2 then - fatal_error no_loc "Ambiguous '-o' option (multiple source files)"; + fatal_error no_loc "ambiguous '-o' option (multiple source files)"; if !num_input_files = 0 then fatal_error no_loc "no input file"; let linker_args = time "Total compilation time" perform_actions () in diff --git a/driver/Driveraux.ml b/driver/Driveraux.ml index ccc3d00d..5b2d792e 100644 --- a/driver/Driveraux.ml +++ b/driver/Driveraux.ml @@ -47,7 +47,7 @@ let command stdout args = match status with | Unix.WEXITED rc -> rc | Unix.WSIGNALED n | Unix.WSTOPPED n -> - error no_loc "Command '%s' killed on a signal." argv.(0); -1 + error no_loc "command '%s' killed on a signal." argv.(0); -1 with Unix.Unix_error(err, fn, param) -> error no_loc "executing '%s': %s: %s %s" argv.(0) fn (Unix.error_message err) param; diff --git a/driver/Frontend.ml b/driver/Frontend.ml index db84a9f9..b29bb7f3 100644 --- a/driver/Frontend.ml +++ b/driver/Frontend.ml @@ -17,6 +17,15 @@ open Driveraux (* Common frontend functions between clightgen and ccomp *) +let predefined_macros = + [ + "-D__COMPCERT__"; + "-U__STDC_IEC_559_COMPLEX__"; + "-D__STDC_NO_ATOMICS__"; + "-D__STDC_NO_COMPLEX__"; + "-D__STDC_NO_THREADS__"; + "-D__STDC_NO_VLA__" + ] (* From C to preprocessed C *) @@ -26,7 +35,7 @@ let preprocess ifile ofile = if ofile = "-" then None else Some ofile in let cmd = List.concat [ Configuration.prepro; - ["-D__COMPCERT__"]; + predefined_macros; (if !Clflags.use_standard_headers then ["-I" ^ Filename.concat !Clflags.stdlib_path "include" ] else []); @@ -64,10 +73,12 @@ let parse_c_file sourcename ifile = let init () = Machine.config:= begin match Configuration.arch with - | "powerpc" -> if Configuration.gnu_toolchain - then if Configuration.abi = "linux" - then Machine.ppc_32_linux_bigendian - else Machine.ppc_32_bigendian + | "powerpc" -> if Configuration.model = "e5500" || Configuration.model = "ppc64" + then if Configuration.abi = "linux" then Machine.ppc_32_r64_linux_bigendian + else if Configuration.gnu_toolchain then Machine.ppc_32_r64_bigendian + else Machine.ppc_32_r64_diab_bigendian + else if Configuration.abi = "linux" then Machine.ppc_32_linux_bigendian + else if Configuration.gnu_toolchain then Machine.ppc_32_bigendian else Machine.ppc_32_diab_bigendian | "arm" -> if Configuration.is_big_endian then Machine.arm_bigendian @@ -116,7 +127,7 @@ let gnu_prepro_actions = [ Exact "-imacros", String (gnu_prepro_opt_key "-imacros"); Exact "-idirafter", String (gnu_prepro_opt_key "-idirafter"); Exact "-isystem", String (gnu_prepro_opt_key "-isystem"); - Exact "-iquote", String (gnu_prepro_opt_key "-iquore"); + Exact "-iquote", String (gnu_prepro_opt_key "-iquote"); Exact "-P", Self gnu_prepro_opt; Exact "-C", Self gnu_prepro_opt; Exact "-CC", Self gnu_prepro_opt;] diff --git a/driver/Frontend.mli b/driver/Frontend.mli index 39f0e612..a18c2704 100644 --- a/driver/Frontend.mli +++ b/driver/Frontend.mli @@ -18,7 +18,7 @@ val parse_c_file: string -> string -> Csyntax.coq_function Ctypes.program (** From preprocessed C to Csyntax *) val prepro_actions: (Commandline.pattern * Commandline.action) list - (** Commandline optins affecting the frontend *) + (** Commandline options affecting the frontend *) val prepro_help: string (** Commandline help description *) diff --git a/driver/Linker.ml b/driver/Linker.ml index 6e6ad6b4..d6e1d384 100644 --- a/driver/Linker.ml +++ b/driver/Linker.ml @@ -86,4 +86,4 @@ let linker_actions = push_linker_arg s); Prefix "-Wl,", Self push_linker_arg; Prefix "-WUl,", Self (fun s -> List.iter push_linker_arg (explode_comma_option s)); - Exact "-u", Self push_linker_arg;] + Exact "-u", String (fun s -> push_linker_arg "-u"; push_linker_arg s);] diff --git a/driver/Linker.mli b/driver/Linker.mli index 3b92da05..dd034543 100644 --- a/driver/Linker.mli +++ b/driver/Linker.mli @@ -12,10 +12,10 @@ (* *********************************************************************) val linker: string -> string list -> unit - (** Link files into executbale *) + (** Link files into executable *) val linker_actions: (Commandline.pattern * Commandline.action) list - (** Commandline optins affecting the assembler *) + (** Commandline options affecting the assembler *) val linker_help: string (** Commandline help description *) diff --git a/exportclight/Clightgen.ml b/exportclight/Clightgen.ml index 9cb0674e..1eb4fe03 100644 --- a/exportclight/Clightgen.ml +++ b/exportclight/Clightgen.ml @@ -53,7 +53,8 @@ let compile_c_ast sourcename csyntax ofile = end; (* Print Clight in Coq syntax *) let oc = open_out ofile in - ExportClight.print_program (Format.formatter_of_out_channel oc) clight; + ExportClight.print_program (Format.formatter_of_out_channel oc) + clight sourcename !option_normalize; close_out oc (* From C source to Clight *) diff --git a/exportclight/ExportClight.ml b/exportclight/ExportClight.ml index 1ae78c15..b124586a 100644 --- a/exportclight/ExportClight.ml +++ b/exportclight/ExportClight.ml @@ -487,8 +487,7 @@ let print_assertions p = let prologue = "\ From Coq Require Import String List ZArith.\n\ From compcert Require Import Coqlib Integers Floats AST Ctypes Cop Clight Clightdefs.\n\ -Local Open Scope Z_scope.\n\ -\n" +Local Open Scope Z_scope.\n" (* Naming the compiler-generated temporaries occurring in the program *) @@ -543,13 +542,30 @@ let name_globdef (id, g) = let name_program p = List.iter name_globdef p.Ctypes.prog_defs +(* Information about this run of clightgen *) + +let print_clightgen_info p sourcefile normalized = + fprintf p "@[<v 2>Module Info."; + fprintf p "@ Definition version := %S%%string." Version.version; + fprintf p "@ Definition build_number := %S%%string." Version.buildnr; + fprintf p "@ Definition build_tag := %S%%string." Version.tag; + fprintf p "@ Definition arch := %S%%string." Configuration.arch; + fprintf p "@ Definition model := %S%%string." Configuration.model; + fprintf p "@ Definition abi := %S%%string." Configuration.abi; + fprintf p "@ Definition bitsize := %d." (if Archi.ptr64 then 64 else 32); + fprintf p "@ Definition big_endian := %B." Archi.big_endian; + fprintf p "@ Definition source_file := %S%%string." sourcefile; + fprintf p "@ Definition normalized := %B." normalized; + fprintf p "@]@ End Info.@ @ " + (* All together *) -let print_program p prog = +let print_program p prog sourcefile normalized = Hashtbl.clear temp_names; name_program prog; fprintf p "@[<v 0>"; fprintf p "%s" prologue; + print_clightgen_info p sourcefile normalized; define_idents p; List.iter (print_globdef p) prog.Ctypes.prog_defs; fprintf p "Definition composites : list composite_definition :=@ "; diff --git a/flocq/Appli/Fappli_IEEE.v b/flocq/Appli/Fappli_IEEE.v index 161b545a..7503dc1d 100644 --- a/flocq/Appli/Fappli_IEEE.v +++ b/flocq/Appli/Fappli_IEEE.v @@ -597,9 +597,8 @@ revert H1. clear -H2. rewrite Zpos_digits2_pos. unfold fexp, FLT_exp. generalize (Zdigits radix2 (Zpos mx)). -intros ; zify ; subst. -clear -H H2. clearbody emin. -omega. +clearbody emin. +intros ; zify ; omega. Qed. Theorem abs_B2R_lt_emax : diff --git a/flocq/Appli/Fappli_double_round.v b/flocq/Appli/Fappli_double_round.v index 2c4937ab..82f61da3 100644 --- a/flocq/Appli/Fappli_double_round.v +++ b/flocq/Appli/Fappli_double_round.v @@ -5,6 +5,7 @@ Require Import Fcore_defs. Require Import Fcore_generic_fmt. Require Import Fcalc_ops. Require Import Fcore_ulp. +Require Fcore_FLX Fcore_FLT Fcore_FTZ. Require Import Psatz. @@ -659,7 +660,7 @@ Qed. Section Double_round_mult_FLX. -Require Import Fcore_FLX. +Import Fcore_FLX. Variable prec : Z. Variable prec' : Z. @@ -685,8 +686,8 @@ End Double_round_mult_FLX. Section Double_round_mult_FLT. -Require Import Fcore_FLX. -Require Import Fcore_FLT. +Import Fcore_FLX. +Import Fcore_FLT. Variable emin prec : Z. Variable emin' prec' : Z. @@ -718,7 +719,8 @@ End Double_round_mult_FLT. Section Double_round_mult_FTZ. -Require Import Fcore_FTZ. +Import Fcore_FLX. +Import Fcore_FTZ. Variable emin prec : Z. Variable emin' prec' : Z. @@ -796,7 +798,7 @@ Lemma ln_beta_minus_disj : \/ (ln_beta (x - y) = (ln_beta x - 1)%Z :> Z)). Proof. intros x y Px Py Hln. -assert (Hxy : y < x); [now apply (ln_beta_lt_pos beta); [| |omega]|]. +assert (Hxy : y < x); [now apply (ln_beta_lt_pos beta); [ |omega]|]. generalize (ln_beta_minus beta x y Py Hxy); intro Hln2. generalize (ln_beta_minus_lb beta x y Px Py Hln); intro Hln3. omega. @@ -1611,7 +1613,7 @@ Qed. Section Double_round_plus_FLX. -Require Import Fcore_FLX. +Import Fcore_FLX. Variable prec : Z. Variable prec' : Z. @@ -1667,8 +1669,8 @@ End Double_round_plus_FLX. Section Double_round_plus_FLT. -Require Import Fcore_FLX. -Require Import Fcore_FLT. +Import Fcore_FLX. +Import Fcore_FLT. Variable emin prec : Z. Variable emin' prec' : Z. @@ -1739,8 +1741,8 @@ End Double_round_plus_FLT. Section Double_round_plus_FTZ. -Require Import Fcore_FLX. -Require Import Fcore_FTZ. +Import Fcore_FLX. +Import Fcore_FTZ. Variable emin prec : Z. Variable emin' prec' : Z. @@ -2325,7 +2327,7 @@ Qed. Section Double_round_plus_beta_ge_3_FLX. -Require Import Fcore_FLX. +Import Fcore_FLX. Variable prec : Z. Variable prec' : Z. @@ -2385,8 +2387,8 @@ End Double_round_plus_beta_ge_3_FLX. Section Double_round_plus_beta_ge_3_FLT. -Require Import Fcore_FLX. -Require Import Fcore_FLT. +Import Fcore_FLX. +Import Fcore_FLT. Variable emin prec : Z. Variable emin' prec' : Z. @@ -2461,8 +2463,8 @@ End Double_round_plus_beta_ge_3_FLT. Section Double_round_plus_beta_ge_3_FTZ. -Require Import Fcore_FLX. -Require Import Fcore_FTZ. +Import Fcore_FLX. +Import Fcore_FTZ. Variable emin prec : Z. Variable emin' prec' : Z. @@ -2880,7 +2882,7 @@ Qed. Section Double_round_sqrt_FLX. -Require Import Fcore_FLX. +Import Fcore_FLX. Variable prec : Z. Variable prec' : Z. @@ -2917,8 +2919,8 @@ End Double_round_sqrt_FLX. Section Double_round_sqrt_FLT. -Require Import Fcore_FLX. -Require Import Fcore_FLT. +Import Fcore_FLX. +Import Fcore_FLT. Variable emin prec : Z. Variable emin' prec' : Z. @@ -2972,8 +2974,8 @@ End Double_round_sqrt_FLT. Section Double_round_sqrt_FTZ. -Require Import Fcore_FLX. -Require Import Fcore_FTZ. +Import Fcore_FLX. +Import Fcore_FTZ. Variable emin prec : Z. Variable emin' prec' : Z. @@ -3318,7 +3320,7 @@ Qed. Section Double_round_sqrt_beta_ge_4_FLX. -Require Import Fcore_FLX. +Import Fcore_FLX. Variable prec : Z. Variable prec' : Z. @@ -3357,8 +3359,8 @@ End Double_round_sqrt_beta_ge_4_FLX. Section Double_round_sqrt_beta_ge_4_FLT. -Require Import Fcore_FLX. -Require Import Fcore_FLT. +Import Fcore_FLX. +Import Fcore_FLT. Variable emin prec : Z. Variable emin' prec' : Z. @@ -3414,8 +3416,8 @@ End Double_round_sqrt_beta_ge_4_FLT. Section Double_round_sqrt_beta_ge_4_FTZ. -Require Import Fcore_FLX. -Require Import Fcore_FTZ. +Import Fcore_FLX. +Import Fcore_FTZ. Variable emin prec : Z. Variable emin' prec' : Z. @@ -4401,7 +4403,7 @@ Qed. Section Double_round_div_FLX. -Require Import Fcore_FLX. +Import Fcore_FLX. Variable prec : Z. Variable prec' : Z. @@ -4445,8 +4447,8 @@ End Double_round_div_FLX. Section Double_round_div_FLT. -Require Import Fcore_FLX. -Require Import Fcore_FLT. +Import Fcore_FLX. +Import Fcore_FLT. Variable emin prec : Z. Variable emin' prec' : Z. @@ -4515,8 +4517,8 @@ End Double_round_div_FLT. Section Double_round_div_FTZ. -Require Import Fcore_FLX. -Require Import Fcore_FTZ. +Import Fcore_FLX. +Import Fcore_FTZ. Variable emin prec : Z. Variable emin' prec' : Z. diff --git a/flocq/Core/Fcore_FLT.v b/flocq/Core/Fcore_FLT.v index 53dc48a7..2258b1d9 100644 --- a/flocq/Core/Fcore_FLT.v +++ b/flocq/Core/Fcore_FLT.v @@ -257,32 +257,33 @@ apply Rle_lt_trans with (2:=Hx). now apply He. Qed. -Theorem ulp_FLT_le: forall x, (bpow (emin+prec) <= Rabs x)%R -> - (ulp beta FLT_exp x <= Rabs x * bpow (1-prec))%R. +Theorem ulp_FLT_le : + forall x, (bpow (emin + prec - 1) <= Rabs x)%R -> + (ulp beta FLT_exp x <= Rabs x * bpow (1 - prec))%R. Proof. intros x Hx. -assert (x <> 0)%R. -intros Z; contradict Hx; apply Rgt_not_le, Rlt_gt. -rewrite Z, Rabs_R0; apply bpow_gt_0. -rewrite ulp_neq_0; try assumption. +assert (Zx : (x <> 0)%R). + intros Z; contradict Hx; apply Rgt_not_le, Rlt_gt. + rewrite Z, Rabs_R0; apply bpow_gt_0. +rewrite ulp_neq_0 with (1 := Zx). unfold canonic_exp, FLT_exp. destruct (ln_beta beta x) as (e,He). apply Rle_trans with (bpow (e-1)*bpow (1-prec))%R. rewrite <- bpow_plus. right; apply f_equal. -apply trans_eq with (e-prec)%Z;[idtac|ring]. -simpl; apply Z.max_l. -assert (emin+prec <= e)%Z; try omega. -apply le_bpow with beta. -apply Rle_trans with (1:=Hx). -left; now apply He. +replace (e - 1 + (1 - prec))%Z with (e - prec)%Z by ring. +apply Z.max_l. +assert (emin+prec-1 < e)%Z; try omega. +apply lt_bpow with beta. +apply Rle_lt_trans with (1:=Hx). +now apply He. apply Rmult_le_compat_r. apply bpow_ge_0. now apply He. Qed. - -Theorem ulp_FLT_ge: forall x, (Rabs x * bpow (-prec) < ulp beta FLT_exp x)%R. +Theorem ulp_FLT_gt : + forall x, (Rabs x * bpow (-prec) < ulp beta FLT_exp x)%R. Proof. intros x; case (Req_dec x 0); intros Hx. rewrite Hx, ulp_FLT_small, Rabs_R0, Rmult_0_l; try apply bpow_gt_0. diff --git a/flocq/Core/Fcore_Raux.v b/flocq/Core/Fcore_Raux.v index 44db6c35..77235e63 100644 --- a/flocq/Core/Fcore_Raux.v +++ b/flocq/Core/Fcore_Raux.v @@ -1842,10 +1842,13 @@ Qed. Lemma ln_beta_lt_pos : forall x y, - (0 < x)%R -> (0 < y)%R -> + (0 < y)%R -> (ln_beta x < ln_beta y)%Z -> (x < y)%R. Proof. -intros x y Px Py. +intros x y Py. +case (Rle_or_lt x 0); intros Px. +intros H. +now apply Rle_lt_trans with 0%R. destruct (ln_beta x) as (ex, Hex). destruct (ln_beta y) as (ey, Hey). simpl. @@ -2099,7 +2102,7 @@ assert (Hbeta : (2 <= r)%Z). { destruct r as (beta_val,beta_prop). now apply Zle_bool_imp_le. } intros x y Px Py Hln. -assert (Oxy : (y < x)%R); [now apply ln_beta_lt_pos; [| |omega]|]. +assert (Oxy : (y < x)%R); [apply ln_beta_lt_pos;[assumption|omega]|]. destruct (ln_beta x) as (ex,Hex). destruct (ln_beta y) as (ey,Hey). simpl in Hln |- *. diff --git a/flocq/Core/Fcore_ulp.v b/flocq/Core/Fcore_ulp.v index 3bc0eac3..4fdd319e 100644 --- a/flocq/Core/Fcore_ulp.v +++ b/flocq/Core/Fcore_ulp.v @@ -43,7 +43,6 @@ now left. now right. Qed. - (** [negligible_exp] is either none (as in FLX) or Some n such that n <= fexp n. *) Definition negligible_exp: option Z := match (LPO_Z _ (fun z => Z_le_dec_aux z (fexp z))) with @@ -272,6 +271,7 @@ Qed. Lemma not_FTZ_generic_format_ulp: (forall x, F (ulp x)) -> Exp_not_FTZ fexp. +Proof. intros H e. specialize (H (bpow (e-1))). rewrite ulp_neq_0 in H. @@ -1483,23 +1483,27 @@ now apply generic_format_opp. now apply Ropp_lt_contravar. Qed. - -Theorem lt_succ_le: +Theorem lt_succ_le : forall x y, - F x -> F y -> (y <> 0)%R -> + (y <> 0)%R -> (x <= y)%R -> (x < succ y)%R. Proof. -intros x y Fx Fy Zy Hxy. -case (Rle_or_lt (succ y) x); trivial; intros H. -absurd (succ y = y)%R. -apply Rgt_not_eq. +intros x y Zy Hxy. +apply Rle_lt_trans with (1 := Hxy). now apply succ_gt_id. -apply Rle_antisym. -now apply Rle_trans with x. -apply succ_ge_id. Qed. +Theorem pred_lt_le : + forall x y, + (x <> 0)%R -> + (x <= y)%R -> + (pred x < y)%R. +Proof. +intros x y Zy Hxy. +apply Rlt_le_trans with (2 := Hxy). +now apply pred_lt_id. +Qed. Theorem succ_pred_aux : forall x, F x -> (0 < x)%R -> succ (pred x)=x. Proof. @@ -1510,17 +1514,15 @@ rewrite succ_eq_pos. now apply pred_pos_plus_ulp. Qed. -Theorem pred_succ_aux_0 : (pred (succ 0)=0)%R. +Theorem pred_ulp_0 : + pred (ulp 0) = 0%R. Proof. -unfold succ; rewrite Rle_bool_true. -2: apply Rle_refl. -rewrite Rplus_0_l. rewrite pred_eq_pos. 2: apply ulp_ge_0. unfold ulp; rewrite Req_bool_true; trivial. case negligible_exp_spec'. (* *) -intros (H1,H2); rewrite H1. +intros [H1 _]; rewrite H1. unfold pred_pos; rewrite Req_bool_false. 2: apply Rlt_not_eq, bpow_gt_0. unfold ulp; rewrite Req_bool_true; trivial. @@ -1535,111 +1537,73 @@ apply Rminus_diag_eq, f_equal. apply sym_eq, valid_exp; omega. Qed. -Theorem pred_succ_aux : forall x, F x -> (0 < x)%R -> pred (succ x)=x. +Theorem succ_0 : + succ 0 = ulp 0. Proof. -intros x Fx Hx. -rewrite succ_eq_pos;[idtac|now left]. -rewrite pred_eq_pos. -2: apply Rplus_le_le_0_compat;[now left| apply ulp_ge_0]. -unfold pred_pos. -case Req_bool_spec; intros H1. -(* *) -pose (l:=(ln_beta beta (x+ulp x))). -rewrite H1 at 1; fold l. -apply Rplus_eq_reg_r with (ulp x). -rewrite H1; fold l. -rewrite (ulp_neq_0 x) at 3. -2: now apply Rgt_not_eq. -unfold canonic_exp. -replace (fexp (ln_beta beta x)) with (fexp (l-1))%Z. -ring. -apply f_equal, sym_eq. -apply Zle_antisym. -assert (ln_beta beta x - 1 < l - 1)%Z;[idtac|omega]. -apply lt_bpow with beta. -unfold l; rewrite <- H1. -apply Rle_lt_trans with x. -destruct (ln_beta beta x) as (e,He); simpl. -rewrite <- (Rabs_right x) at 1. -2: apply Rle_ge; now left. -now apply He, Rgt_not_eq. -apply Rplus_lt_reg_l with (-x)%R; ring_simplify. -rewrite ulp_neq_0. -apply bpow_gt_0. -now apply Rgt_not_eq. -apply le_bpow with beta. -unfold l; rewrite <- H1. -apply id_p_ulp_le_bpow; trivial. -rewrite <- (Rabs_right x) at 1. -2: apply Rle_ge; now left. -apply bpow_ln_beta_gt. -(* *) -replace (ulp (x+ ulp x)) with (ulp x). -ring. -rewrite ulp_neq_0 at 1. -2: now apply Rgt_not_eq. -rewrite ulp_neq_0 at 1. -2: apply Rgt_not_eq, Rlt_gt. -2: apply Rlt_le_trans with (1:=Hx). -2: apply Rplus_le_reg_l with (-x)%R; ring_simplify. -2: apply ulp_ge_0. -apply f_equal; unfold canonic_exp; apply f_equal. -apply sym_eq, ln_beta_unique. -rewrite Rabs_right. -2: apply Rle_ge; left. -2: apply Rlt_le_trans with (1:=Hx). -2: apply Rplus_le_reg_l with (-x)%R; ring_simplify. -2: apply ulp_ge_0. -destruct (ln_beta beta x) as (e,He); simpl. -rewrite Rabs_right in He. -2: apply Rle_ge; now left. -split. -apply Rle_trans with x. -apply He, Rgt_not_eq; assumption. -apply Rplus_le_reg_l with (-x)%R; ring_simplify. -apply ulp_ge_0. -case (Rle_lt_or_eq_dec (x+ulp x) (bpow e)); trivial. -apply id_p_ulp_le_bpow; trivial. -apply He, Rgt_not_eq; assumption. -intros K; contradict H1. -rewrite K, ln_beta_bpow. -apply f_equal; ring. +unfold succ. +rewrite Rle_bool_true. +apply Rplus_0_l. +apply Rle_refl. Qed. +Theorem pred_0 : + pred 0 = Ropp (ulp 0). +Proof. +rewrite <- succ_0. +rewrite <- Ropp_0 at 1. +apply pred_opp. +Qed. - -Theorem succ_pred : forall x, F x -> succ (pred x)=x. +Theorem pred_succ_aux : + forall x, F x -> (0 < x)%R -> + pred (succ x) = x. +Proof. +intros x Fx Hx. +apply Rle_antisym. +- apply Rnot_lt_le. + intros H. + apply succ_le_lt with (1 := Fx) in H. + revert H. + apply Rlt_not_le. + apply pred_lt_id. + apply Rgt_not_eq. + apply Rlt_le_trans with (1 := Hx). + apply succ_ge_id. + now apply generic_format_pred, generic_format_succ. +- apply le_pred_lt with (1 := Fx). + now apply generic_format_succ. + apply succ_gt_id. + now apply Rgt_not_eq. +Qed. + +Theorem succ_pred : + forall x, F x -> + succ (pred x) = x. Proof. intros x Fx. -case (Rle_or_lt 0 x); intros Hx. -destruct Hx as [Hx|Hx]. +destruct (Rle_or_lt 0 x) as [[Hx|Hx]|Hx]. now apply succ_pred_aux. rewrite <- Hx. -rewrite pred_eq_opp_succ_opp, succ_opp, Ropp_0. -rewrite pred_succ_aux_0; ring. +rewrite pred_0, succ_opp, pred_ulp_0. +apply Ropp_0. rewrite pred_eq_opp_succ_opp, succ_opp. rewrite pred_succ_aux. -ring. +apply Ropp_involutive. now apply generic_format_opp. now apply Ropp_0_gt_lt_contravar. Qed. -Theorem pred_succ : forall x, F x -> pred (succ x)=x. +Theorem pred_succ : + forall x, F x -> + pred (succ x) = x. Proof. intros x Fx. -case (Rle_or_lt 0 x); intros Hx. -destruct Hx as [Hx|Hx]. -now apply pred_succ_aux. -rewrite <- Hx. -apply pred_succ_aux_0. -rewrite succ_eq_opp_pred_opp, pred_opp. -rewrite succ_pred_aux. -ring. +rewrite <- (Ropp_involutive x). +rewrite succ_opp, pred_opp. +apply f_equal, succ_pred. now apply generic_format_opp. -now apply Ropp_0_gt_lt_contravar. Qed. - Theorem round_UP_pred_plus_eps : forall x, F x -> forall eps, (0 < eps <= if (Rle_bool x 0) then (ulp x) @@ -2041,26 +2005,16 @@ apply error_le_half_ulp. rewrite round_DN_opp; apply Ropp_0_gt_lt_contravar; apply Rlt_gt; assumption. Qed. - -Theorem pred_le: forall x y, - F x -> F y -> (x <= y)%R -> (pred x <= pred y)%R. +Theorem pred_le : + forall x y, F x -> F y -> (x <= y)%R -> + (pred x <= pred y)%R. Proof. -intros x y Fx Fy Hxy. -assert (V:( ((x = 0) /\ (y = 0)) \/ (x <>0 \/ x < y))%R). -case (Req_dec x 0); intros Zx. -case Hxy; intros Zy. -now right; right. -left; split; trivial; now rewrite <- Zy. -now right; left. -destruct V as [(V1,V2)|V]. -rewrite V1,V2; now right. -apply le_pred_lt; try assumption. -apply generic_format_pred; try assumption. -case V; intros V1. -apply Rlt_le_trans with (2:=Hxy). -now apply pred_lt_id. -apply Rle_lt_trans with (2:=V1). -now apply pred_le_id. +intros x y Fx Fy [Hxy| ->]. +2: apply Rle_refl. +apply le_pred_lt with (2 := Fy). +now apply generic_format_pred. +apply Rle_lt_trans with (2 := Hxy). +apply pred_le_id. Qed. Theorem succ_le: forall x y, @@ -2088,6 +2042,28 @@ rewrite <- (pred_succ x), <- (pred_succ y); try assumption. apply pred_le; trivial; now apply generic_format_succ. Qed. +Theorem pred_lt : + forall x y, F x -> F y -> (x < y)%R -> + (pred x < pred y)%R. +Proof. +intros x y Fx Fy Hxy. +apply Rnot_le_lt. +intros H. +apply Rgt_not_le with (1 := Hxy). +now apply pred_le_inv. +Qed. + +Theorem succ_lt : + forall x y, F x -> F y -> (x < y)%R -> + (succ x < succ y)%R. +Proof. +intros x y Fx Fy Hxy. +apply Rnot_le_lt. +intros H. +apply Rgt_not_le with (1 := Hxy). +now apply succ_le_inv. +Qed. + (* was lt_UP_le_DN *) Theorem le_round_DN_lt_UP : forall x y, F y -> diff --git a/flocq/Flocq_version.v b/flocq/Flocq_version.v index b01a08f9..72d4fe20 100644 --- a/flocq/Flocq_version.v +++ b/flocq/Flocq_version.v @@ -29,4 +29,4 @@ Definition Flocq_version := Eval vm_compute in parse t major (minor * 10 + N_of_ascii h - N_of_ascii "0"%char)%N | Empty_string => (major * 100 + minor)%N end in - parse "2.5.2"%string N0 N0. + parse "2.6.1"%string N0 N0. diff --git a/flocq/Prop/Fprop_mult_error.v b/flocq/Prop/Fprop_mult_error.v index 7c71627b..44448cd6 100644 --- a/flocq/Prop/Fprop_mult_error.v +++ b/flocq/Prop/Fprop_mult_error.v @@ -158,7 +158,6 @@ Notation bpow e := (bpow beta e). Variable emin prec : Z. Context { prec_gt_0_ : Prec_gt_0 prec }. -Variable Hpemin: (emin <= prec)%Z. Notation format := (generic_format beta (FLT_exp emin prec)). Notation cexp := (canonic_exp beta (FLT_exp emin prec)). @@ -173,7 +172,6 @@ Theorem mult_error_FLT : (x*y = 0)%R \/ (bpow (emin + 2*prec - 1) <= Rabs (x * y))%R -> format (round beta (FLT_exp emin prec) rnd (x * y) - (x * y))%R. Proof with auto with typeclass_instances. -clear Hpemin. intros x y Hx Hy Hxy. set (f := (round beta (FLT_exp emin prec) rnd (x * y))). destruct (Req_dec (f - x * y) 0) as [Hr0|Hr0]. diff --git a/flocq/Prop/Fprop_plus_error.v b/flocq/Prop/Fprop_plus_error.v index 41c2f031..9bb5aee8 100644 --- a/flocq/Prop/Fprop_plus_error.v +++ b/flocq/Prop/Fprop_plus_error.v @@ -19,6 +19,7 @@ COPYING file for more details. (** * Error of the rounded-to-nearest addition is representable. *) +Require Import Psatz. Require Import Fcore_Raux. Require Import Fcore_defs. Require Import Fcore_float_prop. @@ -26,6 +27,7 @@ Require Import Fcore_generic_fmt. Require Import Fcore_FIX. Require Import Fcore_FLX. Require Import Fcore_FLT. +Require Import Fcore_ulp. Require Import Fcalc_ops. @@ -267,3 +269,270 @@ rewrite Z2R_plus; ring. Qed. End Fprop_plus_FLT. + +Section Fprop_plus_mult_ulp. + +Variable beta : radix. +Notation bpow e := (bpow beta e). + +Variable fexp : Z -> Z. +Context { valid_exp : Valid_exp fexp }. +Context { monotone_exp : Monotone_exp fexp }. +Variable rnd : R -> Z. +Context { valid_rnd : Valid_rnd rnd }. + +Notation format := (generic_format beta fexp). +Notation cexp := (canonic_exp beta fexp). + +Lemma ex_shift : + forall x e, format x -> (e <= cexp x)%Z -> + exists m, (x = Z2R m * bpow e)%R. +Proof with auto with typeclass_instances. +intros x e Fx He. +exists (Ztrunc (scaled_mantissa beta fexp x)*Zpower beta (cexp x -e))%Z. +rewrite Fx at 1; unfold F2R; simpl. +rewrite Z2R_mult, Rmult_assoc. +f_equal. +rewrite Z2R_Zpower. +2: omega. +rewrite <- bpow_plus; f_equal; ring. +Qed. + +Lemma ln_beta_minus1 : + forall z, z <> 0%R -> + (ln_beta beta z - 1)%Z = ln_beta beta (z / Z2R beta). +Proof. +intros z Hz. +unfold Zminus. +rewrite <- ln_beta_mult_bpow with (1 := Hz). +now rewrite bpow_opp, bpow_1. +Qed. + +Theorem round_plus_mult_ulp : + forall x y, format x -> format y -> (x <> 0)%R -> + exists m, (round beta fexp rnd (x+y) = Z2R m * ulp beta fexp (x/Z2R beta))%R. +Proof with auto with typeclass_instances. +intros x y Fx Fy Zx. +case (Zle_or_lt (ln_beta beta (x/Z2R beta)) (ln_beta beta y)); intros H1. +pose (e:=cexp (x / Z2R beta)). +destruct (ex_shift x e) as (nx, Hnx); try exact Fx. +apply monotone_exp. +rewrite <- (ln_beta_minus1 x Zx); omega. +destruct (ex_shift y e) as (ny, Hny); try assumption. +apply monotone_exp... +destruct (round_repr_same_exp beta fexp rnd (nx+ny) e) as (n,Hn). +exists n. +apply trans_eq with (F2R (Float beta n e)). +rewrite <- Hn; f_equal. +rewrite Hnx, Hny; unfold F2R; simpl; rewrite Z2R_plus; ring. +unfold F2R; simpl. +rewrite ulp_neq_0; try easy. +apply Rmult_integral_contrapositive_currified; try assumption. +apply Rinv_neq_0_compat. +apply Rgt_not_eq. +apply radix_pos. +(* *) +destruct (ex_shift (round beta fexp rnd (x + y)) (cexp (x/Z2R beta))) as (n,Hn). +apply generic_format_round... +apply Zle_trans with (cexp (x+y)). +apply monotone_exp. +rewrite <- ln_beta_minus1 by easy. +rewrite <- (ln_beta_abs beta (x+y)). +(* . *) +assert (U: (Rabs (x+y) = Rabs x + Rabs y)%R \/ (y <> 0 /\ Rabs (x+y) = Rabs x - Rabs y)%R). +assert (V: forall x y, (Rabs y <= Rabs x)%R -> + (Rabs (x+y) = Rabs x + Rabs y)%R \/ (y <> 0 /\ Rabs (x+y) = Rabs x - Rabs y)%R). +clear; intros x y. +case (Rle_or_lt 0 y); intros Hy. +case Hy; intros Hy'. +case (Rle_or_lt 0 x); intros Hx. +intros _; rewrite (Rabs_pos_eq y) by easy. +rewrite (Rabs_pos_eq x) by easy. +left; apply Rabs_pos_eq. +now apply Rplus_le_le_0_compat. +rewrite (Rabs_pos_eq y) by easy. +rewrite (Rabs_left x) by easy. +intros H; right; split. +now apply Rgt_not_eq. +rewrite Rabs_left1. +ring. +apply Rplus_le_reg_l with (-x)%R; ring_simplify; assumption. +intros _; left. +now rewrite <- Hy', Rabs_R0, 2!Rplus_0_r. +case (Rle_or_lt 0 x); intros Hx. +rewrite (Rabs_left y) by easy. +rewrite (Rabs_pos_eq x) by easy. +intros H; right; split. +now apply Rlt_not_eq. +rewrite Rabs_pos_eq. +ring. +apply Rplus_le_reg_l with (-y)%R; ring_simplify; assumption. +intros _; left. +rewrite (Rabs_left y) by easy. +rewrite (Rabs_left x) by easy. +rewrite Rabs_left1. +ring. +lra. +apply V; left. +apply ln_beta_lt_pos with beta. +now apply Rabs_pos_lt. +rewrite <- ln_beta_minus1 in H1; try assumption. +rewrite 2!ln_beta_abs; omega. +(* . *) +destruct U as [U|U]. +rewrite U; apply Zle_trans with (ln_beta beta x). +omega. +rewrite <- ln_beta_abs. +apply ln_beta_le. +now apply Rabs_pos_lt. +apply Rplus_le_reg_l with (-Rabs x)%R; ring_simplify. +apply Rabs_pos. +destruct U as (U',U); rewrite U. +rewrite <- ln_beta_abs. +apply ln_beta_minus_lb. +now apply Rabs_pos_lt. +now apply Rabs_pos_lt. +rewrite 2!ln_beta_abs. +assert (ln_beta beta y < ln_beta beta x - 1)%Z. +now rewrite (ln_beta_minus1 x Zx). +omega. +apply canonic_exp_round_ge... +intros K. +apply round_plus_eq_zero in K... +contradict H1; apply Zle_not_lt. +rewrite <- (ln_beta_minus1 x Zx). +replace y with (-x)%R. +rewrite ln_beta_opp; omega. +lra. +exists n. +rewrite ulp_neq_0. +assumption. +apply Rmult_integral_contrapositive_currified; try assumption. +apply Rinv_neq_0_compat. +apply Rgt_not_eq. +apply radix_pos. +Qed. + +Context {exp_not_FTZ : Exp_not_FTZ fexp}. + +Theorem round_plus_ge_ulp : + forall x y, format x -> format y -> + round beta fexp rnd (x+y) = 0%R \/ + (ulp beta fexp (x/Z2R beta) <= Rabs (round beta fexp rnd (x+y)))%R. +Proof with auto with typeclass_instances. +intros x y Fx Fy. +case (Req_dec x 0); intros Zx. +(* *) +rewrite Zx, Rplus_0_l. +rewrite round_generic... +unfold Rdiv; rewrite Rmult_0_l. +rewrite Fy at 2. +unfold F2R; simpl; rewrite Rabs_mult. +rewrite (Rabs_pos_eq (bpow _)) by apply bpow_ge_0. +case (Z.eq_dec (Ztrunc (scaled_mantissa beta fexp y)) 0); intros Hm. +left. +rewrite Fy, Hm; unfold F2R; simpl; ring. +right. +apply Rle_trans with (1*bpow (cexp y))%R. +rewrite Rmult_1_l. +rewrite <- ulp_neq_0. +apply ulp_ge_ulp_0... +intros K; apply Hm. +rewrite K, scaled_mantissa_0. +apply (Ztrunc_Z2R 0). +apply Rmult_le_compat_r. +apply bpow_ge_0. +rewrite <- Z2R_abs. +apply (Z2R_le 1). +apply (Zlt_le_succ 0). +now apply Z.abs_pos. +(* *) +destruct (round_plus_mult_ulp x y Fx Fy Zx) as (m,Hm). +case (Z.eq_dec m 0); intros Zm. +left. +rewrite Hm, Zm; simpl; ring. +right. +rewrite Hm, Rabs_mult. +rewrite (Rabs_pos_eq (ulp _ _ _)) by apply ulp_ge_0. +apply Rle_trans with (1*ulp beta fexp (x/Z2R beta))%R. +right; ring. +apply Rmult_le_compat_r. +apply ulp_ge_0. +rewrite <- Z2R_abs. +apply (Z2R_le 1). +apply (Zlt_le_succ 0). +now apply Z.abs_pos. +Qed. + +End Fprop_plus_mult_ulp. + +Section Fprop_plus_ge_ulp. + +Variable beta : radix. +Notation bpow e := (bpow beta e). + +Variable rnd : R -> Z. +Context { valid_rnd : Valid_rnd rnd }. +Variable emin prec : Z. +Context { prec_gt_0_ : Prec_gt_0 prec }. + +Theorem round_plus_ge_ulp_FLT : forall x y e, + generic_format beta (FLT_exp emin prec) x -> generic_format beta (FLT_exp emin prec) y -> + (bpow e <= Rabs x)%R -> + round beta (FLT_exp emin prec) rnd (x+y) = 0%R \/ + (bpow (e - prec) <= Rabs (round beta (FLT_exp emin prec) rnd (x+y)))%R. +Proof with auto with typeclass_instances. +intros x y e Fx Fy He. +assert (Zx: x <> 0%R). + contradict He. + apply Rlt_not_le; rewrite He, Rabs_R0. + apply bpow_gt_0. +case round_plus_ge_ulp with beta (FLT_exp emin prec) rnd x y... +intros H; right. +apply Rle_trans with (2:=H). +rewrite ulp_neq_0. +unfold canonic_exp. +rewrite <- ln_beta_minus1 by easy. +unfold FLT_exp; apply bpow_le. +apply Zle_trans with (2:=Z.le_max_l _ _). +destruct (ln_beta beta x) as (n,Hn); simpl. +assert (e < n)%Z; try omega. +apply lt_bpow with beta. +apply Rle_lt_trans with (1:=He). +now apply Hn. +apply Rmult_integral_contrapositive_currified; try assumption. +apply Rinv_neq_0_compat. +apply Rgt_not_eq. +apply radix_pos. +Qed. + +Theorem round_plus_ge_ulp_FLX : forall x y e, + generic_format beta (FLX_exp prec) x -> generic_format beta (FLX_exp prec) y -> + (bpow e <= Rabs x)%R -> + round beta (FLX_exp prec) rnd (x+y) = 0%R \/ + (bpow (e - prec) <= Rabs (round beta (FLX_exp prec) rnd (x+y)))%R. +Proof with auto with typeclass_instances. +intros x y e Fx Fy He. +assert (Zx: x <> 0%R). + contradict He. + apply Rlt_not_le; rewrite He, Rabs_R0. + apply bpow_gt_0. +case round_plus_ge_ulp with beta (FLX_exp prec) rnd x y... +intros H; right. +apply Rle_trans with (2:=H). +rewrite ulp_neq_0. +unfold canonic_exp. +rewrite <- ln_beta_minus1 by easy. +unfold FLX_exp; apply bpow_le. +destruct (ln_beta beta x) as (n,Hn); simpl. +assert (e < n)%Z; try omega. +apply lt_bpow with beta. +apply Rle_lt_trans with (1:=He). +now apply Hn. +apply Rmult_integral_contrapositive_currified; try assumption. +apply Rinv_neq_0_compat. +apply Rgt_not_eq. +apply radix_pos. +Qed. + +End Fprop_plus_ge_ulp. diff --git a/lib/Camlcoq.ml b/lib/Camlcoq.ml index 5c25796e..d94e3582 100644 --- a/lib/Camlcoq.ml +++ b/lib/Camlcoq.ml @@ -20,7 +20,7 @@ open BinNums open BinNat open BinInt open BinPos -open Floats +open! Floats (* Coq's [nat] type and some of its operations *) diff --git a/lib/Coqlib.v b/lib/Coqlib.v index 3fe1ea2e..3b8e5b3b 100644 --- a/lib/Coqlib.v +++ b/lib/Coqlib.v @@ -17,6 +17,7 @@ used throughout the development. It complements the Coq standard library. *) +Require Export String. Require Export ZArith. Require Export Znumtheory. Require Export List. diff --git a/lib/Readconfig.mll b/lib/Readconfig.mll index e71c8fb7..7b98255e 100644 --- a/lib/Readconfig.mll +++ b/lib/Readconfig.mll @@ -43,9 +43,9 @@ let error msg lexbuf = lexbuf.lex_curr_p.pos_lnum, msg))) -let ill_formed_line lexbuf = error "Ill-formed line" lexbuf -let unterminated_quote lexbuf = error "Unterminated quote" lexbuf -let lone_backslash lexbuf = error "Lone \\ (backslash) at end of file" lexbuf +let ill_formed_line lexbuf = error "ill-formed line" lexbuf +let unterminated_quote lexbuf = error "unterminated quote" lexbuf +let lone_backslash lexbuf = error "lone \\ (backslash) at end of file" lexbuf } diff --git a/powerpc/Asm.v b/powerpc/Asm.v index 746a610b..aa15547b 100644 --- a/powerpc/Asm.v +++ b/powerpc/Asm.v @@ -239,6 +239,7 @@ Inductive instruction : Type := | Pld: ireg -> constant -> ireg -> instruction (**r load 64-bit int (PPC64) *) | Pldx: ireg -> ireg -> ireg -> instruction (**r same, with 2 index regs *) | Pld_a: ireg -> constant -> ireg -> instruction (**r load 64-bit quantity to int reg (PPC64) *) + | Pldbrx: ireg -> ireg -> ireg -> instruction (**r load 64-bit int and reverse endianness (PPC64) *) | Pldx_a: ireg -> ireg -> ireg -> instruction (**r same, with 2 index regs *) | Plfd: freg -> constant -> ireg -> instruction (**r load 64-bit float *) | Plfdx: freg -> ireg -> ireg -> instruction (**r same, with 2 index regs *) @@ -307,6 +308,7 @@ Inductive instruction : Type := | Pstbx: ireg -> ireg -> ireg -> instruction (**r same, with 2 index regs *) | Pstd: ireg -> constant -> ireg -> instruction (**r store 64-bit integer (PPC64) *) | Pstdx: ireg -> ireg -> ireg -> instruction (**r same, with 2 index regs (PPC64) *) + | Pstdbrx: ireg -> ireg -> ireg -> instruction (**r store 64-bit int with reverse endianness (PPC64) *) | Pstdu: ireg -> constant -> ireg -> instruction (**r store 64-bit integer with update (PPC64) *) | Pstd_a: ireg -> constant -> ireg -> instruction (**r store 64-bit quantity from int reg (PPC64) *) | Pstdx_a: ireg -> ireg -> ireg -> instruction (**r same, with 2 index regs (PPC64) *) @@ -1077,6 +1079,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out | Picbi _ _ | Picbtls _ _ _ | Pisync + | Pldbrx _ _ _ | Plwsync | Plhbrx _ _ _ | Plwzu _ _ _ @@ -1086,6 +1089,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out | Pmtspr _ _ | Prldicl _ _ _ _ | Prldimi _ _ _ _ + | Pstdbrx _ _ _ | Pstdu _ _ _ | Pstwbrx _ _ _ | Pstwcx_ _ _ _ @@ -1126,6 +1130,15 @@ Definition preg_of (r: mreg) : preg := | F28 => FPR28 | F29 => FPR29 | F30 => FPR30 | F31 => FPR31 end. +(** Undefine all registers except SP and callee-save registers *) + +Definition undef_caller_save_regs (rs: regset) : regset := + fun r => + if preg_eq r SP + || In_dec preg_eq r (List.map preg_of (List.filter is_callee_save all_mregs)) + then rs r + else Vundef. + (** Extract the values of the arguments of an external call. We exploit the calling conventions from module [Conventions], except that we use PPC registers instead of locations. *) @@ -1185,7 +1198,7 @@ Inductive step: state -> trace -> state -> Prop := Genv.find_funct_ptr ge b = Some (External ef) -> external_call ef ge args m t res m' -> extcall_arguments rs m (ef_sig ef) args -> - rs' = (set_pair (loc_external_result (ef_sig ef)) res rs) #PC <- (rs RA) -> + rs' = (set_pair (loc_external_result (ef_sig ef)) res (undef_caller_save_regs rs)) #PC <- (rs RA) -> step (State rs m) t (State rs' m'). End RELSEM. diff --git a/powerpc/AsmToJSON.ml b/powerpc/AsmToJSON.ml index 720d09a6..ee3eaca8 100644 --- a/powerpc/AsmToJSON.ml +++ b/powerpc/AsmToJSON.ml @@ -97,14 +97,14 @@ let mnemonic_names =["Padd"; "Paddc"; "Padde"; "Paddi"; "Paddic"; "Paddis"; "Pa "Pfmadd"; "Pfmr"; "Pfmsub"; "Pfmul"; "Pfmuls"; "Pfneg"; "Pfnmadd"; "Pfnmsub"; "Pfres"; "Pfrsp"; "Pfrsqrte"; "Pfsel"; "Pfsqrt"; "Pfsub"; "Pfsubs"; "Picbi"; "Picbtls"; "Pinlineasm"; "Pisel"; "Pisync"; "Plabel"; - "Plbz"; "Plbzx"; "Pld"; "Pldi"; "Pldx"; "Plfd"; "Plfdx"; "Plfi"; "Plfis"; + "Plbz"; "Plbzx"; "Pld"; "Pldbrx"; "Pldi"; "Pldx"; "Plfd"; "Plfdx"; "Plfi"; "Plfis"; "Plfs"; "Plfsx"; "Plha"; "Plhax"; "Plhbrx"; "Plhz"; "Plhzx"; "Plwarx"; "Plwbrx"; "Plwsync"; "Plwz"; "Plwzu"; "Plwzx"; "Pmbar"; "Pmfcr"; "Pmflr"; "Pmfspr"; "Pmr"; "Pmtctr"; "Pmtlr"; "Pmtspr"; "Pmulhd"; "Pmulhdu"; "Pmulhw"; "Pmulhwu"; "Pmulld"; "Pmulli"; "Pmullw"; "Pnand"; "Pnor"; "Por"; "Porc"; "Pori"; "Poris"; "Prldicl"; "Prldimi"; "Prldinm"; "Prlwimi"; "Prlwinm"; "Psld"; "Pslw"; "Psrad"; "Psradi"; "Psraw"; "Psrawi"; "Psrd"; "Psrw"; - "Pstb"; "Pstbx"; "Pstd"; "Pstdu"; "Pstdx"; "Pstfd"; "Pstfdu"; "Pstfdx"; + "Pstb"; "Pstbx"; "Pstd"; "Pstdbrx"; "Pstdu"; "Pstdx"; "Pstfd"; "Pstfdu"; "Pstfdx"; "Pstfs"; "Pstfsx"; "Psth"; "Psthbrx"; "Psthx"; "Pstw"; "Pstwbrx"; "Pstwcx_"; "Pstwu"; "Pstwux"; "Pstwx"; "Psubfc"; "Psubfe"; "Psubfic"; "Psubfze"; "Psync"; "Ptrap"; "Pxor"; "Pxori"; "Pxoris"] @@ -236,6 +236,7 @@ let pp_instructions pp ic = | Plbzx (ir1,ir2,ir3) -> instruction pp "Plbzx" [Ireg ir1; Ireg ir2; Ireg ir3] | Pld (ir1,c,ir2) | Pld_a (ir1,c,ir2) -> instruction pp "Pld" [Ireg ir1; Constant c; Ireg ir2] + | Pldbrx (ir1,ir2,ir3) -> instruction pp "Pldbrx" [Ireg ir1; Ireg ir2; Ireg ir3] | Pldx (ir1,ir2,ir3) | Pldx_a (ir1,ir2,ir3) -> instruction pp "Pldx" [Ireg ir1; Ireg ir2; Ireg ir3] | Plfd (fr,c,ir) @@ -305,6 +306,7 @@ let pp_instructions pp ic = | Pstbx (ir1,ir2,ir3) -> instruction pp "Pstbx" [Ireg ir1; Ireg ir2; Ireg ir3] | Pstd (ir1,c,ir2) | Pstd_a (ir1,c,ir2) -> instruction pp "Pstd" [Ireg ir1; Constant c; Ireg ir2] + | Pstdbrx (ir1,ir2,ir3) -> instruction pp "Pstdbrx" [Ireg ir1; Ireg ir2; Ireg ir3] | Pstdx (ir1,ir2,ir3) | Pstdx_a (ir1,ir2,ir3) -> instruction pp "Pstdx" [Ireg ir1; Ireg ir2; Ireg ir3] | Pstdu (ir1,c,ir2) -> instruction pp "Pstdu" [Ireg ir1; Constant c; Ireg ir2] diff --git a/powerpc/Asmexpand.ml b/powerpc/Asmexpand.ml index 96b11056..5a2df8d3 100644 --- a/powerpc/Asmexpand.ml +++ b/powerpc/Asmexpand.ml @@ -433,6 +433,16 @@ let expand_builtin_inline name args res = emit (Pmulhw(res, a1, a2)) | "__builtin_mulhwu", [BA(IR a1); BA(IR a2)], BR(IR res) -> emit (Pmulhwu(res, a1, a2)) + | "__builtin_mulhd", [BA(IR a1); BA(IR a2)], BR(IR res) -> + if Archi.ppc64 then + emit (Pmulhd(res, a1, a2)) + else + raise (Error "__builtin_mulhd is only supported for PPC64 targets") + | "__builtin_mulhdu", [BA(IR a1); BA(IR a2)], BR(IR res) -> + if Archi.ppc64 then + emit (Pmulhdu(res, a1, a2)) + else + raise (Error "__builtin_mulhdu is only supported for PPC64 targets") | ("__builtin_clz" | "__builtin_clzl"), [BA(IR a1)], BR(IR res) -> emit (Pcntlzw(res, a1)) | "__builtin_clzll", [BA(IR a1)], BR(IR res) -> @@ -543,10 +553,20 @@ let expand_builtin_inline name args res = emit (Plhbrx(res, GPR0, a1)) | "__builtin_read32_reversed", [BA(IR a1)], BR(IR res) -> emit (Plwbrx(res, GPR0, a1)) + | "__builtin_read64_reversed", [BA(IR a1)], BR(IR res) -> + if Archi.ppc64 then + emit (Pldbrx(res, GPR0, a1)) + else + raise (Error "__builtin_read64_reversed is only supported for PPC64 targets") | "__builtin_write16_reversed", [BA(IR a1); BA(IR a2)], _ -> emit (Psthbrx(a2, GPR0, a1)) | "__builtin_write32_reversed", [BA(IR a1); BA(IR a2)], _ -> emit (Pstwbrx(a2, GPR0, a1)) + | "__builtin_write64_reversed", [BA(IR a1); BA(IR a2)], _ -> + if Archi.ppc64 then + emit (Pstdbrx(a2, GPR0, a1)) + else + raise (Error "__builtin_write64_reversed is only supported for PPC64 targets") (* Synchronization *) | "__builtin_membar", [], _ -> () @@ -562,7 +582,7 @@ let expand_builtin_inline name args res = if not (mo = _0 || mo = _1) then raise (Error "the argument of __builtin_mbar must be 0 or 1"); emit (Pmbar mo) - | "__builin_mbar", _, _ -> + | "__builtin_mbar", _, _ -> raise (Error "the argument of __builtin_mbar must be a constant"); | "__builtin_trap", [], _ -> emit (Ptrap) @@ -871,7 +891,7 @@ let expand_instruction instr = expand_builtin_memcpy (Z.to_int sz) (Z.to_int al) args | EF_annot_val(kind,txt, targ) -> expand_annot_val kind txt targ args res - | EF_annot _ | EF_debug _ | EF_inline_asm _ -> + | EF_annot _ | EF_debug _ | EF_inline_asm _ -> emit instr | _ -> assert false @@ -912,10 +932,7 @@ let preg_to_dwarf = function let expand_function id fn = try set_current_function fn; - if !Clflags.option_g then - expand_debug id 1 preg_to_dwarf expand_instruction fn.fn_code - else - List.iter expand_instruction fn.fn_code; + expand id 1 preg_to_dwarf expand_instruction fn.fn_code; Errors.OK (get_current_function ()) with Error s -> Errors.Error (Errors.msg (coqstring_of_camlstring s)) diff --git a/powerpc/Asmgenproof.v b/powerpc/Asmgenproof.v index 9f258e3d..8ad28aea 100644 --- a/powerpc/Asmgenproof.v +++ b/powerpc/Asmgenproof.v @@ -918,8 +918,8 @@ Local Transparent destroyed_by_jumptable. apply plus_one. eapply exec_step_external; eauto. eapply external_call_symbols_preserved; eauto. apply senv_preserved. econstructor; eauto. - unfold loc_external_result. - apply agree_set_other; auto. apply agree_set_pair; auto. + unfold loc_external_result. apply agree_set_other; auto. apply agree_set_pair; auto. + apply agree_undef_caller_save_regs; auto. - (* return *) inv STACKS. simpl in *. diff --git a/powerpc/CBuiltins.ml b/powerpc/CBuiltins.ml index 35d6b89f..c76b69ba 100644 --- a/powerpc/CBuiltins.ml +++ b/powerpc/CBuiltins.ml @@ -42,6 +42,11 @@ let builtins = { (TInt(IInt, []), [TInt(IULongLong, [])], false); "__builtin_cmpb", (TInt (IUInt, []), [TInt(IUInt, []);TInt(IUInt, [])], false); + (* Integer arithmetic in 32/64-bit hybrid mode *) + "__builtin_mulhd", + (TInt(ILongLong, []), [TInt(ILongLong, []); TInt(ILongLong, [])], false); + "__builtin_mulhdu", + (TInt(IULongLong, []), [TInt(IULongLong, []); TInt(IULongLong, [])], false); (* Float arithmetic *) "__builtin_fmadd", (TFloat(FDouble, []), @@ -80,6 +85,11 @@ let builtins = { (TVoid [], [TPtr(TInt(IUShort, []), []); TInt(IUShort, [])], false); "__builtin_write32_reversed", (TVoid [], [TPtr(TInt(IUInt, []), []); TInt(IUInt, [])], false); + (* Memory accesses in 32/64-bit hybrid mode *) + "__builtin_read64_reversed", + (TInt(IULongLong, []), [TPtr(TInt(IULongLong, [AConst]), [])], false); + "__builtin_write64_reversed", + (TVoid [], [TPtr(TInt(IULongLong, []), []); TInt(IULongLong, [])], false); (* Synchronization *) "__builtin_eieio", (TVoid [], [], false); @@ -113,7 +123,7 @@ let builtins = { (TInt(IUInt, []), [TInt(IInt, [])], false); "__builtin_set_spr", (TVoid [], [TInt(IInt, []); TInt(IUInt, [])], false); - (* Access to special registers in 32bit hybrid mode*) + (* Access to special registers in 32/64-bit hybrid mode *) "__builtin_get_spr64", (TInt(IULongLong, []), [TInt(IInt, [])], false); "__builtin_set_spr64", @@ -135,7 +145,7 @@ let builtins = { (* no operation *) "__builtin_nop", (TVoid [], [], false); - (* atomic operations *) + (* Atomic operations *) "__builtin_atomic_exchange", (TVoid [], [TPtr (TInt(IInt, []),[]);TPtr (TInt(IInt, []),[]);TPtr (TInt(IInt, []),[])],false); "__builtin_atomic_load", diff --git a/powerpc/TargetPrinter.ml b/powerpc/TargetPrinter.ml index 9a6840b1..c1aaa55d 100644 --- a/powerpc/TargetPrinter.ml +++ b/powerpc/TargetPrinter.ml @@ -605,7 +605,7 @@ module Target (System : SYSTEM):TARGET = | Pisel (r1,r2,r3,cr) -> fprintf oc " isel %a, %a, %a, %a\n" ireg r1 ireg r2 ireg r3 crbit cr | Picbi (r1,r2) -> - fprintf oc " icbi %a,%a\n" ireg r1 ireg r2 + fprintf oc " icbi %a, %a\n" ireg r1 ireg r2 | Picbtls (n,r1,r2) -> fprintf oc " icbtls %ld, %a, %a\n" (camlint_of_coqint n) ireg r1 ireg r2 | Pisync -> @@ -618,6 +618,8 @@ module Target (System : SYSTEM):TARGET = fprintf oc " lbzx %a, %a, %a\n" ireg r1 ireg r2 ireg r3 | Pld(r1, c, r2) | Pld_a(r1, c, r2) -> fprintf oc " ld %a, %a(%a)\n" ireg r1 constant c ireg r2 + | Pldbrx(r1, r2, r3) -> + fprintf oc " ldbrx %a, %a, %a\n" ireg r1 ireg r2 ireg r3 | Pldx(r1, r2, r3) | Pldx_a(r1, r2, r3) -> fprintf oc " ldx %a, %a, %a\n" ireg r1 ireg r2 ireg r3 | Plfd(r1, c, r2) | Plfd_a(r1, c, r2) -> @@ -772,6 +774,8 @@ module Target (System : SYSTEM):TARGET = fprintf oc " stbx %a, %a, %a\n" ireg r1 ireg r2 ireg r3 | Pstd(r1, c, r2) | Pstd_a(r1, c, r2) -> fprintf oc " std %a, %a(%a)\n" ireg r1 constant c ireg r2 + | Pstdbrx(r1, r2, r3) -> + fprintf oc " stdbrx %a, %a, %a\n" ireg r1 ireg r2 ireg r3 | Pstdx(r1, r2, r3) | Pstdx_a(r1, r2, r3) -> fprintf oc " stdx %a, %a, %a\n" ireg r1 ireg r2 ireg r3 | Pstdu(r1, c, r2) -> @@ -840,7 +844,7 @@ module Target (System : SYSTEM):TARGET = fprintf oc "%s annotation: %S\n" comment annot | 2 -> let lbl = new_label () in - fprintf oc "%a: " label lbl; + fprintf oc "%a:\n" label lbl; add_ais_annot lbl preg_annot "r1" (camlstring_of_coqstring txt) args | _ -> assert false end @@ -875,6 +879,7 @@ module Target (System : SYSTEM):TARGET = | Pbf(bit, lbl) -> 2 | Pbt(bit, lbl) -> 2 | Pbtbl(r, tbl) -> 5 + | Pldi (r1,c) -> 2 | Plfi(r1, c) -> 2 | Plfis(r1, c) -> 2 | Plabel lbl -> 0 diff --git a/riscV/Asm.v b/riscV/Asm.v index 4cd3b1fd..1d8fda11 100644 --- a/riscV/Asm.v +++ b/riscV/Asm.v @@ -344,7 +344,8 @@ Inductive instruction : Type := | Ploadsi (rd: freg) (f: float32) (**r load an immediate single *) | Pbtbl (r: ireg) (tbl: list label) (**r N-way branch through a jump table *) | Pbuiltin: external_function -> list (builtin_arg preg) - -> builtin_res preg -> instruction. (**r built-in function (pseudo) *) + -> builtin_res preg -> instruction (**r built-in function (pseudo) *) + | Pnop : instruction. (**r nop instruction *) (** The pseudo-instructions are the following: @@ -985,6 +986,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out | Pfmsubd _ _ _ _ | Pfnmaddd _ _ _ _ | Pfnmsubd _ _ _ _ + | Pnop => Stuck end. @@ -1013,6 +1015,15 @@ Definition preg_of (r: mreg) : preg := | Machregs.F28 => F28 | Machregs.F29 => F29 | Machregs.F30 => F30 | Machregs.F31 => F31 end. +(** Undefine all registers except SP and callee-save registers *) + +Definition undef_caller_save_regs (rs: regset) : regset := + fun r => + if preg_eq r SP + || In_dec preg_eq r (List.map preg_of (List.filter is_callee_save all_mregs)) + then rs r + else Vundef. + (** Extract the values of the arguments of an external call. We exploit the calling conventions from module [Conventions], except that we use RISC-V registers instead of locations. *) @@ -1073,7 +1084,7 @@ Inductive step: state -> trace -> state -> Prop := Genv.find_funct_ptr ge b = Some (External ef) -> external_call ef ge args m t res m' -> extcall_arguments rs m (ef_sig ef) args -> - rs' = (set_pair (loc_external_result (ef_sig ef) ) res rs)#PC <- (rs RA) -> + rs' = (set_pair (loc_external_result (ef_sig ef) ) res (undef_caller_save_regs rs))#PC <- (rs RA) -> step (State rs m) t (State rs' m'). End RELSEM. diff --git a/riscV/Asmexpand.ml b/riscV/Asmexpand.ml index 945974e0..3e734747 100644 --- a/riscV/Asmexpand.ml +++ b/riscV/Asmexpand.ml @@ -23,7 +23,7 @@ open Asm open Asmexpandaux open AST open Camlcoq -open Integers +open !Integers exception Error of string @@ -468,7 +468,8 @@ let expand_builtin_inline name args res = (fun rl -> emit (Pmulw (rl, X a, X b)); emit (Pmulhuw (rh, X a, X b))) - + | "__builtin_nop", [], _ -> + emit Pnop (* Catch-all *) | _ -> raise (Error ("unrecognized builtin " ^ name)) @@ -598,10 +599,7 @@ let preg_to_dwarf = function let expand_function id fn = try set_current_function fn; - if !Clflags.option_g then - expand_debug id (* sp= *) 2 preg_to_dwarf expand_instruction fn.fn_code - else - List.iter expand_instruction fn.fn_code; + expand id (* sp= *) 2 preg_to_dwarf expand_instruction fn.fn_code; Errors.OK (get_current_function ()) with Error s -> Errors.Error (Errors.msg (coqstring_of_camlstring s)) diff --git a/riscV/Asmgenproof.v b/riscV/Asmgenproof.v index cc45a8de..5ec57886 100644 --- a/riscV/Asmgenproof.v +++ b/riscV/Asmgenproof.v @@ -975,8 +975,8 @@ Local Transparent destroyed_at_function_entry. apply plus_one. eapply exec_step_external; eauto. eapply external_call_symbols_preserved; eauto. apply senv_preserved. econstructor; eauto. - unfold loc_external_result. - apply agree_set_other; auto. apply agree_set_pair; auto. + unfold loc_external_result. apply agree_set_other; auto. apply agree_set_pair; auto. + apply agree_undef_caller_save_regs; auto. - (* return *) inv STACKS. simpl in *. diff --git a/riscV/TargetPrinter.ml b/riscV/TargetPrinter.ml index e3fbfe36..19704bad 100644 --- a/riscV/TargetPrinter.ml +++ b/riscV/TargetPrinter.ml @@ -564,6 +564,8 @@ module Target : TARGET = fprintf oc " jr x5\n"; jumptables := (lbl, tbl) :: !jumptables; fprintf oc "%s end pseudoinstr btbl\n" comment + | Pnop -> + fprintf oc " nop\n" | Pbuiltin(ef, args, res) -> begin match ef with | EF_annot(kind,txt, targs) -> @@ -571,7 +573,7 @@ module Target : TARGET = | 1 -> let annot = annot_text preg_annot "x2" (camlstring_of_coqstring txt) args in fprintf oc "%s annotation: %S\n" comment annot | 2 -> let lbl = new_label () in - fprintf oc "%a: " label lbl; + fprintf oc "%a:\n" label lbl; add_ais_annot lbl preg_annot "x2" (camlstring_of_coqstring txt) args | _ -> assert false end diff --git a/runtime/include/stddef.h b/runtime/include/stddef.h index 452497c3..6056db62 100644 --- a/runtime/include/stddef.h +++ b/runtime/include/stddef.h @@ -117,4 +117,13 @@ typedef signed int wchar_t; #define offsetof(ty,member) (__builtin_offsetof(ty,member)) #endif +#ifdef _STDDEF_H +/* Type whose alignment is supported in every context and is at least + as great as that of any standard type not using alignment + specifiers. Since we do not support long double per default the type + with the maximum alignment supported in every context is long long. +*/ +typedef long long max_align_t; +#endif + #endif diff --git a/test/Makefile b/test/Makefile index e53dfd83..504e4c53 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,4 +1,9 @@ +include ../Makefile.config + DIRS=c compression raytracer spass regression +ifeq ($(CLIGHTGEN),true) +DIRS+=clightgen +endif all: set -e; for i in $(DIRS); do $(MAKE) CCOMPOPTS='$(CCOMPOPTS)' -C $$i all; done @@ -6,6 +11,9 @@ all: test: set -e; for i in $(DIRS); do $(MAKE) SIMU='$(SIMU)' -C $$i test; done +parallel: + parallel $(MAKE) SIMU='$(SIMU)' -C {} test ::: $(DIRS) + bench: for i in $(DIRS); do $(MAKE) -C $$i bench; done diff --git a/test/clightgen/Makefile b/test/clightgen/Makefile new file mode 100644 index 00000000..0607e2fa --- /dev/null +++ b/test/clightgen/Makefile @@ -0,0 +1,44 @@ +include ../../Makefile.config + +ifeq ($(wildcard ../../$(ARCH)_$(BITSIZE)),) +ARCHDIRS=$(ARCH) +else +ARCHDIRS=$(ARCH)_$(BITSIZE) $(ARCH) +endif +RECDIRS=lib common $(ARCHDIRS) cfrontend flocq exportclight +COQINCLUDES=$(foreach d, $(RECDIRS), -R ../../$(d) compcert.$(d)) + +CLIGHTGEN=../../clightgen +COQC=coqc + +# Regression tests in the current directory +SRC=$(wildcard *.c) +# From ../c +SRC+=aes.c almabench.c binarytrees.c bisect.c chomp.c fannkuch.c fft.c \ + fftsp.c fftw.c fib.c integr.c knucleotide.c lists.c mandelbrot.c \ + nbody.c nsievebits.c nsieve.c perlin.c qsort.c sha1.c sha3.c \ + siphash24.c spectral.c vmach.c +# From ../raytracer +SRC+=arrays.c eval.c gmllexer.c gmlparser.c intersect.c light.c main.c \ + matrix.c memory.c object.c render.c simplify.c surface.c vector.c + +all: $(SRC:.c=.vo) + +test: + +%.v: %.c + $(CLIGHTGEN) $(CFLAGS) -o $@ $< + +%.v: ../c/%.c + $(CLIGHTGEN) $(CFLAGS) -o $@ $< + +%.v: ../raytracer/%.c + $(CLIGHTGEN) -I../raytracer -fall $(CFLAGS) -o $@ $< + +%.vo: %.v + $(COQC) $(COQINCLUDES) -noglob $< + +.SECONDARY: $(SRC:.c=.v) + +clean: + rm -f *.v *.vo .*.aux diff --git a/test/clightgen/empty.c b/test/clightgen/empty.c new file mode 100644 index 00000000..8f8871a7 --- /dev/null +++ b/test/clightgen/empty.c @@ -0,0 +1 @@ +/* The empty source file */ diff --git a/test/clightgen/issue196.c b/test/clightgen/issue196.c new file mode 100644 index 00000000..1821fd6d --- /dev/null +++ b/test/clightgen/issue196.c @@ -0,0 +1,927 @@ +#include <stdint.h> +#include <stdlib.h> +#include <sys/types.h> + + +typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct asn1_object_st ASN1_OBJECT; +typedef struct asn1_pctx_st ASN1_PCTX; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_STRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_VISIBLESTRING; + +typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID; +typedef struct DIST_POINT_st DIST_POINT; +typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT; +typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS; +typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE; +typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL; +typedef struct X509_POLICY_NODE_st X509_POLICY_NODE; +typedef struct X509_POLICY_TREE_st X509_POLICY_TREE; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_st X509_CRL; +typedef struct X509_pubkey_st X509_PUBKEY; +typedef struct bignum_ctx BN_CTX; +typedef struct bignum_st BIGNUM; +typedef struct bio_method_st BIO_METHOD; +typedef struct bio_st BIO; +typedef struct bn_gencb_st BN_GENCB; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct buf_mem_st BUF_MEM; +typedef struct cbb_st CBB; +typedef struct cbs_st CBS; +typedef struct conf_st CONF; +typedef struct dh_method DH_METHOD; +typedef struct dh_st DH; +typedef struct dsa_method DSA_METHOD; +typedef struct dsa_st DSA; +typedef struct ec_key_st EC_KEY; +typedef struct ecdsa_method_st ECDSA_METHOD; +typedef struct ecdsa_sig_st ECDSA_SIG; +typedef struct engine_st ENGINE; +typedef struct env_md_ctx_st EVP_MD_CTX; +typedef struct env_md_st EVP_MD; +typedef struct evp_aead_st EVP_AEAD; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; +typedef struct evp_pkey_st EVP_PKEY; +typedef struct hmac_ctx_st HMAC_CTX; +typedef struct md4_state_st MD4_CTX; +typedef struct md5_state_st MD5_CTX; +typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; +typedef struct pkcs12_st PKCS12; +typedef struct rand_meth_st RAND_METHOD; +typedef struct rc4_key_st RC4_KEY; +typedef struct rsa_meth_st RSA_METHOD; +typedef struct rsa_st RSA; +typedef struct sha256_state_st SHA256_CTX; +typedef struct sha512_state_st SHA512_CTX; +typedef struct sha_state_st SHA_CTX; +typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_st SSL; +typedef struct st_ERR_FNS ERR_FNS; +typedef struct v3_ext_ctx X509V3_CTX; +typedef struct x509_crl_method_st X509_CRL_METHOD; +typedef struct x509_revoked_st X509_REVOKED; +typedef struct x509_st X509; +typedef struct x509_store_ctx_st X509_STORE_CTX; +typedef struct x509_store_st X509_STORE; +typedef void *OPENSSL_BLOCK; + const EVP_MD *EVP_md4(void); + const EVP_MD *EVP_md5(void); + const EVP_MD *EVP_sha1(void); + const EVP_MD *EVP_sha224(void); + const EVP_MD *EVP_sha256(void); + const EVP_MD *EVP_sha384(void); + const EVP_MD *EVP_sha512(void); + + + + const EVP_MD *EVP_md5_sha1(void); + + + + const EVP_MD *EVP_get_digestbynid(int nid); + + + + const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj); + void EVP_MD_CTX_init(EVP_MD_CTX *ctx); + + + + EVP_MD_CTX *EVP_MD_CTX_create(void); + + + + int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); + + + void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); + + + + int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); + + + + + + + + int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, + ENGINE *engine); + + + + int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); + + + + int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, + size_t len); + int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, + unsigned int *out_size); + + + + int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md_out, + unsigned int *out_size); + + + + + + + int EVP_Digest(const void *data, size_t len, uint8_t *md_out, + unsigned int *md_out_size, const EVP_MD *type, + ENGINE *impl); + int EVP_MD_type(const EVP_MD *md); + + + const char *EVP_MD_name(const EVP_MD *md); + + + + uint32_t EVP_MD_flags(const EVP_MD *md); + + + size_t EVP_MD_size(const EVP_MD *md); + + + size_t EVP_MD_block_size(const EVP_MD *md); + int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in); + + + + int EVP_add_digest(const EVP_MD *digest); + + + + + + + const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); + + + + unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx); + + + + unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx); + + + + + int EVP_MD_CTX_type(const EVP_MD_CTX *ctx); + + + void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, uint32_t flags); + + + + void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, uint32_t flags); + + + + uint32_t EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, + uint32_t flags); + + +struct evp_md_pctx_ops; + +struct env_md_ctx_st { + + const EVP_MD *digest; + + uint32_t flags; + + + void *md_data; + + + + int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); + + + + EVP_PKEY_CTX *pctx; + + + + const struct evp_md_pctx_ops *pctx_ops; +} ; + + int MD4_Init(MD4_CTX *md4); + + + int MD4_Update(MD4_CTX *md4, const void *data, size_t len); + + + + + int MD4_Final(uint8_t *md, MD4_CTX *md4); + + + + void MD4_Transform(MD4_CTX *md4, const uint8_t *block); + +struct md4_state_st { + uint32_t A, B, C, D; + uint32_t Nl, Nh; + uint32_t data[16]; + unsigned int num; +}; + int MD5_Init(MD5_CTX *md5); + + + int MD5_Update(MD5_CTX *md5, const void *data, size_t len); + + + + + int MD5_Final(uint8_t *md, MD5_CTX *md5); + + + + uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out); + + + + void MD5_Transform(MD5_CTX *md5, const uint8_t *block); + +struct md5_state_st { + uint32_t A, B, C, D; + uint32_t Nl, Nh; + uint32_t data[16]; + unsigned int num; +}; +struct cbs_st { + const uint8_t *data; + size_t len; +}; + + + + void CBS_init(CBS *cbs, const uint8_t *data, size_t len); + + + + int CBS_skip(CBS *cbs, size_t len); + + + const uint8_t *CBS_data(const CBS *cbs); + + + size_t CBS_len(const CBS *cbs); + + + + + + + int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len); + int CBS_strdup(const CBS *cbs, char **out_ptr); + + + + int CBS_contains_zero_byte(const CBS *cbs); + + + + + int CBS_mem_equal(const CBS *cbs, const uint8_t *data, + size_t len); + + + + int CBS_get_u8(CBS *cbs, uint8_t *out); + + + + int CBS_get_u16(CBS *cbs, uint16_t *out); + + + + int CBS_get_u24(CBS *cbs, uint32_t *out); + + + + int CBS_get_u32(CBS *cbs, uint32_t *out); + + + + int CBS_get_bytes(CBS *cbs, CBS *out, size_t len); + + + + + int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out); + + + + + int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out); + + + + + int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out); + int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value); + + + + int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value); + + + + + + + int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value); + int CBS_get_any_asn1_element(CBS *cbs, CBS *out, + unsigned *out_tag, + size_t *out_header_len); + + + + + + int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out); + + + + + + + int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, + unsigned tag); + + + + + + + + int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, + int *out_present, + unsigned tag); + + + + + + + int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, + unsigned tag, + uint64_t default_value); + + + + + + + int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag, + int default_value); +struct cbb_buffer_st { + uint8_t *buf; + size_t len; + size_t cap; + char can_resize; + +}; + +struct cbb_st { + struct cbb_buffer_st *base; + + + size_t offset; + + struct cbb_st *child; + + + uint8_t pending_len_len; + char pending_is_asn1; + + + char is_top_level; +}; + + + + + int CBB_init(CBB *cbb, size_t initial_capacity); + + + + + int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); + + + + + void CBB_cleanup(CBB *cbb); + int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len); + + + + + int CBB_flush(CBB *cbb); + + + + + int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents); + + + + + int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents); + + + + + int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents); + + + + + + + int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag); + + + + int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len); + + + + + + int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len); + + + + int CBB_add_u8(CBB *cbb, uint8_t value); + + + + int CBB_add_u16(CBB *cbb, uint16_t value); + + + + int CBB_add_u24(CBB *cbb, uint32_t value); + + + + + int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); + ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *obj); + + + + int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); + + + + + + + int OBJ_obj2nid(const ASN1_OBJECT *obj); + + + + int OBJ_cbs2nid(const CBS *cbs); + + + + int OBJ_sn2nid(const char *short_name); + + + + int OBJ_ln2nid(const char *long_name); + + + + + int OBJ_txt2nid(const char *s); + + + + + + + const ASN1_OBJECT *OBJ_nid2obj(int nid); + + + const char *OBJ_nid2sn(int nid); + + + const char *OBJ_nid2ln(int nid); + + + + int OBJ_nid2cbb(CBB *out, int nid); + ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names); + int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, + int dont_return_name); + + + + + + + int OBJ_create(const char *oid, const char *short_name, + const char *long_name); + int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, + int *out_pkey_nid); + + + + + + + int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, + int pkey_nid); + int SHA1_Init(SHA_CTX *sha); + + + int SHA1_Update(SHA_CTX *sha, const void *data, size_t len); + + + + + int SHA1_Final(uint8_t *md, SHA_CTX *sha); + + + + + uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out); + + + + void SHA1_Transform(SHA_CTX *sha, const uint8_t *block); + +struct sha_state_st { + uint32_t h0, h1, h2, h3, h4; + uint32_t Nl, Nh; + uint32_t data[16]; + unsigned int num; +}; + int SHA224_Init(SHA256_CTX *sha); + + + int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len); + + + + int SHA224_Final(uint8_t *md, SHA256_CTX *sha); + + + + + uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out); + int SHA256_Init(SHA256_CTX *sha); + + + int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len); + + + + int SHA256_Final(uint8_t *md, SHA256_CTX *sha); + + + + + uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out); + + + + void SHA256_Transform(SHA256_CTX *sha, const uint8_t *data); + +struct sha256_state_st { + uint32_t h[8]; + uint32_t Nl, Nh; + uint32_t data[16]; + unsigned int num, md_len; +}; + int SHA384_Init(SHA512_CTX *sha); + + + int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len); + + + + int SHA384_Final(uint8_t *md, SHA512_CTX *sha); + + + + + uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out); + + + + void SHA384_Transform(SHA512_CTX *sha, const uint8_t *data); + int SHA512_Init(SHA512_CTX *sha); + + + int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len); + + + + int SHA512_Final(uint8_t *md, SHA512_CTX *sha); + + + + + uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out); + + + + void SHA512_Transform(SHA512_CTX *sha, const uint8_t *data); + +struct sha512_state_st { + uint64_t h[8]; + uint64_t Nl, Nh; + union { + uint64_t d[16]; + uint8_t p[128]; + } u; + unsigned int num, md_len; +}; + +struct env_md_st { + + + int type; + + + unsigned md_size; + + + uint32_t flags; + + + + int (*init)(EVP_MD_CTX *ctx); + + + int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count); + + + int (*final)(EVP_MD_CTX *ctx, uint8_t *out); + + + unsigned block_size; + + + unsigned ctx_size; +}; + + + + +struct evp_md_pctx_ops { + + + void (*free) (EVP_PKEY_CTX *pctx); + + + + EVP_PKEY_CTX* (*dup) (EVP_PKEY_CTX *pctx); + + + + int (*begin_digest) (EVP_MD_CTX *ctx); +}; + + +static int md4_init(EVP_MD_CTX *ctx) { return MD4_Init(ctx->md_data); } + +static int md4_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + return MD4_Update(ctx->md_data, data, count); +} + +static int md4_final(EVP_MD_CTX *ctx, unsigned char *out) { + return MD4_Final(out, ctx->md_data); +} + +static const EVP_MD md4_md = { + 257, 16, 0 , md4_init, + md4_update, md4_final, 64 , sizeof(MD4_CTX), +}; + +const EVP_MD *EVP_md4(void) { return &md4_md; } + + +static int md5_init(EVP_MD_CTX *ctx) { return MD5_Init(ctx->md_data); } + +static int md5_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + return MD5_Update(ctx->md_data, data, count); +} + +static int md5_final(EVP_MD_CTX *ctx, unsigned char *out) { + return MD5_Final(out, ctx->md_data); +} + +static const EVP_MD md5_md = { + 4, 16, 0 , md5_init, + md5_update, md5_final, 64 , sizeof(MD5_CTX), +}; + +const EVP_MD *EVP_md5(void) { return &md5_md; } + + +static int sha1_init(EVP_MD_CTX *ctx) { return SHA1_Init(ctx->md_data); } + +static int sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + return SHA1_Update(ctx->md_data, data, count); +} + +static int sha1_final(EVP_MD_CTX *ctx, unsigned char *md) { + return SHA1_Final(md, ctx->md_data); +} + +static const EVP_MD sha1_md = { + 64, 20, 0 , sha1_init, + sha1_update, sha1_final, 64 , sizeof(SHA_CTX), +}; + +const EVP_MD *EVP_sha1(void) { return &sha1_md; } + + +static int sha224_init(EVP_MD_CTX *ctx) { return SHA224_Init(ctx->md_data); } + +static int sha224_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + return SHA224_Update(ctx->md_data, data, count); +} + +static int sha224_final(EVP_MD_CTX *ctx, unsigned char *md) { + return SHA224_Final(md, ctx->md_data); +} + +static const EVP_MD sha224_md = { + 675, 28, 0 , + sha224_init, sha224_update, sha224_final, + 64 , sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha224(void) { return &sha224_md; } + + +static int sha256_init(EVP_MD_CTX *ctx) { return SHA256_Init(ctx->md_data); } + +static int sha256_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + return SHA256_Update(ctx->md_data, data, count); +} + +static int sha256_final(EVP_MD_CTX *ctx, unsigned char *md) { + return SHA256_Final(md, ctx->md_data); +} + +static const EVP_MD sha256_md = { + 672, 32, 0 , + sha256_init, sha256_update, sha256_final, + 64 , sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha256(void) { return &sha256_md; } + + +static int sha384_init(EVP_MD_CTX *ctx) { return SHA384_Init(ctx->md_data); } + +static int sha384_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + return SHA384_Update(ctx->md_data, data, count); +} + +static int sha384_final(EVP_MD_CTX *ctx, unsigned char *md) { + return SHA384_Final(md, ctx->md_data); +} + +static const EVP_MD sha384_md = { + 673, 48, 0 , + sha384_init, sha384_update, sha384_final, + 128 , sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha384(void) { return &sha384_md; } + + +static int sha512_init(EVP_MD_CTX *ctx) { return SHA512_Init(ctx->md_data); } + +static int sha512_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + return SHA512_Update(ctx->md_data, data, count); +} + +static int sha512_final(EVP_MD_CTX *ctx, unsigned char *md) { + return SHA512_Final(md, ctx->md_data); +} + +static const EVP_MD sha512_md = { + 674, 64, 0 , + sha512_init, sha512_update, sha512_final, + 128 , sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha512(void) { return &sha512_md; } + + +typedef struct { + MD5_CTX md5; + SHA_CTX sha1; +} MD5_SHA1_CTX; + +static int md5_sha1_init(EVP_MD_CTX *md_ctx) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + return MD5_Init(&ctx->md5) && SHA1_Init(&ctx->sha1); +} + +static int md5_sha1_update(EVP_MD_CTX *md_ctx, const void *data, size_t count) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + return MD5_Update(&ctx->md5, data, count) && SHA1_Update(&ctx->sha1, data, count); +} + +static int md5_sha1_final(EVP_MD_CTX *md_ctx, unsigned char *out) { + MD5_SHA1_CTX *ctx = md_ctx->md_data; + if (!MD5_Final(out, &ctx->md5) || + !SHA1_Final(out + 16, &ctx->sha1)) { + return 0; + } + return 1; +} + +static const EVP_MD md5_sha1_md = { + 114, + 16 + 20, + 0 , + md5_sha1_init, + md5_sha1_update, + md5_sha1_final, + 64 , + sizeof(MD5_SHA1_CTX), +}; + +const EVP_MD *EVP_md5_sha1(void) { return &md5_sha1_md; } + + +struct nid_to_digest { + int nid; + const EVP_MD* (*md_func)(void); +}; + +static const struct nid_to_digest nid_to_digest_mapping[] = { + { 4, EVP_md5 }, + { 64, EVP_sha1 }, + { 675, EVP_sha224 }, + { 672, EVP_sha256 }, + { 673, EVP_sha384 }, + { 674, EVP_sha512 }, + { 114, EVP_md5_sha1 }, + { 66, EVP_sha1 }, + { 113, EVP_sha1 }, + { 416, EVP_sha1 }, + { 8, EVP_md5 }, + { 65, EVP_sha1 }, + { 671, EVP_sha224 }, + { 668, EVP_sha256 }, + { 669, EVP_sha384 }, + { 670, EVP_sha512 }, +}; + +const EVP_MD* EVP_get_digestbynid(int nid) { + unsigned i; + + for (i = 0; i < sizeof(nid_to_digest_mapping) / sizeof(struct nid_to_digest); + i++) { + if (nid_to_digest_mapping[i].nid == nid) { + return nid_to_digest_mapping[i].md_func(); + } + } + + return + ((void *)0) + ; +} + +const EVP_MD* EVP_get_digestbyobj(const ASN1_OBJECT *obj) { + return EVP_get_digestbynid(OBJ_obj2nid(obj)); +} diff --git a/test/clightgen/issue216.c b/test/clightgen/issue216.c new file mode 100644 index 00000000..796b69b4 --- /dev/null +++ b/test/clightgen/issue216.c @@ -0,0 +1,5 @@ +#include <stddef.h> + +struct list {unsigned head; struct list *tail;}; +struct list three[] = { {1, three+1}, {2, three+2}, {3, NULL} }; +int f(int x) { return x;} diff --git a/test/regression/Makefile b/test/regression/Makefile index 48e2b7b3..191a2285 100644 --- a/test/regression/Makefile +++ b/test/regression/Makefile @@ -1,7 +1,9 @@ include ../../Makefile.config CCOMP=../../ccomp -CCOMPFLAGS=$(CCOMPOPTS) -stdlib ../../runtime -dparse -dc -dclight -dasm -fall +CCOMPFLAGS=$(CCOMPOPTS) -stdlib ../../runtime \ + -dparse -dc -dclight -dasm -fall \ + -DARCH_$(ARCH) -DMODEL_$(MODEL) INTERPFLAGS=-stdlib ../../runtime -interp -quiet -fall LIBS=$(LIBMATH) @@ -20,18 +22,9 @@ TESTS=int32 int64 floats floats-basics \ TESTS_COMP=attribs1 bitfields1 bitfields2 bitfields3 bitfields4 \ bitfields5 bitfields6 bitfields7 bitfields8 \ - builtins-$(ARCH) packedstruct2 alignas \ + builtins-$(ARCH) packedstruct1 packedstruct2 alignas \ varargs1 varargs2 sections alias -# packedstruct1 makes unaligned memory accesses - -ifeq ($(ARCH),powerpc) -TESTS_COMP+=packedstruct1 -endif -ifeq ($(ARCH),x86) -TESTS_COMP+=packedstruct1 -endif - # Can run, both in compiled mode and in interpreter mode, # but produce processor-dependent results, so no reference output in Results @@ -70,12 +63,12 @@ clean: test: @echo "----------- Compiled tests -------------" - @for i in $(TESTS) $(TESTS_COMP); do \ + @set -e; for i in $(TESTS) $(TESTS_COMP); do \ SIMU='$(SIMU)' ./Runtest $$i ./$$i.compcert; \ done @echo "----------- Interpreted tests -------------" - @for i in $(TESTS); do \ - SIMU='' ./Runtest $$i $(CCOMP) $(INTERPFLAGS) $$i.c; \ + @set -e; for i in $(TESTS); do \ + SIMU='' INTERP=1 ./Runtest $$i $(CCOMP) $(INTERPFLAGS) $$i.c; \ done @for i in $(TESTS_DIFF); do \ if $(CCOMP) -fall -interp -quiet $$i.c > _cinterp.log; then \ diff --git a/test/regression/Results/alignas b/test/regression/Results/alignas index 581a4377..620b5e76 100644 --- a/test/regression/Results/alignas +++ b/test/regression/Results/alignas @@ -1,9 +1,10 @@ -a: size = 4, alignment = 16, address mod 16 = 0 -b: size = 12, alignment = 16, address mod 16 = 0 -bb: size = 12, alignment = 16, address mod 16 = 0 -c: size = 32, alignment = 16, address mod 16 = 0 -d: size = 32, alignment = 64, address mod 64 = 0 -e: size = 16, alignment = 16, address mod 16 = 0 -f: size = 16, alignment = 32, address mod 32 = 0 -g: size = 96, alignment = 16, address mod 16 = 0 -h: size = 192, alignment = 64, address mod 64 = 0 +a: size = 4, address mod 16 = 0 +b: size = 12, address mod 16 = 0 +bb: size = 12, address mod 16 = 0 +bbb: size = 12, address mod 16 = 0 +c: size = 32, address mod 16 = 0 +d: size = 32, address mod 64 = 0 +e: size = 16, address mod 16 = 0 +f: size = 16, address mod 32 = 0 +g: size = 96, address mod 16 = 0 +h: size = 192, address mod 64 = 0 diff --git a/test/regression/Results/bitfields9 b/test/regression/Results/bitfields9 index a1d0e9fd..e35c2414 100644 --- a/test/regression/Results/bitfields9 +++ b/test/regression/Results/bitfields9 @@ -1,10 +1,18 @@ glob_s = { a = -12, b = 1 } glob_t = { c = 123, d = 1, e = -45 } +glob_u_u = { u = -3 } +glob_u_v = { v = 6 } loc_s = { a = 11, b = 2 } loc_t = { c = 11, d = 1, e = 2 } +loc_u_u = { u = -5 } +loc_u_v = { v = 3 } compound_s = { a = 2, b = 3 } compound_t = { c = 2, d = 1, e = -11 } +compound_u = { u = 2 } loc_s = { a = 7, b = 2 } loc_t = { c = 7, d = 1, e = 50 } +loc_u_u = { u = 7 } +loc_u_v = { v = 2 } compound_s = { a = -14, b = 3 } compound_t = { c = 50, d = 1, e = -7 } +compound_u = { u = 2 } diff --git a/test/regression/Results/packedstruct1-32 b/test/regression/Results/packedstruct1-32 index e4bca769..e7d1c296 100644 --- a/test/regression/Results/packedstruct1-32 +++ b/test/regression/Results/packedstruct1-32 @@ -1,25 +1,37 @@ sizeof(struct s1) = 14 +precomputed sizeof(struct s1) = 14 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s1 = {x = 123, y = -456, z = 3.14159} sizeof(struct s2) = 16 +precomputed sizeof(struct s2) = 16 &s2 mod 16 = 0 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s2 = {x = 57, y = -456, z = 3.14159} sizeof(struct s3) = 31 +precomputed sizeof(struct s3) = 31 offsetof(s) = 29 +precomputed offsetof(s) = 29 s3 = {x = 123, y = 45678, z = 2147483649, v = -456, w = -1234567, p is ok, t = {111,222,333}, s = {'o','k'}} sizeof(struct s4) = 16 +precomputed sizeof(struct s4) = 16 offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8 +precomputed offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8 s4 = {x = 123, y = -456, z = 3.14159} sizeof(struct s5) = 14 +precomputed sizeof(struct s5) = 14 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s5 = {x = 123, y = -456, z = 3.14159} sizeof(struct s6) = 14 +precomputed sizeof(struct s6) = 14 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s62 = {x = 123, y = -456, z = 3.14159} diff --git a/test/regression/Results/packedstruct1-64 b/test/regression/Results/packedstruct1-64 index c2a8bcd2..d255595f 100644 --- a/test/regression/Results/packedstruct1-64 +++ b/test/regression/Results/packedstruct1-64 @@ -1,25 +1,37 @@ sizeof(struct s1) = 14 +precomputed sizeof(struct s1) = 14 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s1 = {x = 123, y = -456, z = 3.14159} sizeof(struct s2) = 16 +precomputed sizeof(struct s2) = 16 &s2 mod 16 = 0 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s2 = {x = 57, y = -456, z = 3.14159} sizeof(struct s3) = 35 +precomputed sizeof(struct s3) = 35 offsetof(s) = 33 +precomputed offsetof(s) = 33 s3 = {x = 123, y = 45678, z = 2147483649, v = -456, w = -1234567, p is ok, t = {111,222,333}, s = {'o','k'}} sizeof(struct s4) = 16 +precomputed sizeof(struct s4) = 16 offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8 +precomputed offsetof(x) = 0, offsetof(y) = 4, offsetof(z) = 8 s4 = {x = 123, y = -456, z = 3.14159} sizeof(struct s5) = 14 +precomputed sizeof(struct s5) = 14 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s5 = {x = 123, y = -456, z = 3.14159} sizeof(struct s6) = 14 +precomputed sizeof(struct s6) = 14 offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 +precomputed offsetof(x) = 0, offsetof(y) = 2, offsetof(z) = 6 s62 = {x = 123, y = -456, z = 3.14159} diff --git a/test/regression/Runtest b/test/regression/Runtest index ad2a58f1..f693219a 100755 --- a/test/regression/Runtest +++ b/test/regression/Runtest @@ -9,6 +9,9 @@ out="test$$.log" rm -f $out trap "rm -f $out" 0 INT QUIT +# Is the test expected to fail? +expect_fail=false + # The architecture and the bitsize arch=`sed -n -e 's/^ARCH=//p' ../../Makefile.config` bits=`sed -n -e 's/^BITSIZE=//p' ../../Makefile.config` @@ -26,10 +29,23 @@ else ref="" fi +# Special conditions + +if test -f "$name.cond"; then + RUN=0 SKIP=1 EXPECT_FAIL=2 sh "$name.cond" + case "$?" in + 1) echo "$name: skipped"; exit 0;; + 2) expect_fail=true;; + esac +fi + # Administer the test if $SIMU $* > $out then - if test -n "$ref"; then + if $expect_fail; then + echo "$name: ERROR (should have failed but did not)" + exit 2 + elif test -n "$ref"; then if cmp -s "$out" "$ref"; then echo "$name: passed" exit 0 @@ -43,7 +59,13 @@ then exit 0 fi else - echo "$name: EXECUTION FAILED (status $?)" - exit 2 + retcode=$? + if $expect_fail; then + echo "$name: passed (failed as expected)" + exit 0 + else + echo "$name: EXECUTION FAILED (status $retcode)" + exit 2 + fi fi diff --git a/test/regression/alignas.c b/test/regression/alignas.c index b3754039..777c13a5 100644 --- a/test/regression/alignas.c +++ b/test/regression/alignas.c @@ -2,16 +2,12 @@ #include <stdio.h> -#if __STDC_VERSION__ < 201100 && defined(__GNUC__) -#define _Alignas(x) __attribute__((aligned(x))) -#define _Alignof(x) __alignof__(x) -#endif - #ifdef _Alignas #undef _Alignas #endif -#ifdef _Alignof -#undef _Alignof + +#if __STDC_VERSION__ < 201100 && defined(__GNUC__) +#define _Alignas(x) __attribute((aligned(x))) #endif /* Base type */ @@ -24,10 +20,9 @@ _Alignas(16) int b[3]; typedef int int3[3]; _Alignas(16) int3 bb; -#if 0 -typedef _Alignas(16) int int16; +/* _Alignas is not allowed in typedefs but the "aligned" attribute is */ +typedef __attribute((aligned(16))) int int16; int16 bbb[3]; -#endif char filler2; @@ -72,28 +67,26 @@ char filler8; int main() { - printf("a: size = %u, alignment = %u, address mod 16 = %u\n", - (unsigned) sizeof(a), (unsigned) _Alignof(a), ((unsigned) &a) & 0xF); - printf("b: size = %u, alignment = %u, address mod 16 = %u\n", - (unsigned) sizeof(b), (unsigned) _Alignof(b), ((unsigned) &b) & 0xF); - printf("bb: size = %u, alignment = %u, address mod 16 = %u\n", - (unsigned) sizeof(bb), (unsigned) _Alignof(bb), ((unsigned) &bb) & 0xF); -#if 0 - printf("bbb: size = %u, alignment = %u, address mod 16 = %u\n", - (unsigned) sizeof(bbb), (unsigned) _Alignof(bbb), ((unsigned) &bbb) & 0xF); -#endif - printf("c: size = %u, alignment = %u, address mod 16 = %u\n", - (unsigned) sizeof(c), (unsigned) _Alignof(c), ((unsigned) &c) & 0xF); - printf("d: size = %u, alignment = %u, address mod 64 = %u\n", - (unsigned) sizeof(d), (unsigned) _Alignof(d), ((unsigned) &d) & 0x3F); - printf("e: size = %u, alignment = %u, address mod 16 = %u\n", - (unsigned) sizeof(e), (unsigned) _Alignof(e), ((unsigned) &e) & 0xF); - printf("f: size = %u, alignment = %u, address mod 32 = %u\n", - (unsigned) sizeof(f), (unsigned) _Alignof(f), ((unsigned) &f) & 0x1F); - printf("g: size = %u, alignment = %u, address mod 16 = %u\n", - (unsigned) sizeof(g), (unsigned) _Alignof(g), ((unsigned) &g) & 0xF); - printf("h: size = %u, alignment = %u, address mod 64 = %u\n", - (unsigned) sizeof(h), (unsigned) _Alignof(h), ((unsigned) &h) & 0x3F); + printf("a: size = %u, address mod 16 = %u\n", + (unsigned) sizeof(a), ((unsigned) &a) & 0xF); + printf("b: size = %u, address mod 16 = %u\n", + (unsigned) sizeof(b), ((unsigned) &b) & 0xF); + printf("bb: size = %u, address mod 16 = %u\n", + (unsigned) sizeof(bb), ((unsigned) &bb) & 0xF); + printf("bbb: size = %u, address mod 16 = %u\n", + (unsigned) sizeof(bbb), ((unsigned) &bbb) & 0xF); + printf("c: size = %u, address mod 16 = %u\n", + (unsigned) sizeof(c), ((unsigned) &c) & 0xF); + printf("d: size = %u, address mod 64 = %u\n", + (unsigned) sizeof(d), ((unsigned) &d) & 0x3F); + printf("e: size = %u, address mod 16 = %u\n", + (unsigned) sizeof(e), ((unsigned) &e) & 0xF); + printf("f: size = %u, address mod 32 = %u\n", + (unsigned) sizeof(f), ((unsigned) &f) & 0x1F); + printf("g: size = %u, address mod 16 = %u\n", + (unsigned) sizeof(g), ((unsigned) &g) & 0xF); + printf("h: size = %u, address mod 64 = %u\n", + (unsigned) sizeof(h), ((unsigned) &h) & 0x3F); return 0; } diff --git a/test/regression/bitfields9.c b/test/regression/bitfields9.c index be87057b..eef20168 100644 --- a/test/regression/bitfields9.c +++ b/test/regression/bitfields9.c @@ -11,6 +11,12 @@ struct t { unsigned int c: 16; _Bool d: 1; short e: 8; + int : 10; +}; + +union u { + int u: 4; + unsigned int v: 3; }; void print_s(char * msg, struct s p) @@ -23,25 +29,45 @@ void print_t(char * msg, struct t p) printf("%s = { c = %d, d = %d, e = %d }\n", msg, p.c, p.d, p.e); } +void print_u_u(char * msg, union u p) +{ + printf("%s = { u = %d }\n", msg, p.u); +} + +void print_u_v(char * msg, union u p) +{ + printf("%s = { v = %u }\n", msg, p.v); +} + + /* Global initialization */ struct s glob_s = { -12, 1 }; struct t glob_t = { 123, 2, -45 }; +union u glob_u_u = { -3 }; +union u glob_u_v = { .v = 6 }; /* Local initialization */ void f(int x, int y, int z) { struct s loc_s = { x, y }; struct t loc_t = { x, z, y }; + union u loc_u_u = { .u = x }; + union u loc_u_v = { .v = z }; print_s("loc_s", loc_s); print_t("loc_t", loc_t); + print_u_u("loc_u_u", loc_u_u); + print_u_v("loc_u_v", loc_u_v); print_s("compound_s", (struct s) { y, x }); print_t("compound_t", (struct t) { y, ~z, -x }); + print_u_u("compound_u", (union u) { y }); } int main() { print_s("glob_s", glob_s); print_t("glob_t", glob_t); + print_u_u("glob_u_u", glob_u_u); + print_u_v("glob_u_v", glob_u_v); f(11, 2, 3); f(7, 50, 2); return 0; diff --git a/test/regression/extasm.c b/test/regression/extasm.c index a41c4202..babc57f1 100644 --- a/test/regression/extasm.c +++ b/test/regression/extasm.c @@ -18,7 +18,10 @@ int clobbers(int x, int z) return y + z; } -#if defined(__x86_64__) || __riscv_xlen == 64 +#if (defined(ARCH_x86) && defined(MODEL_64)) \ + || (defined(ARCH_riscV) && defined(MODEL_64)) \ + || (defined(ARCH_powerpc) && defined(MODEL_ppc64)) \ + || (defined(ARCH_powerpc) && defined(MODEL_e5500)) #define SIXTYFOUR #else #undef SIXTYFOUR diff --git a/test/regression/funptr2.cond b/test/regression/funptr2.cond new file mode 100644 index 00000000..ab460efb --- /dev/null +++ b/test/regression/funptr2.cond @@ -0,0 +1,6 @@ +#!/bin/sh + +if test -n "$INTERP" +then exit $EXPECT_FAIL +else exit $RUN +fi diff --git a/test/regression/interop1.cond b/test/regression/interop1.cond new file mode 100644 index 00000000..77904189 --- /dev/null +++ b/test/regression/interop1.cond @@ -0,0 +1,10 @@ +#!/bin/sh +arch=`sed -n -e 's/^ARCH=//p' ../../Makefile.config` +model=`sed -n -e 's/^MODEL=//p' ../../Makefile.config` +system=`sed -n -e 's/^SYSTEM=//p' ../../Makefile.config` + +case "$arch,$model,$system" in + *,*,cygwin) exit $SKIP;; + x86,32sse2,*|arm,*,*|powerpc,*,*) exit $RUN;; + *) exit $SKIP;; +esac diff --git a/test/regression/packedstruct1.c b/test/regression/packedstruct1.c index 8b138dd4..5d3e7124 100644 --- a/test/regression/packedstruct1.c +++ b/test/regression/packedstruct1.c @@ -2,8 +2,18 @@ #include <stdio.h> +/* offsetof is the offset computed by the verified front-end (cfrontend/) */ #define offsetof(s,f) (int)&(((struct s *)0)->f) +/* boffsetof is the offset computed by the elaborator (cparser/) */ +#define boffsetof(s,f) (int)__builtin_offsetof(struct s, f) + +/* szof is the size computed by the verified front-end (cfrontend/) */ +#define szof(s) (int) sizeof(struct s) + +/* bszof is the size computed by the elaborator (cparser/) */ +#define bszof(s) (int) sizeof(char [sizeof(struct s)]) + /* Simple packing */ struct __packed__(1) s1 { unsigned short x; int y; double z; }; @@ -11,9 +21,12 @@ struct __packed__(1) s1 { unsigned short x; int y; double z; }; void test1(void) { struct s1 s1; - printf("sizeof(struct s1) = %d\n", sizeof(struct s1)); + printf("sizeof(struct s1) = %d\n", szof(s1)); + printf("precomputed sizeof(struct s1) = %d\n", bszof(s1)); printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", offsetof(s1,x), offsetof(s1,y), offsetof(s1,z)); + printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", + boffsetof(s1,x), boffsetof(s1,y), boffsetof(s1,z)); s1.x = 123; s1.y = -456; s1.z = 3.14159; printf("s1 = {x = %d, y = %d, z = %.5f}\n\n", s1.x, s1.y, s1.z); } @@ -28,10 +41,13 @@ struct s2 s2; void test2(void) { - printf("sizeof(struct s2) = %d\n", sizeof(struct s2)); + printf("sizeof(struct s2) = %d\n", szof(s2)); + printf("precomputed sizeof(struct s2) = %d\n", bszof(s2)); printf("&s2 mod 16 = %d\n", ((int) &s2) & 0xF); printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", offsetof(s2,x), offsetof(s2,y), offsetof(s2,z)); + printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", + boffsetof(s2,x), boffsetof(s2,y), boffsetof(s2,z)); s2.x = 12345; s2.y = -456; s2.z = 3.14159; printf("s2 = {x = %d, y = %d, z = %.5f}\n\n", s2.x, s2.y, s2.z); } @@ -55,8 +71,10 @@ void test3(void) { char xx; - printf("sizeof(struct s3) = %d\n", sizeof(struct s3)); + printf("sizeof(struct s3) = %d\n", szof(s3)); + printf("precomputed sizeof(struct s3) = %d\n", bszof(s3)); printf("offsetof(s) = %d\n", offsetof(s3,s)); + printf("precomputed offsetof(s) = %d\n", boffsetof(s3,s)); s3.x = 123; s3.y = 45678; s3.z = 0x80000001U; @@ -82,9 +100,13 @@ struct s4 { unsigned short x; int y; double z; }; void test4(void) { struct s4 s4; - printf("sizeof(struct s4) = %d\n", sizeof(struct s4)); + + printf("sizeof(struct s4) = %d\n", szof(s4)); + printf("precomputed sizeof(struct s4) = %d\n", bszof(s4)); printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", offsetof(s4,x), offsetof(s4,y), offsetof(s4,z)); + printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", + boffsetof(s4,x), boffsetof(s4,y), boffsetof(s4,z)); s4.x = 123; s4.y = -456; s4.z = 3.14159; printf("s4 = {x = %d, y = %d, z = %.5f}\n\n", s4.x, s4.y, s4.z); } @@ -96,9 +118,13 @@ struct __attribute((packed)) s5 { unsigned short x; int y; double z; }; void test5(void) { struct s5 s5; - printf("sizeof(struct s5) = %d\n", sizeof(struct s5)); + + printf("sizeof(struct s5) = %d\n", szof(s5)); + printf("precomputed sizeof(struct s5) = %d\n", bszof(s5)); printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", offsetof(s5,x), offsetof(s5,y), offsetof(s5,z)); + printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", + boffsetof(s5,x), boffsetof(s5,y), boffsetof(s5,z)); s5.x = 123; s5.y = -456; s5.z = 3.14159; printf("s5 = {x = %d, y = %d, z = %.5f}\n\n", s5.x, s5.y, s5.z); } @@ -110,9 +136,13 @@ struct s6 { unsigned short x; int y; double z; } __attribute((packed)) const s6 void test6(void) { struct s6 s62; - printf("sizeof(struct s6) = %d\n", sizeof(struct s6)); + + printf("sizeof(struct s6) = %d\n", szof(s6)); + printf("precomputed sizeof(struct s6) = %d\n", bszof(s6)); printf("offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", offsetof(s6,x), offsetof(s6,y), offsetof(s6,z)); + printf("precomputed offsetof(x) = %d, offsetof(y) = %d, offsetof(z) = %d\n", + boffsetof(s6,x), boffsetof(s6,y), boffsetof(s6,z)); s62.x = 123; s62.y = -456; s62.z = 3.14159; printf("s62 = {x = %d, y = %d, z = %.5f}\n\n", s62.x, s62.y, s62.z); } @@ -284,6 +284,7 @@ Inductive instruction: Type := | Pmovsb | Pmovsw | Pmovw_rm (rd: ireg) (ad: addrmode) + | Pnop | Prep_movsl | Psbbl_rr (rd: ireg) (r2: ireg) | Psqrtsd (rd: freg) (r1: freg) @@ -1001,6 +1002,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out | Pmovsb | Pmovsw | Pmovw_rm _ _ + | Pnop | Prep_movsl | Psbbl_rr _ _ | Psqrtsd _ _ @@ -1047,6 +1049,15 @@ Definition preg_of (r: mreg) : preg := | FP0 => ST0 end. +(** Undefine all registers except SP and callee-save registers *) + +Definition undef_caller_save_regs (rs: regset) : regset := + fun r => + if preg_eq r SP + || In_dec preg_eq r (List.map preg_of (List.filter is_callee_save all_mregs)) + then rs r + else Vundef. + (** Extract the values of the arguments of an external call. We exploit the calling conventions from module [Conventions], except that we use machine registers instead of locations. *) @@ -1106,7 +1117,7 @@ Inductive step: state -> trace -> state -> Prop := Genv.find_funct_ptr ge b = Some (External ef) -> extcall_arguments rs m (ef_sig ef) args -> external_call ef ge args m t res m' -> - rs' = (set_pair (loc_external_result (ef_sig ef)) res rs) #PC <- (rs RA) -> + rs' = (set_pair (loc_external_result (ef_sig ef)) res (undef_caller_save_regs rs)) #PC <- (rs RA) -> step (State rs m) t (State rs' m'). End RELSEM. diff --git a/x86/Asmexpand.ml b/x86/Asmexpand.ml index 9927d2fb..16426ce3 100644 --- a/x86/Asmexpand.ml +++ b/x86/Asmexpand.ml @@ -331,9 +331,17 @@ let expand_builtin_inline name args res = if a1 <> res then emit (Pmov_rr (res,a1)); emit (Pbswap16 res) - | ("__builtin_clz"|"__builtin_clzl"), [BA(IR a1)], BR(IR res) -> + | "__builtin_clz", [BA(IR a1)], BR(IR res) -> emit (Pbsrl (res,a1)); emit (Pxorl_ri(res,coqint_of_camlint 31l)) + | "__builtin_clzl", [BA(IR a1)], BR(IR res) -> + if not(Archi.ptr64) then begin + emit (Pbsrl (res,a1)); + emit (Pxorl_ri(res,coqint_of_camlint 31l)) + end else begin + emit (Pbsrq (res,a1)); + emit (Pxorl_ri(res,coqint_of_camlint 63l)) + end | "__builtin_clzll", [BA(IR a1)], BR(IR res) -> emit (Pbsrq (res,a1)); emit (Pxorl_ri(res,coqint_of_camlint 63l)) @@ -349,8 +357,13 @@ let expand_builtin_inline name args res = emit (Pbsrl(res, al)); emit (Pxorl_ri(res, coqint_of_camlint 63l)); emit (Plabel lbl2) - | ("__builtin_ctz" | "__builtin_ctzl"), [BA(IR a1)], BR(IR res) -> + | "__builtin_ctz", [BA(IR a1)], BR(IR res) -> emit (Pbsfl (res,a1)) + | "__builtin_ctzl", [BA(IR a1)], BR(IR res) -> + if not(Archi.ptr64) then + emit (Pbsfl (res,a1)) + else + emit (Pbsfq (res,a1)) | "__builtin_ctzll", [BA(IR a1)], BR(IR res) -> emit (Pbsfq (res,a1)) | "__builtin_ctzll", [BA_splitlong(BA (IR ah), BA (IR al))], BR(IR res) -> @@ -462,7 +475,7 @@ let expand_builtin_inline name args res = () (* no operation *) | "__builtin_nop", [], _ -> - emit (Pmov_rr (RAX,RAX)) + emit Pnop (* Catch-all *) | _ -> raise (Error ("unrecognized builtin " ^ name)) @@ -619,10 +632,7 @@ let preg_to_dwarf = function let expand_function id fn = try set_current_function fn; - if !Clflags.option_g then - expand_debug id (int_reg_to_dwarf RSP) preg_to_dwarf expand_instruction fn.fn_code - else - List.iter expand_instruction fn.fn_code; + expand id (int_reg_to_dwarf RSP) preg_to_dwarf expand_instruction fn.fn_code; Errors.OK (get_current_function ()) with Error s -> Errors.Error (Errors.msg (coqstring_of_camlstring s)) diff --git a/x86/Asmgenproof.v b/x86/Asmgenproof.v index 38816fd2..3aa87a4c 100644 --- a/x86/Asmgenproof.v +++ b/x86/Asmgenproof.v @@ -861,8 +861,8 @@ Transparent destroyed_at_function_entry. apply plus_one. eapply exec_step_external; eauto. eapply external_call_symbols_preserved; eauto. apply senv_preserved. econstructor; eauto. - unfold loc_external_result. - apply agree_set_other; auto. apply agree_set_pair; auto. + unfold loc_external_result. apply agree_set_other; auto. apply agree_set_pair; auto. + apply agree_undef_caller_save_regs; auto. - (* return *) inv STACKS. simpl in *. diff --git a/x86/TargetPrinter.ml b/x86/TargetPrinter.ml index 1bb8c226..3ac2f36e 100644 --- a/x86/TargetPrinter.ml +++ b/x86/TargetPrinter.ml @@ -791,6 +791,8 @@ module Target(System: SYSTEM):TARGET = fprintf oc " movsw\n"; | Pmovw_rm (rd, a) -> fprintf oc " movw %a, %a\n" addressing a ireg16 rd + | Pnop -> + fprintf oc " nop\n" | Prep_movsl -> fprintf oc " rep movsl\n" | Psbbl_rr (res,a1) -> @@ -814,7 +816,7 @@ module Target(System: SYSTEM):TARGET = | 1 -> let annot = annot_text preg_annot "esp" (camlstring_of_coqstring txt) args in fprintf oc "%s annotation: %S\n" comment annot | 2 -> let lbl = new_label () in - fprintf oc "%a: \n" label lbl; + fprintf oc "%a:\n" label lbl; let sp = if Archi.ptr64 then "rsp" else "esp" in add_ais_annot lbl preg_ais_annot sp (camlstring_of_coqstring txt) args | _ -> assert false |