Skip to content

Commit e21a5e4

Browse files
authored
Merge pull request #214 from jbj/mergeback-20180921_104253
Mergeback rc/1.18 -> master
2 parents d281558 + e2a17e9 commit e21a5e4

File tree

23 files changed

+328
-55
lines changed

23 files changed

+328
-55
lines changed

cpp/ql/src/semmle/code/cpp/Parameter.qll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,9 @@ class Parameter extends LocalScopeVariable, @parameter {
6868
*/
6969
private VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
7070
if getFunction().isConstructedFrom(_)
71-
then exists (Parameter prototype
72-
| prototype = result.getVariable() and
73-
prototype.getIndex() = getIndex() and
74-
getFunction().isConstructedFrom(prototype.getFunction()))
71+
then exists (Function prototypeInstantiation
72+
| prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and
73+
getFunction().isConstructedFrom(prototypeInstantiation))
7574
else result = getADeclarationEntry()
7675
}
7776

cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
import semmle.code.cpp.Type
22

3-
/** Holds if `d` is a complete class named `name`. */
3+
pragma[noinline]
4+
private string getTopLevelClassName(@usertype c) {
5+
isClass(c) and
6+
usertypes(c, result, _) and
7+
not namespacembrs(_, c) and // not in a namespace
8+
not member(_, _, c) and // not in some structure
9+
not class_instantiation(c, _) // not a template instantiation
10+
}
11+
12+
/** Holds if `d` is a unique complete class named `name`. */
413
pragma[noinline]
514
private predicate existsCompleteWithName(string name, @usertype d) {
6-
isClass(d) and
715
is_complete(d) and
8-
usertypes(d, name, _)
16+
name = getTopLevelClassName(d) and
17+
strictcount(@usertype other | is_complete(other) and getTopLevelClassName(other) = name) = 1
918
}
1019

1120
/** Holds if `c` is an incomplete class named `name`. */
1221
pragma[noinline]
1322
private predicate existsIncompleteWithName(string name, @usertype c) {
14-
isClass(c) and
1523
not is_complete(c) and
16-
usertypes(c, name, _)
24+
name = getTopLevelClassName(c)
1725
}
1826

1927
/**
20-
* Holds if `c` is an incomplete class, and there exists a complete class `d`
28+
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
2129
* with the same name.
2230
*/
2331
private predicate hasCompleteTwin(@usertype c, @usertype d) {
@@ -30,10 +38,8 @@ private predicate hasCompleteTwin(@usertype c, @usertype d) {
3038
import Cached
3139
cached private module Cached {
3240
/**
33-
* If `c` is incomplete, and there exists a complete class with the same name,
34-
* then the result is that complete class. Otherwise, the result is `c`. If
35-
* multiple complete classes have the same name, this predicate may have
36-
* multiple results.
41+
* If `c` is incomplete, and there exists a unique complete class with the same name,
42+
* then the result is that complete class. Otherwise, the result is `c`.
3743
*/
3844
cached @usertype resolveClass(@usertype c) {
3945
hasCompleteTwin(c, result)

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ newtype TTranslatedElement =
270270
not ignoreExpr(initList) and
271271
isFirstValueInitializedElementInRange(initList, elementIndex) and
272272
elementCount =
273-
getNextExplicitlyInitializedElementAfter(initList, elementIndex) -
273+
getEndOfValueInitializedRange(initList, elementIndex) -
274274
elementIndex
275275
} or
276276
// The initialization of a base class from within a constructor.
@@ -322,23 +322,30 @@ newtype TTranslatedElement =
322322

323323
/**
324324
* Gets the index of the first explicitly initialized element in `initList`
325-
* whose index is greater than `afterElementIndex`. If there are no remaining
326-
* explicitly initialized elements in `initList`, the result is the total number
327-
* of elements in the array being initialized.
325+
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
326+
* is a first value-initialized element in a value-initialized range in
327+
* `initList`. If there are no remaining explicitly initialized elements in
328+
* `initList`, the result is the total number of elements in the array being
329+
* initialized.
328330
*/
329-
private int getNextExplicitlyInitializedElementAfter(
330-
ArrayAggregateLiteral initList, int afterElementIndex) {
331-
if exists(int x |
332-
x > afterElementIndex and
333-
exists(initList.getElementExpr(x)))
334-
then (
335-
if exists(initList.getElementExpr(afterElementIndex + 1))
336-
then result = afterElementIndex + 1
337-
else result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex+1))
338-
else
339-
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() and
340-
// required for binding
341-
initList.isInitialized(afterElementIndex)
331+
private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) {
332+
result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)
333+
or
334+
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
335+
not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
336+
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize()
337+
}
338+
339+
/**
340+
* Gets the index of the first explicitly initialized element in `initList`
341+
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
342+
* is a first value-initialized element in a value-initialized range in
343+
* `initList`.
344+
*/
345+
private int getNextExplicitlyInitializedElementAfter(
346+
ArrayAggregateLiteral initList, int afterElementIndex) {
347+
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
348+
result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex)
342349
}
343350

344351
/**

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6303,3 +6303,35 @@ ir.cpp:
63036303
# 958| Type = int
63046304
# 958| ValueCategory = prvalue(load)
63056305
# 959| 8: return ...
6306+
# 961| designatedInit() -> int
6307+
# 961| params:
6308+
# 961| body: { ... }
6309+
# 962| 0: declaration
6310+
# 962| 0: definition of a1
6311+
# 962| Type = int[1000]
6312+
# 962| init: initializer for a1
6313+
# 962| expr: {...}
6314+
# 962| Type = int[1000]
6315+
# 962| ValueCategory = prvalue
6316+
# 962| 0: 10002
6317+
# 962| Type = int
6318+
# 962| Value = 10002
6319+
# 962| ValueCategory = prvalue
6320+
# 962| 1: 10900
6321+
# 962| Type = int
6322+
# 962| Value = 10900
6323+
# 962| ValueCategory = prvalue
6324+
# 963| 1: return ...
6325+
# 963| 0: access to array
6326+
# 963| Type = int
6327+
# 963| ValueCategory = prvalue(load)
6328+
# 963| 0: array to pointer conversion
6329+
# 963| Type = int *
6330+
# 963| ValueCategory = prvalue
6331+
# 963| expr: a1
6332+
# 963| Type = int[1000]
6333+
# 963| ValueCategory = lvalue
6334+
# 963| 1: 900
6335+
# 963| Type = int
6336+
# 963| Value = 900
6337+
# 963| ValueCategory = prvalue

cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3906,3 +3906,49 @@ ir.cpp:
39063906
# 950| v0_65(void) = ReturnVoid :
39073907
# 950| v0_66(void) = UnmodeledUse : mu*
39083908
# 950| v0_67(void) = ExitFunction :
3909+
3910+
# 961| designatedInit() -> int
3911+
# 961| Block 0
3912+
# 961| v0_0(void) = EnterFunction :
3913+
# 961| mu0_1(unknown) = UnmodeledDefinition :
3914+
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
3915+
# 962| r0_3(int) = Constant[0] :
3916+
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
3917+
# 962| r0_5(unknown[8]) = Constant[0] :
3918+
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
3919+
#-----| Goto -> Block 2
3920+
3921+
# 962| Block 1
3922+
# 962| r1_0(int) = Constant[900] :
3923+
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
3924+
# 962| r1_2(int) = Constant[10900] :
3925+
# 962| mu1_3(int) = Store : r1_1, r1_2
3926+
# 962| r1_4(int) = Constant[901] :
3927+
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
3928+
# 962| r1_6(unknown[396]) = Constant[0] :
3929+
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
3930+
#-----| Goto -> Block 2
3931+
3932+
# 963| Block 2
3933+
# 963| r2_0(glval<int>) = VariableAddress[#return] :
3934+
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
3935+
# 963| r2_2(int *) = Convert : r2_1
3936+
# 963| r2_3(int) = Constant[900] :
3937+
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
3938+
# 963| r2_5(int) = Load : r2_4, mu0_1
3939+
# 963| m2_6(int) = Store : r2_0, r2_5
3940+
# 961| r2_7(glval<int>) = VariableAddress[#return] :
3941+
# 961| v2_8(void) = ReturnValue : r2_7, m2_6
3942+
# 961| v2_9(void) = UnmodeledUse : mu*
3943+
# 961| v2_10(void) = ExitFunction :
3944+
3945+
# 962| Block 3
3946+
# 962| r3_0(int) = Constant[2] :
3947+
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
3948+
# 962| r3_2(int) = Constant[10002] :
3949+
# 962| mu3_3(int) = Store : r3_1, r3_2
3950+
# 962| r3_4(int) = Constant[3] :
3951+
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
3952+
# 962| r3_6(unknown[3588]) = Constant[0] :
3953+
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
3954+
#-----| Goto -> Block 2

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,11 @@ void OperatorNewArray(int n) {
958958
new int[n] { 0, 1, 2 };
959959
}
960960

961+
int designatedInit() {
962+
int a1[1000] = { [2] = 10002, [900] = 10900 };
963+
return a1[900];
964+
}
965+
961966
#if 0
962967
void OperatorDelete() {
963968
delete static_cast<int*>(nullptr); // No destructor

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3885,3 +3885,49 @@ ir.cpp:
38853885
# 950| v0_65(void) = ReturnVoid :
38863886
# 950| v0_66(void) = UnmodeledUse : mu*
38873887
# 950| v0_67(void) = ExitFunction :
3888+
3889+
# 961| designatedInit() -> int
3890+
# 961| Block 0
3891+
# 961| v0_0(void) = EnterFunction :
3892+
# 961| mu0_1(unknown) = UnmodeledDefinition :
3893+
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
3894+
# 962| r0_3(int) = Constant[0] :
3895+
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
3896+
# 962| r0_5(unknown[8]) = Constant[0] :
3897+
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
3898+
#-----| Goto -> Block 2
3899+
3900+
# 962| Block 1
3901+
# 962| r1_0(int) = Constant[900] :
3902+
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
3903+
# 962| r1_2(int) = Constant[10900] :
3904+
# 962| mu1_3(int) = Store : r1_1, r1_2
3905+
# 962| r1_4(int) = Constant[901] :
3906+
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
3907+
# 962| r1_6(unknown[396]) = Constant[0] :
3908+
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
3909+
#-----| Goto -> Block 2
3910+
3911+
# 963| Block 2
3912+
# 963| r2_0(glval<int>) = VariableAddress[#return] :
3913+
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
3914+
# 963| r2_2(int *) = Convert : r2_1
3915+
# 963| r2_3(int) = Constant[900] :
3916+
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
3917+
# 963| r2_5(int) = Load : r2_4, mu0_1
3918+
# 963| mu2_6(int) = Store : r2_0, r2_5
3919+
# 961| r2_7(glval<int>) = VariableAddress[#return] :
3920+
# 961| v2_8(void) = ReturnValue : r2_7, mu0_1
3921+
# 961| v2_9(void) = UnmodeledUse : mu*
3922+
# 961| v2_10(void) = ExitFunction :
3923+
3924+
# 962| Block 3
3925+
# 962| r3_0(int) = Constant[2] :
3926+
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
3927+
# 962| r3_2(int) = Constant[10002] :
3928+
# 962| mu3_3(int) = Store : r3_1, r3_2
3929+
# 962| r3_4(int) = Constant[3] :
3930+
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
3931+
# 962| r3_6(unknown[3588]) = Constant[0] :
3932+
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
3933+
#-----| Goto -> Block 2

cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
| IR: VarArgs | 1 |
9393
| IR: VirtualMemberFunction | 1 |
9494
| IR: WhileStatements | 4 |
95+
| IR: designatedInit | 4 |
9596
| IR: min | 4 |
9697
| IR: operator= | 1 |
9798
| IR: ~Base | 1 |

cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3906,3 +3906,49 @@ ir.cpp:
39063906
# 950| v0_65(void) = ReturnVoid :
39073907
# 950| v0_66(void) = UnmodeledUse : mu*
39083908
# 950| v0_67(void) = ExitFunction :
3909+
3910+
# 961| designatedInit() -> int
3911+
# 961| Block 0
3912+
# 961| v0_0(void) = EnterFunction :
3913+
# 961| mu0_1(unknown) = UnmodeledDefinition :
3914+
# 962| r0_2(glval<int[1000]>) = VariableAddress[a1] :
3915+
# 962| r0_3(int) = Constant[0] :
3916+
# 962| r0_4(glval<int>) = PointerAdd : r0_2, r0_3
3917+
# 962| r0_5(unknown[8]) = Constant[0] :
3918+
# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5
3919+
#-----| Goto -> Block 2
3920+
3921+
# 962| Block 1
3922+
# 962| r1_0(int) = Constant[900] :
3923+
# 962| r1_1(glval<int>) = PointerAdd : r0_2, r1_0
3924+
# 962| r1_2(int) = Constant[10900] :
3925+
# 962| mu1_3(int) = Store : r1_1, r1_2
3926+
# 962| r1_4(int) = Constant[901] :
3927+
# 962| r1_5(glval<int>) = PointerAdd : r0_2, r1_4
3928+
# 962| r1_6(unknown[396]) = Constant[0] :
3929+
# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6
3930+
#-----| Goto -> Block 2
3931+
3932+
# 963| Block 2
3933+
# 963| r2_0(glval<int>) = VariableAddress[#return] :
3934+
# 963| r2_1(glval<int[1000]>) = VariableAddress[a1] :
3935+
# 963| r2_2(int *) = Convert : r2_1
3936+
# 963| r2_3(int) = Constant[900] :
3937+
# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3
3938+
# 963| r2_5(int) = Load : r2_4, mu0_1
3939+
# 963| m2_6(int) = Store : r2_0, r2_5
3940+
# 961| r2_7(glval<int>) = VariableAddress[#return] :
3941+
# 961| v2_8(void) = ReturnValue : r2_7, m2_6
3942+
# 961| v2_9(void) = UnmodeledUse : mu*
3943+
# 961| v2_10(void) = ExitFunction :
3944+
3945+
# 962| Block 3
3946+
# 962| r3_0(int) = Constant[2] :
3947+
# 962| r3_1(glval<int>) = PointerAdd : r0_2, r3_0
3948+
# 962| r3_2(int) = Constant[10002] :
3949+
# 962| mu3_3(int) = Store : r3_1, r3_2
3950+
# 962| r3_4(int) = Constant[3] :
3951+
# 962| r3_5(glval<int>) = PointerAdd : r0_2, r3_4
3952+
# 962| r3_6(unknown[3588]) = Constant[0] :
3953+
# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6
3954+
#-----| Goto -> Block 2

cpp/ql/test/library-tests/structs/compatible_cpp/b1.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@ class Damson {
2424
int damson_x;
2525
void foo();
2626
};
27+
28+
namespace unrelated {
29+
class AppleCompatible {
30+
long apple_x;
31+
};
32+
}

cpp/ql/test/library-tests/structs/compatible_cpp/compatible.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
| b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 1 | foo |
3333
| b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 2 | operator= |
3434
| b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 3 | operator= |
35+
| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 0 | apple_x |
36+
| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 1 | operator= |
37+
| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 2 | operator= |
3538
| b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 0 | apple_x |
3639
| b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 1 | operator= |
3740
| b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 2 | operator= |

cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
| b1.cpp:11:7:11:22 | BananaCompatible | 0 | file://:0:0:0:0 | int | 1 types |
1111
| b1.cpp:16:7:16:12 | Cherry | 0 | file://:0:0:0:0 | int | 1 types |
1212
| b1.cpp:23:7:23:12 | Damson | 0 | file://:0:0:0:0 | int | 1 types |
13+
| b1.cpp:29:9:29:23 | AppleCompatible | 0 | file://:0:0:0:0 | long | 1 types |
1314
| b2.cpp:2:7:2:21 | AppleCompatible | 0 | file://:0:0:0:0 | int | 1 types |
1415
| b2.cpp:9:7:9:22 | BananaCompatible | 0 | file://:0:0:0:0 | int | 1 types |
1516
| b2.cpp:14:7:14:12 | Cherry | 0 | file://:0:0:0:0 | short | 1 types |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
| a.h:5:8:5:13 | cheese | y.cpp:4:8:4:10 | Foo | 3 |
22
| x.cpp:3:6:3:10 | bar_x | a.h:4:8:4:10 | Bar | 3 |
3+
| x.cpp:19:6:19:10 | foo_x | y.cpp:4:8:4:10 | Foo | 3 |
4+
| x.cpp:23:5:23:17 | templateField | x.cpp:6:10:6:12 | Foo | 3 |
5+
| x.cpp:23:5:23:17 | templateField | x.cpp:12:9:12:11 | Foo | 3 |
6+
| x.cpp:26:18:26:29 | template_foo | x.cpp:22:7:22:14 | Template<Foo *> | 0 |
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
11
#include "a.h"
22

33
Bar *bar_x;
4+
5+
namespace unrelated {
6+
struct Foo {
7+
short val;
8+
};
9+
}
10+
11+
struct ContainsAnotherFoo {
12+
class Foo {
13+
long val;
14+
};
15+
};
16+
17+
// The type of `foo_x` should not refer to any of the above classes, none of
18+
// which are named `Foo` in the global scope.
19+
Foo *foo_x;
20+
21+
template<typename T>
22+
class Template {
23+
T templateField;
24+
};
25+
26+
Template<Foo *> *template_foo;
27+
28+
// Instantiation of the template with unrelated classes named `Foo` should not
29+
// get mixed up with the instantiation above.
30+
template class Template<unrelated::Foo *>;
31+
template class Template<ContainsAnotherFoo::Foo *>;

0 commit comments

Comments
 (0)