Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
203f283
Add C11 generic to Cabs and CIL
coslu Sep 7, 2020
d9a7510
Fix C11 generic warnings
coslu Nov 10, 2020
0067d37
Remove C11 generic from CIL
sim642 Sep 10, 2021
a7cf7e4
Rewrite C11 generic Cabs2cil to resolve generic switch
sim642 Sep 10, 2021
ddd59c1
Implement C11 generic Cabsvisit
sim642 Sep 10, 2021
76e9c83
Remove now unnecessary stripParenLocal from C11 generic Cabs2cil
sim642 Sep 10, 2021
005a453
Move Cabs2cil.stripParenLocal back to its old location
sim642 Sep 10, 2021
e58de49
Add comments about C11 generic
sim642 Sep 10, 2021
50c02c9
Add failing generic test
michael-schwarz Sep 11, 2021
041c7cf
fix error numbers
michael-schwarz Sep 11, 2021
962dc8a
Add type qualifier attribute compatibility check and strip to combine…
sim642 Sep 13, 2021
5f1b78e
Add type qualifier attribute strip to C11 generic combineTypes
sim642 Sep 13, 2021
c2f6339
Add type qualifier attribute strip to function argument combineTypes
sim642 Sep 13, 2021
7cdf8ad
Fix make test printing annoying raw output
sim642 Sep 13, 2021
0b162ca
Fix raw test output in CI
sim642 Sep 13, 2021
9a17ba2
Fix raw test output failing successful tests in CI
sim642 Sep 13, 2021
9473315
Fix make test failure exit code
sim642 Sep 13, 2021
19238f0
Remove useless raw log step in CI
sim642 Sep 13, 2021
06a878c
Remove invalid test with conflicting type qualifiers
sim642 Sep 13, 2021
b4bd664
Document some type functions in Cabs2cil
sim642 Sep 13, 2021
2add3ca
Update comments about C11 generic in Cabs2cil.doExp
sim642 Sep 13, 2021
a6ef80d
Remove outdated comments in small1/c11-generic test
sim642 Sep 13, 2021
897aba2
Move qualifier attributes functions from Cabs2cil to Cil
sim642 Sep 13, 2021
5e9a2f6
Port type qualifier fixes from Cabs2cil.combineTypes to Mergecil.comb…
sim642 Sep 13, 2021
e67879d
Expand Mergecil.combineTypes different type qualifiers message
sim642 Sep 13, 2021
46c6a0a
Fix combineTypes dropping type qualifiers
sim642 Sep 13, 2021
dd8f2f2
Add C11 generic string literal test
sim642 Sep 13, 2021
919c0f8
Add C11 generic test where pointer type fails
sim642 Sep 14, 2021
66b5e81
Fix parsing of pointer types in C11 generic associations
sim642 Sep 14, 2021
f703a1c
Remove const_string_literals from Machdep
sim642 Sep 14, 2021
afafead
Remove ref from Cil.stringLiteralType
sim642 Sep 14, 2021
e84b98b
Expose Cil.stringLiteralType in signature
sim642 Sep 14, 2021
8fc4cc4
Disable broken macOS CI
sim642 Sep 14, 2021
0177bfd
Add C11 generic test where expression without parenthesis breaks
sim642 Sep 15, 2021
8d5204a
Fix C11 generic Cabsvisit dropping simple GENERIC
sim642 Sep 15, 2021
ba391a8
Add C11 generic GCC test 1
sim642 Sep 15, 2021
b13180b
Add C11 generic GCC test 2
sim642 Sep 15, 2021
2be7157
Add C11 generic GCC test 3
sim642 Sep 15, 2021
79a4579
Add main functions to C11 generic GCC tests to prevent failure from GCC
sim642 Sep 15, 2021
1983c12
Disable gcc-c11-generic-2-6 test
sim642 Sep 15, 2021
39d8442
Add C11 generic Clang tests
sim642 Sep 15, 2021
ce4f4f7
Fix pointer qualifier handling in ternary operator typing
sim642 Sep 15, 2021
46e4f05
Fix Cil.isNullPtrConstant to only allow void* casts
sim642 Sep 15, 2021
7a7e1e4
Refactor integer 0 handling in ternary operator typing
sim642 Sep 15, 2021
3dfa002
Add missing void case to ternary operator typing
sim642 Sep 15, 2021
6674fd1
Add separate pconst attribute for tracking whether to print const
sim642 Nov 15, 2021
544dbfc
Revert "Disable broken macOS CI"
sim642 Nov 29, 2021
7606d26
Fix Cprint print_generic_list only printing first association
sim642 Nov 29, 2021
e47e4ad
Simplify Cabs2cil.stripConstLocalType
sim642 Nov 29, 2021
f70e708
Merge branch 'develop' into c11-generic
sim642 Dec 10, 2021
a0a1a94
Add C11 _Generic to CHANGES
sim642 Dec 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ clean: $(CILLYDIR)/Makefile

.PHONY: test
test:
cd test; CC=@CC@ ./testcil -r --regrtest || { cat cil.log; exit 1; }
cd test; CC=@CC@ ./testcil -r --regrtest || { echo "Check test/cil.log for raw output"; exit 1; }

########################################################################

Expand Down
2 changes: 2 additions & 0 deletions src/frontc/cabs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type typeSpecifier = (* Merge all specifiers into one type *)
| Tenum of string * enum_item list option * attribute list
| TtypeofE of expression (* GCC __typeof__ *)
| TtypeofT of specifier * decl_type (* GCC __typeof__ *)
| Tdefault (** "default" in generic associations *)

and storage =
NO_STORAGE | AUTO | STATIC | EXTERN | REGISTER
Expand Down Expand Up @@ -281,6 +282,7 @@ and expression =
| MEMBEROFPTR of expression * string
| GNU_BODY of block
| EXPR_PATTERN of string (* pattern variable, and name *)
| GENERIC of expression * ((specifier * expression) list)

and constant =
| CONST_INT of string (* the textual representation *)
Expand Down
66 changes: 65 additions & 1 deletion src/frontc/cabs2cil.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1589,7 +1589,38 @@ type combineWhat =
* that are known to be equal *)
let isomorphicStructs : (string * string, bool) H.t = H.create 15

(** [typeAttrs], which doesn't add inner attributes. *)
let typeAttrsOuter = function
| TVoid a -> a
| TInt (_, a) -> a
| TFloat (_, a) -> a
| TNamed (_, a) -> a
| TPtr (_, a) -> a
| TArray (_, _, a) -> a
| TComp (_, a) -> a
| TEnum (_, a) -> a
| TFun (_, _, _, a) -> a
| TBuiltin_va_list a -> a

let partitionQualifierAttributes al =
List.partition (function
| Attr (("const" | "volatile" | "restrict"), []) -> true
| _ -> false
) al

let removeOuterQualifierAttributes t =
let a = typeAttrsOuter t in
let (_, a') = partitionQualifierAttributes a in
setTypeAttrs t a'

let rec combineTypes (what: combineWhat) (oldt: typ) (t: typ) : typ =
let (oldq, olda) = partitionQualifierAttributes (typeAttrsOuter oldt) in
let (q, a) = partitionQualifierAttributes (typeAttrsOuter t) in
if oldq <> q then
raise (Failure "different type qualifiers")
else if q <> [] then
combineTypes what (setTypeAttrs oldt olda) (setTypeAttrs t a)
else
match oldt, t with
| TVoid olda, TVoid a -> TVoid (cabsAddAttributes olda a)
| TInt (oldik, olda), TInt (ik, a) ->
Expand Down Expand Up @@ -1762,7 +1793,7 @@ let rec combineTypes (what: combineWhat) (oldt: typ) (t: typ) : typ =
combineTypes
(if what = CombineFundef then
CombineFunarg else CombineOther)
ot' at
(removeOuterQualifierAttributes ot') (removeOuterQualifierAttributes at)
in
let a = addAttributes oa aa in
(n, t, a))
Expand Down Expand Up @@ -2458,6 +2489,7 @@ let rec doSpecList (suggestedAnonName: string) (* This string will be part of
| [A.Tfloat128] -> TFloat(FLongDouble, []) (* TODO: Correct? *)

(* Now the other type specifiers *)
| [A.Tdefault] -> E.s (error "Default outside generic associations")
| [A.Tnamed n] -> begin
if n = "__builtin_va_list" &&
!Machdep.theMachine.Machdep.__builtin_va_list then begin
Expand Down Expand Up @@ -4844,6 +4876,38 @@ and doExp (asconst: bool) (* This expression is used as a constant *)

| A.EXPR_PATTERN _ -> E.s (E.bug "EXPR_PATTERN in cabs2cil input")

| A.GENERIC (e, al) ->
let is_default = function
| [SpecType Tdefault] -> true (* exactly matches cparser *)
| _ -> false
in
let (al_default, al_nondefault) = List.partition (fun (at, _) -> is_default at) al in

let typ_compatible t1 t2 =
match combineTypes CombineOther t1 t2 with (* combineTypes seems to do "compatible types" check *)
| _ -> true
| exception (Failure _) -> false
in
(* cppreference mentions "lvalue conversions" on e before compatibility: https://en.cppreference.com/w/c/language/generic.
C11 standard section 6.5.1.1.3 does not mention anything.
TODO: Which is it and does doExp already do this? *)
let (_, _, e_typ) = doExp false e (AExp None) in
let e_typ = removeOuterQualifierAttributes e_typ in
let al_compatible = List.filter (fun (at, _) -> typ_compatible e_typ (doOnlyType at JUSTBASE)) al_nondefault in

(* TODO: error when multiple compatible associations or defaults even when unused? *)

begin match al_compatible with
| [(_, ae)] -> doExp false ae (AExp None)
| [] ->
begin match al_default with
| [(_, ae)] -> doExp false ae (AExp None)
| [] -> E.s (error "No compatible associations or default in generic")
| _ -> E.s (error "Multiple defaults in generic")
end
| _ -> E.s (error "Multiple compatible associations in generic")
end

with e when continueOnError -> begin
(*ignore (E.log "error in doExp (%s)" (Printexc.to_string e));*)
E.hadErrors := true;
Expand Down
10 changes: 10 additions & 0 deletions src/frontc/cabsvisit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,16 @@ and childrenExpression vis e =
let b' = visitCabsBlock vis b in
if b' != b then GNU_BODY b' else e
| EXPR_PATTERN _ -> e
| GENERIC (e, al) ->
let e' = ve e in
let al' = mapNoCopy (fun ((at, ae) as a) ->
let at' = visitCabsSpecifier vis at in
let ae' = ve ae in
if at' != at || ae' != ae then (at', ae') else a
) al
in
if e' != e || al' != al then GENERIC (e', al') else e


and visitCabsInitExpression vis (ie: init_expression) : init_expression =
doVisit vis vis#vinitexpr childrenInitExpression ie
Expand Down
1 change: 1 addition & 0 deletions src/frontc/clexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ let init_lexicon _ =
THREAD loc
else
IDENT ("__thread", loc));
("_Generic", fun loc -> GENERIC loc);
]

(* Mark an identifier as a type name. The old mapping is preserved and will
Expand Down
12 changes: 12 additions & 0 deletions src/frontc/cparser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ let transformOffsetOf (speclist, dtype) member =
%token EOF
%token<Cabs.cabsloc> CHAR INT BOOL DOUBLE FLOAT VOID INT64 INT32
%token<Cabs.cabsloc> INT128 FLOAT128 COMPLEX /* C99 */
%token<Cabs.cabsloc> GENERIC /* C11 */
%token<Cabs.cabsloc> ENUM STRUCT TYPEDEF UNION
%token<Cabs.cabsloc> SIGNED UNSIGNED LONG SHORT
%token<Cabs.cabsloc> VOLATILE EXTERN STATIC CONST RESTRICT AUTO REGISTER
Expand Down Expand Up @@ -475,8 +476,19 @@ primary_expression: /*(* 6.5.1. *)*/
/*(* Next is Scott's transformer *)*/
| AT_EXPR LPAREN IDENT RPAREN /* expression pattern variable */
{ EXPR_PATTERN(fst $3), $1 }
| GENERIC LPAREN assignment_expression COMMA generic_assoc_list RPAREN {GENERIC ((fst $3), $5), $1}
;

/* (specifier, expression) list */
generic_assoc_list:
| generic_association {[$1]}
| generic_assoc_list COMMA generic_association {$3 :: $1}

/* specifier, expression */
generic_association:
| type_name COLON assignment_expression {fst $1, fst $3}
| DEFAULT COLON assignment_expression {[SpecType(Tdefault)], fst $3}

postfix_expression: /*(* 6.5.2 *)*/
| primary_expression
{ $1 }
Expand Down
17 changes: 17 additions & 0 deletions src/frontc/cprint.ml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ and print_type_spec = function
(print_enum_items enum_items)
| TtypeofE e -> printl ["__typeof__";"("]; print_expression e; print ") "
| TtypeofT (s,d) -> printl ["__typeof__";"("]; print_onlytype (s, d); print ") "
| Tdefault -> print "default " (* TODO: is this right? *)


(* print "struct foo", but with specified keyword and a list of
Expand Down Expand Up @@ -403,6 +404,7 @@ and get_operator exp =
| TYPE_SIZEOF _ -> ("", 16)
| EXPR_ALIGNOF exp -> ("", 16)
| TYPE_ALIGNOF _ -> ("", 16)
| GENERIC _ -> ("", 16) (* TODO: is this right? *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this TODO resolved now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect not, but I don't know what it's precedence is even supposed to be because it's not even listed here: https://en.cppreference.com/w/c/language/operator_precedence.

Also, I'm not sure the rest are right either. Most of the additions have been copy-pasted all with precedence 16, but that doesn't match at all with the precedence table comment above or the table on cppref.

| IMAG exp -> ("", 16)
| REAL exp -> ("", 16)
| CLASSIFYTYPE exp -> ("", 16)
Expand Down Expand Up @@ -538,6 +540,21 @@ and print_expression_level (lvl: int) (exp : expression) =
printl ["__alignof__";"("];
print_onlytype (bt, dt);
print ")"
| GENERIC (exp, lst) ->
(* TODO: is this right? *)
let print_generic_list l =
match l with
[] -> ()
| (s, e) :: tl ->
print ", ";
print_onlytype (s, JUSTBASE);
print ": ";
print_expression_level 0 e;
in
printl ["_Generic";"("];
print_expression_level 0 exp;
print_generic_list lst;
print ")"
| IMAG exp ->
printl ["__imag__";"("];
print_expression_level 0 exp;
Expand Down
6 changes: 6 additions & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ testrunc99/% : $(SMALL1)/%.c
cd $(SMALL1); ./$*.exe
echo SUCCESS

testrunc11/% : $(SMALL1)/%.c
cd $(SMALL1); $(CILLY) --nomerge --commPrintLn \
$(CFLAGS) -std=c11 $(EXEOUT)$*.exe $*.c -lm
cd $(SMALL1); ./$*.exe
echo SUCCESS

testrungcc/% : $(SMALL1)/%.c mustbegcc
cd $(SMALL1); $(CILLY) --nomerge --commPrintLn \
$(CFLAGS) $(EXEOUT)$*.exe $*.c
Expand Down
27 changes: 27 additions & 0 deletions test/small1/c11-generic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "testharness.h"
#define type1(x) _Generic((x), char: 1, unsigned int:2, default:0)
#define type2(x) _Generic((x), char: 1, unsigned int:2, const int:3, default:0)

// This fails to compile but is perfectly legal, since int and const int are not compatible
#define type3(x) _Generic((x), int:1, const int:2, default:0)

int main() {
unsigned char v_uchar;
char v_char;
int v_int;
const int v_intconst;

if(type1(v_int) != 0) { E(1); }
if(type1(v_uchar) != 0) { E(2); }
if(type1(v_char) != 1) { E(3); }

if(type2(v_int) != 0) { E(4); } // This fails but should succeed
if(type2(v_intconst) != 0) { E(5); } // This fails but should succeed
if(type3(v_int) != 1) { E(6); }
if(type3(v_intconst) != 1) { E(7); }

if(type3((const int)v_int) != 1) { E(8); }
if(type3((const int)v_intconst) != 1) { E(9); }

SUCCESS;
}
20 changes: 0 additions & 20 deletions test/small1/decl1.c

This file was deleted.

2 changes: 1 addition & 1 deletion test/testcil.pl
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,6 @@ sub addToGroup {
addTest("testrun/lval1 _GNUCC=1");
#MIA: addTest("test/bind2 EXTRAARGS=--allowInlineAssembly");
#addToGroup("test/bind2", "slow");
addTest("testrun/decl1 _GNUCC=1");
addTest("testrun/addr-array");
addTest("testrun/addr-string");
addTest("combine1 ");
Expand Down Expand Up @@ -713,6 +712,7 @@ sub addToGroup {
addTest("combinec99inline");
addBadComment("combinec99inline", "C99 inline semantic not fully supported.");

addTest("testrunc11/c11-generic");

# ---------------- c-torture -------------
## if we have the c-torture tests add them
Expand Down