diff options
author | Chris Lattner <sabre@nondot.org> | 2004-02-20 20:27:11 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-02-20 20:27:11 +0000 |
commit | 8ecc27e66750077724539a02b5c20d8b942a8e50 (patch) | |
tree | 4a75c0a1b852a8b759a2d37c01df0f9d63eacd5d /lib/Analysis/DataStructure | |
parent | 3da125839d61e0bb603b56965ac026380ded42b0 (diff) |
Add support for some string functions, the scanf family, and sprintf
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11673 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/DataStructure')
-rw-r--r-- | lib/Analysis/DataStructure/Local.cpp | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp index 28bbef23f2..a3a0e2ebc6 100644 --- a/lib/Analysis/DataStructure/Local.cpp +++ b/lib/Analysis/DataStructure/Local.cpp @@ -484,7 +484,7 @@ void GraphBuilder::visitCallSite(CallSite CS) { if (DSNode *N = RetNH.getNode()) N->setHeapNodeMarker()->setModifiedMarker()->setReadMarker(); return; - } else if (F->getName() == "atoi") { + } else if (F->getName() == "atoi" || F->getName() == "atof") { // atoi reads its argument. if (DSNode *N = getValueDest(**CS.arg_begin()).getNode()) N->setReadMarker(); @@ -549,7 +549,8 @@ void GraphBuilder::visitCallSite(CallSite CS) { if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) H.getNode()->mergeTypeInfo(PTy->getElementType(), H.getOffset()); return; - } else if (F->getName() == "printf" || F->getName() == "fprintf") { + } else if (F->getName() == "printf" || F->getName() == "fprintf" || + F->getName() == "sprintf") { CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); if (F->getName() == "fprintf") { @@ -562,6 +563,16 @@ void GraphBuilder::visitCallSite(CallSite CS) { if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); } + } else if (F->getName() == "sprintf") { + // sprintf writes the first string argument. + DSNodeHandle H = getValueDest(**AI++); + if (DSNode *N = H.getNode()) { + N->setModifiedMarker(); + const Type *ArgTy = (*AI)->getType(); + if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) + N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); + } + } for (; AI != E; ++AI) { @@ -570,9 +581,60 @@ void GraphBuilder::visitCallSite(CallSite CS) { if (DSNode *N = getValueDest(**AI).getNode()) N->setReadMarker(); } + } else if (F->getName() == "scanf" || F->getName() == "fscanf" || + F->getName() == "sscanf") { + CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end(); + + if (F->getName() == "fscanf") { + // fscanf reads and writes the FILE argument, and applies the type + // to it. + DSNodeHandle H = getValueDest(**AI); + if (DSNode *N = H.getNode()) { + N->setReadMarker(); + const Type *ArgTy = (*AI)->getType(); + if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) + N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); + } + } else if (F->getName() == "sscanf") { + // sscanf reads the first string argument. + DSNodeHandle H = getValueDest(**AI++); + if (DSNode *N = H.getNode()) { + N->setReadMarker(); + const Type *ArgTy = (*AI)->getType(); + if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) + N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); + } + } + + for (; AI != E; ++AI) { + // scanf writes all pointer arguments. + if (isPointerType((*AI)->getType())) + if (DSNode *N = getValueDest(**AI).getNode()) + N->setModifiedMarker(); + } + } else if (F->getName() == "strtok") { + // strtok reads and writes the first argument, returning it. It reads + // its second arg. FIXME: strtok also modifies some hidden static + // data. Someday this might matter. + CallSite::arg_iterator AI = CS.arg_begin(); + DSNodeHandle H = getValueDest(**AI++); + if (DSNode *N = H.getNode()) { + N->setReadMarker()->setModifiedMarker(); // Reads/Writes buffer + const Type *ArgTy = F->getFunctionType()->getParamType(0); + if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) + N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); + } + H.mergeWith(getValueDest(*CS.getInstruction())); // Returns buffer + + H = getValueDest(**AI); // Reads delimiter + if (DSNode *N = H.getNode()) { + N->setReadMarker(); + const Type *ArgTy = F->getFunctionType()->getParamType(1); + if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy)) + N->mergeTypeInfo(PTy->getElementType(), H.getOffset()); + } + return; - } else if (F->getName() == "exit") { - // Nothing to do! } else { // Unknown function, warn if it returns a pointer type or takes a // pointer argument. |