I’m trying to write a custom checker that would look for transaction objects being created and used, and would issue a warning when the success of the transaction was not checked after commit.
I’m using checkPreCall, and I can successfully find when a transaction object is constructed, and I add the tracking information, based on what I’ve seen in StreamChecker.cpp:
if(call.getKind() == CE_CXXConstructor)
auto callExpr = static_cast<const CallExpr*>(call.getOriginExpr());
SValBuilder& svalBuilder = context.getSValBuilder();
const LocationContext* locationContext = context.getPredecessor()->getLocationContext();
DefinedSVal createdTransactionObjVal = llvm::cast(svalBuilder.conjureSymbolVal(0, callExpr, locationContext, context.blockCount()));
programState = programState->BindExpr(callExpr, context.getLocationContext(), createdTransactionObjVal);
if(SymbolRef createdTransactionObjSymbol = createdTransactionObjVal.getAsSymbol())
programState = programState->set(createdTransactionObjSymbol, TransactionState());
So first, is there any easier way to access the symbolic value that is created as the result of the constructor running? This seems like an awfully complicated way of doing a simple task.
Next, my problem is with detecting when members of the transaction object is called. I was trying to get the SymbolRef of the object whose member is called:
const CXXInstanceCall* instanceCall = llvm::dyn_cast(&call);
SymbolRef transactionObjectSymbol = instanceCall->getCXXThisVal().getAsSymbol();
But I find that this SymbolRef is always NULL. Why is that?
I also tried to work around with this:
SymbolRef transactionObjectSymbol = programState->getSVal(static_cast<const CXXMemberCallExpr*>(instanceCall->getOriginExpr())->getImplicitObjectArgument(), context.getLocationContext()).getAsSymbol();
But this doesn’t work either.
What am I doing wrong?