Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions cpp/ql/src/semmle/code/cpp/exprs/Expr.qll
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ class Expr extends StmtParent, @expr {
valuebind(_, underlyingElement(this))
or
addressConstantExpression(this)
or
constantTemplateLiteral(this)
}

/**
Expand Down Expand Up @@ -1119,3 +1121,17 @@ private predicate isStandardPlacementNewAllocator(Function operatorNew) {

// Pulled out for performance. See QL-796.
private predicate hasNoConversions(Expr e) { not e.hasConversion() }

/**
* Holds if `e` is a literal of unknown value in a template, or a cast thereof.
* We assume that such literals are constant.
*/
private predicate constantTemplateLiteral(Expr e) {
// Unknown literals in uninstantiated templates could be enum constant
// accesses or pointer-to-member literals.
e instanceof Literal and
e.isFromUninstantiatedTemplate(_) and
not exists(e.getValue())
or
constantTemplateLiteral(e.(Cast).getExpr())
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ private predicate constantAddressLValue(Expr lvalue) {
// tells us how it's going to be used.
lvalue.(FunctionAccess).getType() instanceof RoutineType
or
// Pointer-to-member literals in uninstantiated templates
lvalue instanceof Literal and
not exists(lvalue.getValue()) and
lvalue.isFromUninstantiatedTemplate(_)
or
// String literals have array types and undergo array-to-pointer conversion.
lvalue instanceof StringLiteral
or
Expand Down Expand Up @@ -61,6 +66,10 @@ private predicate constantAddressPointer(Expr pointer) {
// tells us how it's going to be used.
pointer.(FunctionAccess).getType() instanceof FunctionPointerType
or
// Pointer to member function. These accesses are always pointers even though
// their type is `RoutineType`.
pointer.(FunctionAccess).getTarget() instanceof MemberFunction
or
addressConstantVariable(pointer.(VariableAccess).getTarget()) and
pointer.getType().getUnderlyingType() instanceof PointerType
or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ instructionWithoutSuccessor
| ms_try_mix.cpp:11:12:11:15 | Chi: call to C |
| ms_try_mix.cpp:28:12:28:15 | Chi: call to C |
| ms_try_mix.cpp:48:10:48:13 | Chi: call to C |
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
Expand Down
13 changes: 12 additions & 1 deletion cpp/ql/test/library-tests/syntax-zoo/pointer_to_member.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,16 @@ int usePM(int PM::* pm) {
void pmIsConst() {
static const struct {
int PM::* pm1;
} pms = { &PM::x1 };
void (PM::* pm2)();
} pms = { &PM::x1, &PM::f1 };
}

template<typename T>
void pmIsConstT() {
static const struct {
int T::* pm1;
void (T::* pm2)();
} pms = { &T::x1, &T::f1 };
}

template void pmIsConstT<PM>();
7 changes: 4 additions & 3 deletions cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ missingOperand
| misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
| pointer_to_member.cpp:35:13:35:19 | FieldAddress: x1 | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| pointer_to_member.cpp:36:13:36:19 | FieldAddress: x1 | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| range_analysis.c:368:10:368:21 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
| range_analysis.c:369:10:369:36 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
| range_analysis.c:370:10:370:38 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
Expand Down Expand Up @@ -66,7 +66,7 @@ instructionWithoutSuccessor
| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C |
| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... |
| ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } |
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
| static_init_templates.cpp:89:27:89:36 | Convert: (void *)... |
Expand Down Expand Up @@ -673,7 +673,8 @@ useNotDominatedByDefinition
| ms_try_mix.cpp:38:16:38:19 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) |
| ms_try_mix.cpp:41:12:41:15 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) |
| ms_try_mix.cpp:51:5:51:11 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_mix.cpp:47:6:47:28 | IR: ms_empty_finally_at_end | void ms_empty_finally_at_end() |
| pointer_to_member.cpp:35:13:35:19 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| pointer_to_member.cpp:36:11:36:30 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| pointer_to_member.cpp:36:13:36:19 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
| stmt_expr.cpp:30:20:30:21 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
| stmt_expr.cpp:31:16:31:18 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) |
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | IR: throw_from_nonstmt | void throw_from_nonstmt(int) |
Expand Down
12 changes: 12 additions & 0 deletions cpp/ql/test/library-tests/syntax-zoo/staticlocals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,16 @@ void f2() {
static C c{};
}

template<typename T>
struct Sizeof {
enum sizeof_enum { value = sizeof(T) };
};

template<typename T>
void f3() {
static int i = Sizeof<T>::value;
}

template void f3<int>();

}
6 changes: 3 additions & 3 deletions cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL |
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL |
| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL |
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL | |
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL | |
| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL | |
10 changes: 9 additions & 1 deletion cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import Compare

string describeTemplate(ControlFlowNode node) {
node.isFromTemplateInstantiation(_) and
result = "instantiation"
or
node.isFromUninstantiatedTemplate(_) and
result = "uninstantiated"
}

from ControlFlowNode n1, ControlFlowNode n2, string msg
where differentEdge(n1, n2, msg)
select getScopeName(n1), n1, n2, msg
select getScopeName(n1), n1, n2, msg, concat(describeTemplate(n1), ", ")
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ instructionWithoutSuccessor
| ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C |
| ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C |
| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C |
| pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} |
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
Expand Down