Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cb5bbd2

Browse files
committed
[CPP-340] When warning about mismatched parameters, follow what C
compilers do. Various integral and floating-point types are treated as mutually implicitly convertible. Remaining warnings deal with misuse of pointer and array types.
1 parent 29af56d commit cb5bbd2

12 files changed

Lines changed: 117 additions & 88 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
void no_argument();
2-
31
void three_arguments(int x, int y, int z);
42

53
void calls() {
6-
three_arguments(1, 2, 3); // GOOD
7-
three_arguments(1.0f, 2, 3.0f); // BAD: arguments 1 and 3 do not match parameters
4+
int three = 3;
5+
three_arguments(1, 2, three); // GOOD
6+
three_arguments(1, 2, &three); // BAD
87
}
Binary file not shown.

cpp/ql/src/Likely Bugs/UnderspecifiedFunctions/MistypedFunctionArguments.ql

Lines changed: 29 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,89 +14,55 @@
1414

1515
import cpp
1616

17-
predicate argTypeMayBePromoted(Type arg, Type parm) {
17+
pragma[inline]
18+
predicate argTypeMayBeImplicitlyConverted(Type arg, Type parm) {
1819
arg = parm
1920
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
4423
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
4626
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
4829
or
49-
arg instanceof Enum and parm instanceof LongType
30+
arg instanceof PointerType and parm instanceof VoidPointerType
5031
or
51-
arg instanceof Enum and parm instanceof LongLongType
32+
arg instanceof ArrayType and parm instanceof VoidPointerType
5233
or
53-
// enums are usually sized as ints
54-
arg instanceof IntType and parm instanceof Enum
34+
arg instanceof VoidPointerType and parm instanceof ArrayType
5535
or
56-
// pointer types
36+
// pointers to same types
5737
arg.(PointerType).getBaseType().getUnspecifiedType() = parm
58-
.getUnspecifiedType()
5938
.(PointerType)
6039
.getBaseType()
6140
.getUnspecifiedType()
6241
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()
7146
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()
7551
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()
7956
}
8057

8158
// This predicate doesn't necessarily have to exist, but if it does exist
8259
// then it must be inline to make sure we don't enumerate all pairs of
8360
// compatible types.
8461
// Its body could also just be hand-inlined where it's used.
8562
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(),
8865
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-
)
10066
}
10167

10268
from FunctionCall fc, Function f, Parameter p
@@ -110,8 +76,7 @@ where
11076
fde.getNumberOfParameters() = 0
11177
) and
11278
// 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)
11480
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()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.file "MistypedFunctionArguments.c"

cpp/ql/src/Likely Bugs/UnderspecifiedFunctions/TooFewArguments.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @kind problem
88
* @problem.severity error
99
* @precision very-high
10-
* @id cpp/too-few-arguments
10+
* @id cpp/futile-params
1111
* @tags correctness
1212
* maintainability
1313
* security
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
2-
void one_argument(int x);
1+
void one_argument();
32

43
void calls() {
54

65
one_argument(1); // GOOD: `one_argument` will accept and use the argument
76

87
one_argument(1, 2); // BAD: `one_argument` will use the first argument but ignore the second
98
}
9+
10+
void one_argument(int x);

cpp/ql/src/Likely Bugs/UnderspecifiedFunctions/TooManyArguments.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@
2525
</example>
2626

2727
<references>
28-
<li>SEI CERT C++ Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/DCL20-C.+Explicitly+specify+void+when+a+function+accepts+no+arguments"> DCL20-C. Explicitly specify void when a function accepts no arguments </a></li>
28+
<li>SEI CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/DCL20-C.+Explicitly+specify+void+when+a+function+accepts+no+arguments"> DCL20-C. Explicitly specify void when a function accepts no arguments </a></li>
2929
</references>
3030
</qhelp>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//void three_arguments();
2+
void three_arguments(int x, char y, int *z);
3+
void pointer_arguments(float *x, void *y, int **z);
4+
void array_argument(int arr[6]);
5+
void array_argument2(char arr[6]);
6+
int var;
7+
void *pv;
8+
double d = 3732.70e13L;
9+
extern unsigned long long *ull;
10+
11+
extern void *a[3];
12+
13+
void calls() {
14+
three_arguments(*ull, 2, &var); // BAD: arguments 1 and 3 do not match parameters
15+
three_arguments(&ull, 2, &var); // BAD: arguments 1 and 3 do not match parameters
16+
three_arguments(&var, 2, &var); // BAD: arguments 1 and 3 do not match parameters
17+
three_arguments(var, 2, 3.0f); // BAD: arguments 1 and 3 do not match parameters
18+
19+
pointer_arguments(20, 0, 0); // BAD
20+
pointer_arguments(pv, &var, &pv); // GOOD
21+
pointer_arguments(&pv, &var, pv); // BAD
22+
pointer_arguments(&var, a, &pv); // BAD
23+
pointer_arguments(&var, &pv, a); // BAD
24+
25+
array_argument(&var);
26+
array_argument(pv);
27+
array_argument(10);
28+
array_argument("Hello");
29+
30+
array_argument2("Hello");
31+
32+
}
33+
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
| test.c:23:3:23:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:6:32:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:23:31:23:32 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:32:38:32:38 | x | int x |
2-
| test.c:24:3:24:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:6:32:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:24:31:24:34 | 3.0 | 3.0 | file://:0:0:0:0 | float | float | test.c:32:38:32:38 | x | int x |
3-
| test.c:26:3:26:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:35:6:35:30 | not_declared_defined_with | not_declared_defined_with | test.c:26:29:26:31 | 1.0 | 1.0 | file://:0:0:0:0 | double | double | test.c:35:36:35:36 | x | int x |
4-
| test.c:27:3:27:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:35:6:35:30 | not_declared_defined_with | not_declared_defined_with | test.c:27:29:27:31 | 4 | 4 | file://:0:0:0:0 | long long | long long | test.c:35:36:35:36 | x | int x |
1+
| test.c:25:3:25:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:24:3:24:3 | not_yet_declared2 | not_yet_declared2 | test.c:25:21:25:22 | ca | ca | file://:0:0:0:0 | int * | int * | test.c:45:24:45:26 | p#0 | int p#0 |
2+
| test.c:25:3:25:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:45:6:45:22 | not_yet_declared2 | not_yet_declared2 | test.c:25:21:25:22 | ca | ca | file://:0:0:0:0 | int * | int * | test.c:45:24:45:26 | p#0 | int p#0 |
3+
| test.c:32:3:32:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:46:6:46:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:32:31:32:32 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:46:38:46:38 | x | int x |
4+
| test.c:39:3:39:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:5:6:5:27 | declared_with_pointers | declared_with_pointers | test.c:39:26:39:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:61:34:61:34 | x | int * x |
5+
| test.c:39:3:39:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:61:6:61:27 | declared_with_pointers | declared_with_pointers | test.c:39:26:39:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:61:34:61:34 | x | int * x |
6+
| test.c:41:3:41:21 | call to declared_with_array | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:6:6:6:24 | declared_with_array | declared_with_array | test.c:41:23:41:24 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:62:31:62:31 | a | char[6] a |
7+
| test.c:41:3:41:21 | call to declared_with_array | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:62:6:62:24 | declared_with_array | declared_with_array | test.c:41:23:41:24 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:62:31:62:31 | a | char[6] a |
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
| test.c:17:3:17:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:16:3:16:3 | not_yet_declared2 | not_yet_declared2 |
2-
| test.c:17:3:17:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:31:6:31:22 | not_yet_declared2 | not_yet_declared2 |
3-
| test.c:19:3:19:29 | call to declared_empty_defined_with | This call has fewer arguments than required by $@. | test.c:32:6:32:32 | declared_empty_defined_with | declared_empty_defined_with |
1+
| test.c:26:3:26:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:24:3:24:3 | not_yet_declared2 | not_yet_declared2 |
2+
| test.c:26:3:26:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:45:6:45:22 | not_yet_declared2 | not_yet_declared2 |
3+
| test.c:28:3:28:29 | call to declared_empty_defined_with | This call has fewer arguments than required by $@. | test.c:46:6:46:32 | declared_empty_defined_with | declared_empty_defined_with |
4+
| test.c:56:10:56:20 | call to dereference | This call has fewer arguments than required by $@. | test.c:59:5:59:15 | dereference | dereference |

0 commit comments

Comments
 (0)