@@ -603,11 +603,7 @@ let alphaConvertVarAndAddToEnv (addtoenv: bool) (vi: varinfo) : varinfo =
603603 * a struct we must recursively strip the "const" from fields and array
604604 * elements. *)
605605let rec stripConstLocalType (t : typ ) : typ =
606- let dc a =
607- if hasAttribute " const" a then
608- dropAttribute " const" a
609- else a
610- in
606+ let dc = dropAttribute " pconst" in
611607 match t with
612608 | TPtr (bt , a ) ->
613609 (* We want to be able to detect by pointer equality if the type has
@@ -1570,7 +1566,16 @@ type combineWhat =
15701566 * that are known to be equal *)
15711567let isomorphicStructs : (string * string, bool) H.t = H. create 15
15721568
1569+ (* * Construct the composite type of [oldt] and [t] if they are compatible.
1570+ Raise [Failure] if they are incompatible. *)
15731571let rec combineTypes (what : combineWhat ) (oldt : typ ) (t : typ ) : typ =
1572+ let (oldq, olda) = partitionQualifierAttributes (typeAttrsOuter oldt) in
1573+ let (q, a) = partitionQualifierAttributes (typeAttrsOuter t) in
1574+ if oldq <> q then
1575+ raise (Failure " different type qualifiers" )
1576+ else if q <> [] then
1577+ cabsTypeAddAttributes q (combineTypes what (setTypeAttrs oldt olda) (setTypeAttrs t a))
1578+ else
15741579 match oldt, t with
15751580 | TVoid olda , TVoid a -> TVoid (cabsAddAttributes olda a)
15761581 | TInt (oldik , olda ), TInt (ik , a ) ->
@@ -1743,7 +1748,7 @@ let rec combineTypes (what: combineWhat) (oldt: typ) (t: typ) : typ =
17431748 combineTypes
17441749 (if what = CombineFundef then
17451750 CombineFunarg else CombineOther )
1746- ot' at
1751+ (removeOuterQualifierAttributes ot') (removeOuterQualifierAttributes at)
17471752 in
17481753 let a = addAttributes oa aa in
17491754 (n, t, a))
@@ -1883,19 +1888,33 @@ let conditionalConversion (t2: typ) (t3: typ) (e2: exp option) (e3:exp) : typ =
18831888 arithmeticConversion t2 t3
18841889 | TComp (comp2,_), TComp (comp3,_), _
18851890 when comp2.ckey = comp3.ckey -> t2
1886- | TPtr (_ , _ ), TPtr (TVoid _ , _ ), _ ->
1887- if isNullPtrConstant e3 then t2 else t3
1888- | TPtr (TVoid _ , _ ), TPtr (_ , _ ), Some e2' ->
1889- if isNullPtrConstant e2' then t3 else t2
1891+ | TVoid [] , TVoid [] , _ -> TVoid [] (* TODO: what about qualifiers? standard says nothing *)
1892+ | TPtr (_ , _ ), _ , _ when isNullPtrConstant e3 -> t2
1893+ | _ , TPtr (_ , _ ), Some e2' when isNullPtrConstant e2' -> t3
1894+ | TPtr (b2, _), TPtr (TVoid _ as b3, _), _
1895+ | TPtr (TVoid _ as b2 , _ ), TPtr (b3 , _ ), _ ->
1896+ let a2 = typeAttrsOuter b2 in
1897+ let a3 = typeAttrsOuter b3 in
1898+ let (q2, _) = partitionQualifierAttributes a2 in
1899+ let (q3, _) = partitionQualifierAttributes a3 in
1900+ let q = cabsAddAttributes q2 q3 in
1901+ TPtr (TVoid q, [] )
18901902 | TPtr _ , TPtr _ , _ when Util. equals (typeSig t2) (typeSig t3) -> t2
1891- | TPtr _ , TInt _ , _ -> t2 (* most likely comparison with int constant 0, if it isn't it would not be valid C *)
1892- | TInt _ , TPtr _ , _ -> t3 (* most likely comparison with int constant 0, if it isn't it would not be valid C *)
1903+ | TPtr _ , TInt _ , _ -> t2 (* not "null pointer constant", not allowed by standard, works in gcc/clang with warning *)
1904+ | TInt _ , TPtr _ , _ -> t3 (* not "null pointer constant", not allowed by standard, works in gcc/clang with warning *)
18931905
18941906 (* When we compare two pointers of different type, we combine them
18951907 * using the same algorithm when combining multiple declarations of
18961908 * a global *)
1897- | (TPtr _ ) as t2' , (TPtr _ as t3' ), _ -> begin
1898- try combineTypes CombineOther t2' t3'
1909+ | TPtr (b2 , _ ), TPtr (b3 , _ ), _ -> begin
1910+ try
1911+ let a2 = typeAttrsOuter b2 in
1912+ let a3 = typeAttrsOuter b3 in
1913+ let (q2, a2') = partitionQualifierAttributes a2 in
1914+ let (q3, a3') = partitionQualifierAttributes a3 in
1915+ let b = combineTypes CombineOther (setTypeAttrs b2 a2') (setTypeAttrs b2 a3') in
1916+ let q = cabsAddAttributes q2 q3 in
1917+ TPtr (cabsTypeAddAttributes q b, [] )
18991918 with Failure msg -> begin
19001919 ignore (warn " A.QUESTION: %a does not match %a (%s)"
19011920 d_type (unrollType t2) d_type (unrollType t3) msg);
@@ -2443,6 +2462,7 @@ let rec doSpecList (suggestedAnonName: string) (* This string will be part of
24432462 | [A. Tfloat128 ] -> TFloat (FLongDouble , [] ) (* TODO: Correct? *)
24442463
24452464 (* Now the other type specifiers *)
2465+ | [A. Tdefault ] -> E. s (error " Default outside generic associations" )
24462466 | [A. Tnamed n] -> begin
24472467 if n = " __builtin_va_list" &&
24482468 ! Machdep. theMachine.Machdep. __builtin_va_list then begin
@@ -2629,7 +2649,7 @@ let rec doSpecList (suggestedAnonName: string) (* This string will be part of
26292649and convertCVtoAttr (src : A.cvspec list ) : A.attribute list =
26302650 match src with
26312651 | [] -> []
2632- | CV_CONST :: tl -> (" const" ,[] ) :: (convertCVtoAttr tl)
2652+ | CV_CONST :: tl -> (" const" ,[] ) :: ( " pconst " , [] ) :: (convertCVtoAttr tl)
26332653 | CV_VOLATILE :: tl -> (" volatile" ,[] ) :: (convertCVtoAttr tl)
26342654 | CV_RESTRICT :: tl -> (" restrict" ,[] ) :: (convertCVtoAttr tl)
26352655 | CV_COMPLEX :: tl -> (" complex" ,[] ) :: (convertCVtoAttr tl)
@@ -4798,6 +4818,35 @@ and doExp (asconst: bool) (* This expression is used as a constant *)
47984818
47994819 | A. EXPR_PATTERN _ -> E. s (E. bug " EXPR_PATTERN in cabs2cil input" )
48004820
4821+ | A. GENERIC (e , al ) ->
4822+ let is_default = function
4823+ | ([SpecType Tdefault], JUSTBASE) -> true (* exactly matches cparser *)
4824+ | _ -> false
4825+ in
4826+ let (al_default, al_nondefault) = List. partition (fun (at , _ ) -> is_default at) al in
4827+
4828+ let typ_compatible t1 t2 =
4829+ match combineTypes CombineOther t1 t2 with (* combineTypes does "compatible types" check *)
4830+ | _ -> true
4831+ | exception (Failure _ ) -> false
4832+ in
4833+ let (_, _, e_typ) = doExp false e (AExp None ) in (* doExp with AExp handles array and function types for "lvalue conversions" (AType would not!) *)
4834+ let e_typ = removeOuterQualifierAttributes e_typ in (* removeOuterQualifierAttributes handles qualifiers for "lvalue conversions" *)
4835+ let al_compatible = List. filter (fun ((ast , adt ), _ ) -> typ_compatible e_typ (doOnlyType ast adt)) al_nondefault in
4836+
4837+ (* TODO: error when multiple compatible associations or defaults even when unused? *)
4838+
4839+ begin match al_compatible with
4840+ | [(_, ae)] -> doExp false ae (AExp None )
4841+ | [] ->
4842+ begin match al_default with
4843+ | [(_, ae)] -> doExp false ae (AExp None )
4844+ | [] -> E. s (error " No compatible associations or default in generic" )
4845+ | _ -> E. s (error " Multiple defaults in generic" )
4846+ end
4847+ | _ -> E. s (error " Multiple compatible associations in generic" )
4848+ end
4849+
48014850 with e when continueOnError -> begin
48024851 (* ignore (E.log "error in doExp (%s)" (Printexc.to_string e));*)
48034852 E. hadErrors := true ;
0 commit comments