Hello everyone, I hope this is the proper platform for my questions.
I am currently working with the Clang Static Analyser and have a question regarding the checkLocation callback.
This callback function is generally triggered for LValueToRValue casts.
The following code example triggers the checkBind (for the LHS) callback but not the checkLocation (for the RHS):
template <typename T> class MyClass {
private:
T Value;
public:
explicit MyClass(T &&Val = T{}) : Value{Val} {}
T &getValue() { return Value; }
};
MyClass<int> IntIn{3};
MyClass<int> IntOut;
int test_main_cpp() {
IntOut = IntIn;
return 0;
}
When looking at the AST, this also makes sense, as the cast involved here is a NoOp cast:
`-FunctionDecl 0x55a07fade998 <line:40:1, line:45:1> line:40:5 test_main_cpp 'int ()'
`-CompoundStmt 0x55a07fadfdc0 <col:21, line:45:1>
|-CXXOperatorCallExpr 0x55a07fadfd58 <line:42:3, col:12> 'MyClass<int>' lvalue '='
| |-ImplicitCastExpr 0x55a07fadfd40 <col:10> 'MyClass<int> &(*)(const MyClass<int> &) noexcept' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x55a07fadfb18 <col:10> 'MyClass<int> &(const MyClass<int> &) noexcept' lvalue CXXMethod 0x55a07fadf7b0 'operator=' 'MyClass<int> &(const MyClass<int> &) noexcept'
| |-DeclRefExpr 0x55a07fadea40 <col:3> 'MyClass<int>' lvalue Var 0x55a07fade700 'IntOut' 'MyClass<int>'
| `-ImplicitCastExpr 0x55a07fadfb00 <col:12> 'const MyClass<int>' lvalue <NoOp>
| `-DeclRefExpr 0x55a07fadea60 <col:12> 'MyClass<int>' lvalue Var 0x55a07fabb6c0 'IntIn' 'MyClass<int>'
`-ReturnStmt 0x55a07fadfdb0 <line:44:3, col:10>
`-IntegerLiteral 0x55a07fadfd90 <col:10> 'int' 0
As can be seen in the ExprEgnine, evalLocation (and subsequently checkLcoation) is only triggered for LValueToRValue cast.
void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
ExplodedNodeSet dstPreStmt;
getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
if (CastE->getCastKind() == CK_LValueToRValue ||
CastE->getCastKind() == CK_LValueToRValueBitCast) {
for (ExplodedNode *subExprNode : dstPreStmt) {
ProgramStateRef state = subExprNode->getState();
const LocationContext *LCtx = subExprNode->getLocationContext();
evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx));
}
return;
}
...
Should corresponding casts like the NoOp shown also trigger checkLocation (At least in some cases)? Or am I misunderstanding something here and the implied behaviour is correct?
I would be grateful for any suggestions and answers!