Skip to content

Commit 34a03ec

Browse files
authored
Merge pull request #4213 from rdmarsh2/rdmarsh2/cpp/explicit-conversion-perf
C++: Improve performance of getExplicitlyConverted
2 parents c457435 + 2c01575 commit 34a03ec

File tree

2 files changed

+10
-10
lines changed

2 files changed

+10
-10
lines changed

cpp/ql/src/semmle/code/cpp/exprs/Expr.qll

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ class Expr extends StmtParent, @expr {
402402
*/
403403
predicate hasImplicitConversion() {
404404
exists(Expr e |
405-
exprconv(underlyingElement(this), unresolveElement(e)) and e.(Cast).isImplicit()
405+
exprconv(underlyingElement(this), unresolveElement(e)) and e.(Conversion).isImplicit()
406406
)
407407
}
408408

@@ -414,7 +414,7 @@ class Expr extends StmtParent, @expr {
414414
*/
415415
predicate hasExplicitConversion() {
416416
exists(Expr e |
417-
exprconv(underlyingElement(this), unresolveElement(e)) and not e.(Cast).isImplicit()
417+
exprconv(underlyingElement(this), unresolveElement(e)) and not e.(Conversion).isImplicit()
418418
)
419419
}
420420

@@ -453,12 +453,14 @@ class Expr extends StmtParent, @expr {
453453
* cast from B to C. Only (1) and (2) would be included.
454454
*/
455455
Expr getExplicitlyConverted() {
456-
// result is this or one of its conversions
457-
result = this.getConversion*() and
458-
// result is not an implicit conversion - it's either the expr or an explicit cast
459-
(result = this or not result.(Cast).isImplicit()) and
460-
// there is no further explicit conversion after result
461-
not exists(Cast other | other = result.getConversion+() and not other.isImplicit())
456+
// For performance, we avoid a full transitive closure over `getConversion`.
457+
// Since there can be several implicit conversions before and after an
458+
// explicit conversion, use `getImplicitlyConverted` to step over them
459+
// cheaply. Then, if there is an explicit conversion following the implict
460+
// conversion sequence, recurse to handle multiple explicit conversions.
461+
if this.getImplicitlyConverted().hasExplicitConversion()
462+
then result = this.getImplicitlyConverted().getConversion().getExplicitlyConverted()
463+
else result = this
462464
}
463465

464466
/**

cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.expected

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:3:32:3 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int * | int * | test.c:76:24:76:26 | p#0 | int p#0 |
21
| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:3:32:3 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int[4] | int[4] | test.c:76:24:76:26 | p#0 | int p#0 |
3-
| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:76:6:76:22 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int * | int * | test.c:76:24:76:26 | p#0 | int p#0 |
42
| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:76:6:76:22 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int[4] | int[4] | test.c:76:24:76:26 | p#0 | int p#0 |
53
| test.c:40:3:40:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:77:6:77:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:40:31:40:32 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:77:38:77:38 | x | int x |
64
| test.c:44:3:44:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:80:6:80:30 | not_declared_defined_with | not_declared_defined_with | test.c:44:29:44:31 | 4 | 4 | file://:0:0:0:0 | long long | long long | test.c:80:36:80:36 | x | int x |

0 commit comments

Comments
 (0)