1219069Sdim//== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=// 2219069Sdim// 3219069Sdim// The LLVM Compiler Infrastructure 4219069Sdim// 5219069Sdim// This file is distributed under the University of Illinois Open Source 6219069Sdim// License. See LICENSE.TXT for details. 7219069Sdim// 8219069Sdim//===----------------------------------------------------------------------===// 9219069Sdim// 10219069Sdim// This file defines CheckerContext that provides contextual info for 11219069Sdim// path-sensitive checkers. 12219069Sdim// 13219069Sdim//===----------------------------------------------------------------------===// 14219069Sdim 15219069Sdim#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT 16219069Sdim#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT 17219069Sdim 18219069Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 19243830Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 20219069Sdim 21219069Sdimnamespace clang { 22219069Sdimnamespace ento { 23219069Sdim 24243830Sdim /// Declares an immutable map of type \p NameTy, suitable for placement into 25243830Sdim /// the ProgramState. This is implementing using llvm::ImmutableMap. 26243830Sdim /// 27243830Sdim /// \code 28243830Sdim /// State = State->set<Name>(K, V); 29243830Sdim /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map. 30243830Sdim /// State = State->remove<Name>(K); 31243830Sdim /// NameTy Map = State->get<Name>(); 32243830Sdim /// \endcode 33243830Sdim /// 34243830Sdim /// The macro should not be used inside namespaces, or for traits that must 35243830Sdim /// be accessible from more than one translation unit. 36243830Sdim #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \ 37243830Sdim REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \ 38243830Sdim CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)) 39243830Sdim 40243830Sdim /// Declares an immutable set of type \p NameTy, suitable for placement into 41243830Sdim /// the ProgramState. This is implementing using llvm::ImmutableSet. 42243830Sdim /// 43243830Sdim /// \code 44243830Sdim /// State = State->add<Name>(E); 45243830Sdim /// State = State->remove<Name>(E); 46243830Sdim /// bool Present = State->contains<Name>(E); 47243830Sdim /// NameTy Set = State->get<Name>(); 48243830Sdim /// \endcode 49243830Sdim /// 50243830Sdim /// The macro should not be used inside namespaces, or for traits that must 51243830Sdim /// be accessible from more than one translation unit. 52243830Sdim #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \ 53243830Sdim REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>) 54243830Sdim 55243830Sdim /// Declares an immutable list of type \p NameTy, suitable for placement into 56243830Sdim /// the ProgramState. This is implementing using llvm::ImmutableList. 57243830Sdim /// 58243830Sdim /// \code 59243830Sdim /// State = State->add<Name>(E); // Adds to the /end/ of the list. 60243830Sdim /// bool Present = State->contains<Name>(E); 61243830Sdim /// NameTy List = State->get<Name>(); 62243830Sdim /// \endcode 63243830Sdim /// 64243830Sdim /// The macro should not be used inside namespaces, or for traits that must 65243830Sdim /// be accessible from more than one translation unit. 66243830Sdim #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \ 67243830Sdim REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>) 68243830Sdim 69243830Sdim 70219069Sdimclass CheckerContext { 71219069Sdim ExprEngine &Eng; 72234353Sdim /// The current exploded(symbolic execution) graph node. 73219069Sdim ExplodedNode *Pred; 74234353Sdim /// The flag is true if the (state of the execution) has been modified 75234353Sdim /// by the checker using this context. For example, a new transition has been 76234353Sdim /// added or a bug report issued. 77234353Sdim bool Changed; 78234353Sdim /// The tagged location, which is used to generate all new nodes. 79226633Sdim const ProgramPoint Location; 80234353Sdim NodeBuilder &NB; 81234353Sdim 82219069Sdimpublic: 83234353Sdim /// If we are post visiting a call, this flag will be set if the 84234353Sdim /// call was inlined. In all other cases it will be false. 85234353Sdim const bool wasInlined; 86234353Sdim 87234353Sdim CheckerContext(NodeBuilder &builder, 88226633Sdim ExprEngine &eng, 89226633Sdim ExplodedNode *pred, 90226633Sdim const ProgramPoint &loc, 91234353Sdim bool wasInlined = false) 92234353Sdim : Eng(eng), 93226633Sdim Pred(pred), 94234353Sdim Changed(false), 95226633Sdim Location(loc), 96234353Sdim NB(builder), 97234353Sdim wasInlined(wasInlined) { 98234353Sdim assert(Pred->getState() && 99234353Sdim "We should not call the checkers on an empty state."); 100219069Sdim } 101219069Sdim 102219069Sdim AnalysisManager &getAnalysisManager() { 103219069Sdim return Eng.getAnalysisManager(); 104219069Sdim } 105219069Sdim 106219069Sdim ConstraintManager &getConstraintManager() { 107219069Sdim return Eng.getConstraintManager(); 108219069Sdim } 109219069Sdim 110219069Sdim StoreManager &getStoreManager() { 111219069Sdim return Eng.getStoreManager(); 112219069Sdim } 113243830Sdim 114234353Sdim /// \brief Returns the previous node in the exploded graph, which includes 115234353Sdim /// the state of the program before the checker ran. Note, checkers should 116234353Sdim /// not retain the node in their state since the nodes might get invalidated. 117234353Sdim ExplodedNode *getPredecessor() { return Pred; } 118249423Sdim const ProgramStateRef &getState() const { return Pred->getState(); } 119219069Sdim 120234353Sdim /// \brief Check if the checker changed the state of the execution; ex: added 121234353Sdim /// a new transition or a bug report. 122234353Sdim bool isDifferent() { return Changed; } 123234353Sdim 124226633Sdim /// \brief Returns the number of times the current block has been visited 125226633Sdim /// along the analyzed path. 126243830Sdim unsigned blockCount() const { 127243830Sdim return NB.getContext().blockCount(); 128234353Sdim } 129226633Sdim 130219069Sdim ASTContext &getASTContext() { 131219069Sdim return Eng.getContext(); 132219069Sdim } 133234353Sdim 134234353Sdim const LangOptions &getLangOpts() const { 135234353Sdim return Eng.getContext().getLangOpts(); 136234353Sdim } 137234353Sdim 138234353Sdim const LocationContext *getLocationContext() const { 139234353Sdim return Pred->getLocationContext(); 140234353Sdim } 141234353Sdim 142239462Sdim const StackFrameContext *getStackFrame() const { 143239462Sdim return Pred->getStackFrame(); 144239462Sdim } 145239462Sdim 146243830Sdim /// Return true if the current LocationContext has no caller context. 147243830Sdim bool inTopFrame() const { return getLocationContext()->inTopFrame(); } 148243830Sdim 149219069Sdim BugReporter &getBugReporter() { 150219069Sdim return Eng.getBugReporter(); 151219069Sdim } 152219069Sdim 153219069Sdim SourceManager &getSourceManager() { 154219069Sdim return getBugReporter().getSourceManager(); 155219069Sdim } 156219069Sdim 157219069Sdim SValBuilder &getSValBuilder() { 158219069Sdim return Eng.getSValBuilder(); 159219069Sdim } 160219069Sdim 161226633Sdim SymbolManager &getSymbolManager() { 162226633Sdim return getSValBuilder().getSymbolManager(); 163226633Sdim } 164226633Sdim 165234353Sdim bool isObjCGCEnabled() const { 166226633Sdim return Eng.isObjCGCEnabled(); 167226633Sdim } 168226633Sdim 169234353Sdim ProgramStateManager &getStateManager() { 170234353Sdim return Eng.getStateManager(); 171219069Sdim } 172234353Sdim 173234353Sdim AnalysisDeclContext *getCurrentAnalysisDeclContext() const { 174234353Sdim return Pred->getLocationContext()->getAnalysisDeclContext(); 175219069Sdim } 176219069Sdim 177234353Sdim /// \brief If the given node corresponds to a PostStore program point, retrieve 178234353Sdim /// the location region as it was uttered in the code. 179234353Sdim /// 180234353Sdim /// This utility can be useful for generating extensive diagnostics, for 181234353Sdim /// example, for finding variables that the given symbol was assigned to. 182234353Sdim static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) { 183234353Sdim ProgramPoint L = N->getLocation(); 184249423Sdim if (Optional<PostStore> PSL = L.getAs<PostStore>()) 185234353Sdim return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); 186234353Sdim return 0; 187219069Sdim } 188219069Sdim 189239462Sdim /// \brief Get the value of arbitrary expressions at this point in the path. 190239462Sdim SVal getSVal(const Stmt *S) const { 191239462Sdim return getState()->getSVal(S, getLocationContext()); 192239462Sdim } 193239462Sdim 194234353Sdim /// \brief Generates a new transition in the program state graph 195234353Sdim /// (ExplodedGraph). Uses the default CheckerContext predecessor node. 196234353Sdim /// 197243830Sdim /// @param State The state of the generated node. If not specified, the state 198243830Sdim /// will not be changed, but the new node will have the checker's tag. 199234353Sdim /// @param Tag The tag is used to uniquely identify the creation site. If no 200234353Sdim /// tag is specified, a default tag, unique to the given checker, 201234353Sdim /// will be used. Tags are used to prevent states generated at 202234353Sdim /// different sites from caching out. 203243830Sdim ExplodedNode *addTransition(ProgramStateRef State = 0, 204234353Sdim const ProgramPointTag *Tag = 0) { 205243830Sdim return addTransitionImpl(State ? State : getState(), false, 0, Tag); 206219069Sdim } 207219069Sdim 208234353Sdim /// \brief Generates a new transition with the given predecessor. 209234353Sdim /// Allows checkers to generate a chain of nodes. 210234353Sdim /// 211234353Sdim /// @param State The state of the generated node. 212234353Sdim /// @param Pred The transition will be generated from the specified Pred node 213234353Sdim /// to the newly generated node. 214234353Sdim /// @param Tag The tag to uniquely identify the creation site. 215234353Sdim ExplodedNode *addTransition(ProgramStateRef State, 216243830Sdim ExplodedNode *Pred, 217243830Sdim const ProgramPointTag *Tag = 0) { 218243830Sdim return addTransitionImpl(State, false, Pred, Tag); 219219069Sdim } 220219069Sdim 221243830Sdim /// \brief Generate a sink node. Generating a sink stops exploration of the 222234353Sdim /// given path. 223243830Sdim ExplodedNode *generateSink(ProgramStateRef State = 0, 224243830Sdim ExplodedNode *Pred = 0, 225243830Sdim const ProgramPointTag *Tag = 0) { 226243830Sdim return addTransitionImpl(State ? State : getState(), true, Pred, Tag); 227234353Sdim } 228234353Sdim 229234353Sdim /// \brief Emit the diagnostics report. 230243830Sdim void emitReport(BugReport *R) { 231234353Sdim Changed = true; 232243830Sdim Eng.getBugReporter().emitReport(R); 233219069Sdim } 234219069Sdim 235234353Sdim /// \brief Get the declaration of the called function (path-sensitive). 236234353Sdim const FunctionDecl *getCalleeDecl(const CallExpr *CE) const; 237234353Sdim 238234353Sdim /// \brief Get the name of the called function (path-sensitive). 239234353Sdim StringRef getCalleeName(const FunctionDecl *FunDecl) const; 240234353Sdim 241243830Sdim /// \brief Get the identifier of the called function (path-sensitive). 242243830Sdim const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const { 243243830Sdim const FunctionDecl *FunDecl = getCalleeDecl(CE); 244243830Sdim if (FunDecl) 245243830Sdim return FunDecl->getIdentifier(); 246243830Sdim else 247243830Sdim return 0; 248243830Sdim } 249243830Sdim 250234353Sdim /// \brief Get the name of the called function (path-sensitive). 251234353Sdim StringRef getCalleeName(const CallExpr *CE) const { 252234353Sdim const FunctionDecl *FunDecl = getCalleeDecl(CE); 253234353Sdim return getCalleeName(FunDecl); 254219069Sdim } 255219069Sdim 256243830Sdim /// \brief Returns true if the callee is an externally-visible function in the 257243830Sdim /// top-level namespace, such as \c malloc. 258243830Sdim /// 259243830Sdim /// If a name is provided, the function must additionally match the given 260243830Sdim /// name. 261243830Sdim /// 262243830Sdim /// Note that this deliberately excludes C++ library functions in the \c std 263243830Sdim /// namespace, but will include C library functions accessed through the 264243830Sdim /// \c std namespace. This also does not check if the function is declared 265243830Sdim /// as 'extern "C"', or if it uses C++ name mangling. 266243830Sdim static bool isCLibraryFunction(const FunctionDecl *FD, 267243830Sdim StringRef Name = StringRef()); 268234353Sdim 269234353Sdim /// \brief Depending on wither the location corresponds to a macro, return 270234353Sdim /// either the macro name or the token spelling. 271234353Sdim /// 272234353Sdim /// This could be useful when checkers' logic depends on whether a function 273234353Sdim /// is called with a given macro argument. For example: 274234353Sdim /// s = socket(AF_INET,..) 275234353Sdim /// If AF_INET is a macro, the result should be treated as a source of taint. 276234353Sdim /// 277234353Sdim /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName(). 278234353Sdim StringRef getMacroNameOrSpelling(SourceLocation &Loc); 279234353Sdim 280219069Sdimprivate: 281234353Sdim ExplodedNode *addTransitionImpl(ProgramStateRef State, 282234353Sdim bool MarkAsSink, 283234353Sdim ExplodedNode *P = 0, 284234353Sdim const ProgramPointTag *Tag = 0) { 285234353Sdim if (!State || (State == Pred->getState() && !Tag && !MarkAsSink)) 286234353Sdim return Pred; 287219069Sdim 288234353Sdim Changed = true; 289243830Sdim const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); 290243830Sdim if (!P) 291243830Sdim P = Pred; 292243830Sdim 293243830Sdim ExplodedNode *node; 294243830Sdim if (MarkAsSink) 295243830Sdim node = NB.generateSink(LocalLoc, State, P); 296243830Sdim else 297243830Sdim node = NB.generateNode(LocalLoc, State, P); 298219069Sdim return node; 299219069Sdim } 300219069Sdim}; 301219069Sdim 302219069Sdim} // end GR namespace 303219069Sdim 304219069Sdim} // end clang namespace 305219069Sdim 306219069Sdim#endif 307