CheckerContext.h revision 5ac1df3e15f91ed663826faec7efe2462c18d98c
16bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=// 26bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// 36bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// The LLVM Compiler Infrastructure 46bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// 56bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source 66bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// License. See LICENSE.TXT for details. 76bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// 86bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 96bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// 106bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// This file defines CheckerContext that provides contextual info for 116bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// path-sensitive checkers. 126bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis// 136bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 146bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 156bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT 166bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT 176bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 186bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 195ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks#include "llvm/ADT/ImmutableMap.h" 205ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks 215ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks// Declare an immutable map suitable for placement into program states's GDM. 225ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks#define REGISTER_MAP_WITH_GDM(Map, Key, Value) \ 235ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks typedef llvm::ImmutableMap<Key, Value> Map; \ 245ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks namespace clang { \ 255ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks namespace ento { \ 265ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks template <> \ 275ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks struct ProgramStateTrait<Map> \ 285ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks : public ProgramStatePartialTrait<Map> { \ 295ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks static void *GDMIndex() { static int Index; return &Index; } \ 305ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks }; \ 315ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks } \ 325ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks } 335ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks 346bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 356bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisnamespace clang { 366bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisnamespace ento { 376bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 386bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisclass CheckerContext { 396bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis ExprEngine &Eng; 4057300760964904cc022a175643342f29f46b7e6bAnna Zaks /// The current exploded(symbolic execution) graph node. 416bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis ExplodedNode *Pred; 4257300760964904cc022a175643342f29f46b7e6bAnna Zaks /// The flag is true if the (state of the execution) has been modified 4357300760964904cc022a175643342f29f46b7e6bAnna Zaks /// by the checker using this context. For example, a new transition has been 4457300760964904cc022a175643342f29f46b7e6bAnna Zaks /// added or a bug report issued. 4557300760964904cc022a175643342f29f46b7e6bAnna Zaks bool Changed; 4657300760964904cc022a175643342f29f46b7e6bAnna Zaks /// The tagged location, which is used to generate all new nodes. 473f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks const ProgramPoint Location; 483152b3cb5b6a2f797d0972c81a5eb3fd69c0d620Anna Zaks NodeBuilder &NB; 49063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks 506bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidispublic: 51514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek /// If we are post visiting a call, this flag will be set if the 52514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek /// call was inlined. In all other cases it will be false. 53514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek const bool wasInlined; 54514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek 558ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks CheckerContext(NodeBuilder &builder, 5618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ExprEngine &eng, 5718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek ExplodedNode *pred, 58514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek const ProgramPoint &loc, 59514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek bool wasInlined = false) 608ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks : Eng(eng), 6118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek Pred(pred), 6257300760964904cc022a175643342f29f46b7e6bAnna Zaks Changed(false), 633f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks Location(loc), 64514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek NB(builder), 65514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek wasInlined(wasInlined) { 66777d706547ebc751d998134774d9d5388fff8e02Anna Zaks assert(Pred->getState() && 67777d706547ebc751d998134774d9d5388fff8e02Anna Zaks "We should not call the checkers on an empty state."); 68777d706547ebc751d998134774d9d5388fff8e02Anna Zaks } 696bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 706bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis AnalysisManager &getAnalysisManager() { 716bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return Eng.getAnalysisManager(); 726bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 736bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 746bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis ConstraintManager &getConstraintManager() { 756bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return Eng.getConstraintManager(); 766bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 776bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 786bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis StoreManager &getStoreManager() { 796bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return Eng.getStoreManager(); 806bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 816bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 82255d4d4226b24036ceb11228fbb74286e58620f7Ted Kremenek const AnalyzerOptions::ConfigTable &getConfig() const { 83255d4d4226b24036ceb11228fbb74286e58620f7Ted Kremenek return Eng.getAnalysisManager().options.Config; 847b73e0832b20af1f43601a3d19e76d02d9f4dce5Ted Kremenek } 857b73e0832b20af1f43601a3d19e76d02d9f4dce5Ted Kremenek 86a2a860306e3697fcf7a12c5ba59551ca60578968Anna Zaks /// \brief Returns the previous node in the exploded graph, which includes 87a2a860306e3697fcf7a12c5ba59551ca60578968Anna Zaks /// the state of the program before the checker ran. Note, checkers should 88a2a860306e3697fcf7a12c5ba59551ca60578968Anna Zaks /// not retain the node in their state since the nodes might get invalidated. 8939ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks ExplodedNode *getPredecessor() { return Pred; } 908bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef getState() const { return Pred->getState(); } 916bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 9257300760964904cc022a175643342f29f46b7e6bAnna Zaks /// \brief Check if the checker changed the state of the execution; ex: added 9357300760964904cc022a175643342f29f46b7e6bAnna Zaks /// a new transition or a bug report. 9457300760964904cc022a175643342f29f46b7e6bAnna Zaks bool isDifferent() { return Changed; } 9557300760964904cc022a175643342f29f46b7e6bAnna Zaks 965d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks /// \brief Returns the number of times the current block has been visited 975d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks /// along the analyzed path. 9866c486f275531df6362b3511fc3af6563561801bTed Kremenek unsigned blockCount() const { 9966c486f275531df6362b3511fc3af6563561801bTed Kremenek return NB.getContext().blockCount(); 100ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks } 1015d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks 1026bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis ASTContext &getASTContext() { 1036bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return Eng.getContext(); 1046bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 105461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks 1064e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const LangOptions &getLangOpts() const { 1074e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie return Eng.getContext().getLangOpts(); 108461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks } 109461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks 110eeea7c44a6986752fedee1ef1bcef855db373872Anna Zaks const LocationContext *getLocationContext() const { 11139ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks return Pred->getLocationContext(); 11239ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks } 11339ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks 114955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks const StackFrameContext *getStackFrame() const { 115955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks return Pred->getStackFrame(); 116c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 117c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 11805fcbd3dc28f4cba4a6d33e7aeaabb5f6f7837e3Anna Zaks /// Returns true if the predecessor is within an inlined function/method. 11905fcbd3dc28f4cba4a6d33e7aeaabb5f6f7837e3Anna Zaks bool isWithinInlined() { 120dc601f4a9f69315521abddbca04d4652deee5fdbAnna Zaks return (getStackFrame()->getParent() != 0); 12105fcbd3dc28f4cba4a6d33e7aeaabb5f6f7837e3Anna Zaks } 12205fcbd3dc28f4cba4a6d33e7aeaabb5f6f7837e3Anna Zaks 1236bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis BugReporter &getBugReporter() { 1246bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return Eng.getBugReporter(); 1256bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 1266bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 1276bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis SourceManager &getSourceManager() { 1286bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return getBugReporter().getSourceManager(); 1296bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 1306bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 1316bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis SValBuilder &getSValBuilder() { 1326bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return Eng.getSValBuilder(); 1336bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 1346bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 1353f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks SymbolManager &getSymbolManager() { 1363f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks return getSValBuilder().getSymbolManager(); 1373f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks } 1383f10e32b15e54f507aed90cb72d73c7acaa500bbAnna Zaks 139eeea7c44a6986752fedee1ef1bcef855db373872Anna Zaks bool isObjCGCEnabled() const { 14017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose return Eng.isObjCGCEnabled(); 14117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose } 14217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 1436a93bd526c5136ee5a26871e829cf5a8548a1c6aAnna Zaks ProgramStateManager &getStateManager() { 1446a93bd526c5136ee5a26871e829cf5a8548a1c6aAnna Zaks return Eng.getStateManager(); 1456a93bd526c5136ee5a26871e829cf5a8548a1c6aAnna Zaks } 1466a93bd526c5136ee5a26871e829cf5a8548a1c6aAnna Zaks 147063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks AnalysisDeclContext *getCurrentAnalysisDeclContext() const { 148063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks return Pred->getLocationContext()->getAnalysisDeclContext(); 149063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks } 150063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks 1513d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks /// \brief If the given node corresponds to a PostStore program point, retrieve 1523d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks /// the location region as it was uttered in the code. 1533d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks /// 1543d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks /// This utility can be useful for generating extensive diagnostics, for 1553d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks /// example, for finding variables that the given symbol was assigned to. 1563d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) { 1573d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks ProgramPoint L = N->getLocation(); 1583d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks if (const PostStore *PSL = dyn_cast<PostStore>(&L)) 1593d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); 1603d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks return 0; 1613d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks } 1623d7c44e01d568e5d5c0fac9c6ccb3f080157ba19Anna Zaks 163c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks /// \brief Get the value of arbitrary expressions at this point in the path. 164c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks SVal getSVal(const Stmt *S) const { 165c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return getState()->getSVal(S, getLocationContext()); 166c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 167c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 1680bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// \brief Generates a new transition in the program state graph 1690bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// (ExplodedGraph). Uses the default CheckerContext predecessor node. 1700bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// 171fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// @param State The state of the generated node. If not specified, the state 172fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// will not be changed, but the new node will have the checker's tag. 1730bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// @param Tag The tag is used to uniquely identify the creation site. If no 1740bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// tag is specified, a default tag, unique to the given checker, 1750bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// will be used. Tags are used to prevent states generated at 1760bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// different sites from caching out. 177fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose ExplodedNode *addTransition(ProgramStateRef State = 0, 1780bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks const ProgramPointTag *Tag = 0) { 179fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose return addTransitionImpl(State ? State : getState(), false, 0, Tag); 180063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks } 181063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks 1820bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// \brief Generates a new transition with the given predecessor. 1838ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks /// Allows checkers to generate a chain of nodes. 1840bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// 1850bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// @param State The state of the generated node. 1860bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// @param Pred The transition will be generated from the specified Pred node 1870bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// to the newly generated node. 1880bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks /// @param Tag The tag to uniquely identify the creation site. 1898bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ExplodedNode *addTransition(ProgramStateRef State, 190fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose ExplodedNode *Pred, 191fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose const ProgramPointTag *Tag = 0) { 192fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose return addTransitionImpl(State, false, Pred, Tag); 1936bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 1946bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 195fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// \brief Generate a sink node. Generating a sink stops exploration of the 1968ba721428af297e540fb40b176eeeea0ee010c1fAnna Zaks /// given path. 197fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose ExplodedNode *generateSink(ProgramStateRef State = 0, 198fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose ExplodedNode *Pred = 0, 199fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose const ProgramPointTag *Tag = 0) { 200fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose return addTransitionImpl(State ? State : getState(), true, Pred, Tag); 2016bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 2026bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 203063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks /// \brief Emit the diagnostics report. 2046bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis void EmitReport(BugReport *R) { 20557300760964904cc022a175643342f29f46b7e6bAnna Zaks Changed = true; 2066bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis Eng.getBugReporter().EmitReport(R); 2076bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 2086bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 209b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks /// \brief Get the declaration of the called function (path-sensitive). 210b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks const FunctionDecl *getCalleeDecl(const CallExpr *CE) const; 211b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks 2120e12ebfd3ef9ad5d894466c6e4910ac5e6041034Anna Zaks /// \brief Get the name of the called function (path-sensitive). 2139b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks StringRef getCalleeName(const FunctionDecl *FunDecl) const; 2149b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2155ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks /// \brief Get the identifier of the called function (path-sensitive). 2165ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const { 2175ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks const FunctionDecl *FunDecl = getCalleeDecl(CE); 2185ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks if (FunDecl) 2195ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks return FunDecl->getIdentifier(); 2205ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks else 2215ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks return 0; 2225ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks } 2235ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks 2249b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks /// \brief Get the name of the called function (path-sensitive). 2259b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks StringRef getCalleeName(const CallExpr *CE) const { 2269b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks const FunctionDecl *FunDecl = getCalleeDecl(CE); 2279b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks return getCalleeName(FunDecl); 2289b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks } 2299b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks 2309b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks /// Given a function declaration and a name checks if this is a C lib 2319b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks /// function with the given name. 2329b0c749a20d0f7d0e63441d76baa15def3f37fdbAnna Zaks bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name); 233e00575f12cf280621ef0ed4d69e909bdfc9fef62Anna Zaks static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name, 234e00575f12cf280621ef0ed4d69e909bdfc9fef62Anna Zaks ASTContext &Context); 2350e12ebfd3ef9ad5d894466c6e4910ac5e6041034Anna Zaks 236461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// \brief Depending on wither the location corresponds to a macro, return 237461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// either the macro name or the token spelling. 238461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// 239461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// This could be useful when checkers' logic depends on whether a function 240461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// is called with a given macro argument. For example: 241461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// s = socket(AF_INET,..) 242461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// If AF_INET is a macro, the result should be treated as a source of taint. 243461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// 244461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName(). 245461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks StringRef getMacroNameOrSpelling(SourceLocation &Loc); 246461af1e502c9bd88330bbf17d449a7593fc0d624Anna Zaks 2476bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidisprivate: 2488bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ExplodedNode *addTransitionImpl(ProgramStateRef State, 24939ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks bool MarkAsSink, 25039ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks ExplodedNode *P = 0, 25139ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks const ProgramPointTag *Tag = 0) { 252c8bb3befcad8cd8fc9556bc265289b07dc3c94c8Anna Zaks if (!State || (State == Pred->getState() && !Tag && !MarkAsSink)) 253df95d146c13cf02e106b32b01d147577d6d6b5a1Anna Zaks return Pred; 254df95d146c13cf02e106b32b01d147577d6d6b5a1Anna Zaks 25557300760964904cc022a175643342f29f46b7e6bAnna Zaks Changed = true; 256fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); 257fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose if (!P) 258fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose P = Pred; 259fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose 260fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose ExplodedNode *node; 261fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose if (MarkAsSink) 262fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose node = NB.generateSink(LocalLoc, State, P); 263fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose else 264fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose node = NB.generateNode(LocalLoc, State, P); 2656bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis return node; 2666bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis } 2676bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis}; 2686bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 26957300760964904cc022a175643342f29f46b7e6bAnna Zaks/// \brief A helper class which wraps a boolean value set to false by default. 27057300760964904cc022a175643342f29f46b7e6bAnna Zaksstruct DefaultBool { 27157300760964904cc022a175643342f29f46b7e6bAnna Zaks bool Val; 27257300760964904cc022a175643342f29f46b7e6bAnna Zaks DefaultBool() : Val(false) {} 27357300760964904cc022a175643342f29f46b7e6bAnna Zaks operator bool() const { return Val; } 27457300760964904cc022a175643342f29f46b7e6bAnna Zaks DefaultBool &operator=(bool b) { Val = b; return *this; } 27557300760964904cc022a175643342f29f46b7e6bAnna Zaks}; 27657300760964904cc022a175643342f29f46b7e6bAnna Zaks 2776bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis} // end GR namespace 2786bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 2796bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis} // end clang namespace 2806bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis 2816bcb48dc67e417e0ecce803f28d13bbea2ee0243Argyrios Kyrtzidis#endif 282