|
14 | 14 |
|
15 | 15 | import cpp |
16 | 16 |
|
17 | | -predicate argTypeMayBePromoted(Type arg, Type parm) { |
| 17 | +pragma[inline] |
| 18 | +predicate argTypeMayBeImplicitlyConverted(Type arg, Type parm) { |
18 | 19 | arg = parm |
19 | 20 | or |
20 | | - // floating-point and integral promotions |
21 | | - arg instanceof FloatType and parm instanceof DoubleType |
22 | | - or |
23 | | - arg instanceof FloatType and parm instanceof LongDoubleType |
24 | | - or |
25 | | - arg instanceof DoubleType and parm instanceof LongDoubleType |
26 | | - or |
27 | | - arg instanceof CharType and parm instanceof IntType |
28 | | - or |
29 | | - arg instanceof CharType and parm instanceof IntType |
30 | | - or |
31 | | - arg instanceof CharType and parm instanceof LongType |
32 | | - or |
33 | | - arg instanceof CharType and parm instanceof LongLongType |
34 | | - or |
35 | | - arg instanceof ShortType and parm instanceof IntType |
36 | | - or |
37 | | - arg instanceof ShortType and parm instanceof LongType |
38 | | - or |
39 | | - arg instanceof ShortType and parm instanceof LongLongType |
40 | | - or |
41 | | - arg instanceof IntType and parm instanceof LongType |
42 | | - or |
43 | | - arg instanceof IntType and parm instanceof LongLongType |
| 21 | + // integral and floating-point types are implicitly convertible in C |
| 22 | + arg instanceof ArithmeticType and parm instanceof ArithmeticType |
44 | 23 | or |
45 | | - arg instanceof LongType and parm instanceof LongLongType |
| 24 | + // integral values may be used to initialize pointers (but NOT array addresses) |
| 25 | + arg instanceof IntegralType and parm instanceof PointerType |
46 | 26 | or |
47 | | - arg instanceof Enum and parm instanceof IntType |
| 27 | + // pointers-to-void may be used for arbitrary pointers |
| 28 | + arg instanceof VoidPointerType and parm instanceof PointerType |
48 | 29 | or |
49 | | - arg instanceof Enum and parm instanceof LongType |
| 30 | + arg instanceof PointerType and parm instanceof VoidPointerType |
50 | 31 | or |
51 | | - arg instanceof Enum and parm instanceof LongLongType |
| 32 | + arg instanceof ArrayType and parm instanceof VoidPointerType |
52 | 33 | or |
53 | | - // enums are usually sized as ints |
54 | | - arg instanceof IntType and parm instanceof Enum |
| 34 | + arg instanceof VoidPointerType and parm instanceof ArrayType |
55 | 35 | or |
56 | | - // pointer types |
| 36 | + // pointers to same types |
57 | 37 | arg.(PointerType).getBaseType().getUnspecifiedType() = parm |
58 | | - .getUnspecifiedType() |
59 | 38 | .(PointerType) |
60 | 39 | .getBaseType() |
61 | 40 | .getUnspecifiedType() |
62 | 41 | or |
63 | | - // void * parameters accept arbitrary pointer arguments |
64 | | - arg instanceof PointerType and |
65 | | - parm.(PointerType).getBaseType().getUnspecifiedType() instanceof VoidType |
66 | | - or |
67 | | - // handle reference types |
68 | | - argTypeMayBePromoted(arg.(ReferenceType).getBaseType().getUnspecifiedType(), parm) |
69 | | - or |
70 | | - argTypeMayBePromoted(arg, parm.(ReferenceType).getBaseType().getUnspecifiedType()) |
| 42 | + arg.(ArrayType).getBaseType().getUnspecifiedType() = parm |
| 43 | + .(PointerType) |
| 44 | + .getBaseType() |
| 45 | + .getUnspecifiedType() |
71 | 46 | or |
72 | | - // array-to-pointer decay |
73 | | - argTypeMayBePromoted(arg.(ArrayType).getBaseType().getUnspecifiedType(), |
74 | | - parm.(PointerType).getBaseType().getUnspecifiedType()) |
| 47 | + arg.(PointerType).getBaseType().getUnspecifiedType() = parm |
| 48 | + .(ArrayType) |
| 49 | + .getBaseType() |
| 50 | + .getUnspecifiedType() |
75 | 51 | or |
76 | | - // pointer-to-array promotion (C99) |
77 | | - argTypeMayBePromoted(arg.(PointerType).getBaseType().getUnspecifiedType(), |
78 | | - parm.(ArrayType).getBaseType().getUnspecifiedType()) |
| 52 | + arg.(ArrayType).getBaseType().getUnspecifiedType() = parm |
| 53 | + .(ArrayType) |
| 54 | + .getBaseType() |
| 55 | + .getUnspecifiedType() |
79 | 56 | } |
80 | 57 |
|
81 | 58 | // This predicate doesn't necessarily have to exist, but if it does exist |
82 | 59 | // then it must be inline to make sure we don't enumerate all pairs of |
83 | 60 | // compatible types. |
84 | 61 | // Its body could also just be hand-inlined where it's used. |
85 | 62 | pragma[inline] |
86 | | -predicate argMayBePromoted(Expr arg, Parameter parm) { |
87 | | - argTypeMayBePromoted(arg.getExplicitlyConverted().getType().getUnspecifiedType(), |
| 63 | +predicate argMayBeImplicitlyConverted(Expr arg, Parameter parm) { |
| 64 | + argTypeMayBeImplicitlyConverted(arg.getFullyConverted().getType().getUnspecifiedType(), |
88 | 65 | parm.getType().getUnspecifiedType()) |
89 | | - or |
90 | | - // The value 0 is often passed in to indicate NULL, or to initialize an arbitrary integer type. |
91 | | - // we will allow all literal values for simplicity. Pointer parameters are sometime passed |
92 | | - // special-case literals such as -1, -2, etc. |
93 | | - arg.(Literal).getType() instanceof IntegralType and |
94 | | - ( |
95 | | - parm.getType().getUnspecifiedType() instanceof PointerType |
96 | | - or |
97 | | - parm.getType().getUnspecifiedType() instanceof IntegralType and |
98 | | - arg.(Literal).getType().getSize() <= parm.getType().getUnspecifiedType().getSize() |
99 | | - ) |
100 | 66 | } |
101 | 67 |
|
102 | 68 | from FunctionCall fc, Function f, Parameter p |
|
110 | 76 | fde.getNumberOfParameters() = 0 |
111 | 77 | ) and |
112 | 78 | // Parameter p and its corresponding call argument must have mismatched types |
113 | | - not argMayBePromoted(fc.getArgument(p.getIndex()), p) |
| 79 | + not argMayBeImplicitlyConverted(fc.getArgument(p.getIndex()), p) |
114 | 80 | select fc, "Calling $@: argument $@ of type $@ is incompatible with parameter $@.", f, f.toString(), |
115 | | - fc.getArgument(p.getIndex()), fc.getArgument(p.getIndex()).toString(), |
116 | | - fc.getArgument(p.getIndex()).getType(), fc.getArgument(p.getIndex()).getType().toString(), p, |
117 | | - p.getTypedName() |
| 81 | + fc.getArgument(p.getIndex()) as arg, arg.toString(), arg.getFullyConverted().getType() as type, |
| 82 | + type.toString(), p, p.getTypedName() |
0 commit comments