mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge pull request #1959 from jbj/const-pmf
C++: Classify more expressions as constant
This commit is contained in:
@@ -131,6 +131,8 @@ class Expr extends StmtParent, @expr {
|
||||
valuebind(_, underlyingElement(this))
|
||||
or
|
||||
addressConstantExpression(this)
|
||||
or
|
||||
constantTemplateLiteral(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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,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) |
|
||||
@@ -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 *)... |
|
||||
@@ -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) |
|
||||
|
||||
@@ -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>();
|
||||
|
||||
}
|
||||
|
||||
@@ -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 | |
|
||||
|
||||
@@ -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), ", ")
|
||||
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user