| Ted Kremenek | 77349cb | 2008-02-14 22:13:12 +0000 | [diff] [blame] | 1 | //=-- GRExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-= | 
| Ted Kremenek | 6492485 | 2008-01-31 02:35:41 +0000 | [diff] [blame] | 2 | // | 
| Ted Kremenek | 4af8431 | 2008-01-31 06:49:09 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
| Ted Kremenek | d27f816 | 2008-01-15 23:55:06 +0000 | [diff] [blame] | 4 | // | 
 | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
 | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
| Ted Kremenek | 77349cb | 2008-02-14 22:13:12 +0000 | [diff] [blame] | 10 | //  This file defines a meta-engine for path-sensitive dataflow analysis that | 
 | 11 | //  is built on GREngine, but provides the boilerplate to execute transfer | 
 | 12 | //  functions and build the ExplodedGraph at the expression level. | 
| Ted Kremenek | d27f816 | 2008-01-15 23:55:06 +0000 | [diff] [blame] | 13 | // | 
 | 14 | //===----------------------------------------------------------------------===// | 
 | 15 |  | 
| Ted Kremenek | 77349cb | 2008-02-14 22:13:12 +0000 | [diff] [blame] | 16 | #include "clang/Analysis/PathSensitive/GRExprEngine.h" | 
| Ted Kremenek | 41573eb | 2009-02-14 01:43:44 +0000 | [diff] [blame] | 17 | #include "clang/Analysis/PathSensitive/GRExprEngineBuilders.h" | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 18 | #include "clang/Analysis/PathSensitive/BugReporter.h" | 
| Chris Lattner | 16f0049 | 2009-04-26 01:32:48 +0000 | [diff] [blame] | 19 | #include "clang/AST/ParentMap.h" | 
 | 20 | #include "clang/AST/StmtObjC.h" | 
| Chris Lattner | 1b63e4f | 2009-06-14 01:54:56 +0000 | [diff] [blame] | 21 | #include "clang/Basic/Builtins.h" | 
| Chris Lattner | 16f0049 | 2009-04-26 01:32:48 +0000 | [diff] [blame] | 22 | #include "clang/Basic/SourceManager.h" | 
| Ted Kremenek | e97ca06 | 2008-03-07 20:57:30 +0000 | [diff] [blame] | 23 | #include "clang/Basic/SourceManager.h" | 
| Ted Kremenek | 0bed8a1 | 2009-03-11 02:41:36 +0000 | [diff] [blame] | 24 | #include "clang/Basic/PrettyStackTrace.h" | 
| Ted Kremenek | e01c987 | 2008-02-14 22:36:46 +0000 | [diff] [blame] | 25 | #include "llvm/Support/Streams.h" | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 26 | #include "llvm/ADT/ImmutableList.h" | 
 | 27 | #include "llvm/Support/Compiler.h" | 
| Ted Kremenek | a95d375 | 2008-09-13 05:16:45 +0000 | [diff] [blame] | 28 | #include "llvm/Support/raw_ostream.h" | 
| Ted Kremenek | 4323a57 | 2008-07-10 22:03:41 +0000 | [diff] [blame] | 29 |  | 
| Ted Kremenek | 0f5f059 | 2008-02-27 06:07:00 +0000 | [diff] [blame] | 30 | #ifndef NDEBUG | 
 | 31 | #include "llvm/Support/GraphWriter.h" | 
 | 32 | #include <sstream> | 
 | 33 | #endif | 
 | 34 |  | 
| Ted Kremenek | b387a3f | 2008-02-14 22:16:04 +0000 | [diff] [blame] | 35 | using namespace clang; | 
 | 36 | using llvm::dyn_cast; | 
 | 37 | using llvm::cast; | 
 | 38 | using llvm::APSInt; | 
| Ted Kremenek | ab2b8c5 | 2008-01-23 19:59:44 +0000 | [diff] [blame] | 39 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 40 | //===----------------------------------------------------------------------===// | 
 | 41 | // Engine construction and deletion. | 
 | 42 | //===----------------------------------------------------------------------===// | 
 | 43 |  | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 44 | namespace { | 
 | 45 |  | 
 | 46 | class VISIBILITY_HIDDEN MappedBatchAuditor : public GRSimpleAPICheck { | 
 | 47 |   typedef llvm::ImmutableList<GRSimpleAPICheck*> Checks; | 
 | 48 |   typedef llvm::DenseMap<void*,Checks> MapTy; | 
 | 49 |    | 
 | 50 |   MapTy M; | 
 | 51 |   Checks::Factory F; | 
| Ted Kremenek | 536aa02 | 2009-03-30 17:53:05 +0000 | [diff] [blame] | 52 |   Checks AllStmts; | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 53 |  | 
 | 54 | public: | 
| Ted Kremenek | 536aa02 | 2009-03-30 17:53:05 +0000 | [diff] [blame] | 55 |   MappedBatchAuditor(llvm::BumpPtrAllocator& Alloc) : | 
 | 56 |     F(Alloc), AllStmts(F.GetEmptyList()) {} | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 57 |    | 
 | 58 |   virtual ~MappedBatchAuditor() { | 
 | 59 |     llvm::DenseSet<GRSimpleAPICheck*> AlreadyVisited; | 
 | 60 |      | 
 | 61 |     for (MapTy::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) | 
 | 62 |       for (Checks::iterator I=MI->second.begin(), E=MI->second.end(); I!=E;++I){ | 
 | 63 |  | 
 | 64 |         GRSimpleAPICheck* check = *I; | 
 | 65 |          | 
 | 66 |         if (AlreadyVisited.count(check)) | 
 | 67 |           continue; | 
 | 68 |          | 
 | 69 |         AlreadyVisited.insert(check); | 
 | 70 |         delete check; | 
 | 71 |       } | 
 | 72 |   } | 
 | 73 |  | 
| Ted Kremenek | 536aa02 | 2009-03-30 17:53:05 +0000 | [diff] [blame] | 74 |   void AddCheck(GRSimpleAPICheck *A, Stmt::StmtClass C) { | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 75 |     assert (A && "Check cannot be null."); | 
 | 76 |     void* key = reinterpret_cast<void*>((uintptr_t) C); | 
 | 77 |     MapTy::iterator I = M.find(key); | 
 | 78 |     M[key] = F.Concat(A, I == M.end() ? F.GetEmptyList() : I->second); | 
 | 79 |   } | 
| Ted Kremenek | 536aa02 | 2009-03-30 17:53:05 +0000 | [diff] [blame] | 80 |    | 
 | 81 |   void AddCheck(GRSimpleAPICheck *A) { | 
 | 82 |     assert (A && "Check cannot be null."); | 
 | 83 |     AllStmts = F.Concat(A, AllStmts);     | 
 | 84 |   } | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 85 |  | 
| Ted Kremenek | 4adc81e | 2008-08-13 04:27:00 +0000 | [diff] [blame] | 86 |   virtual bool Audit(NodeTy* N, GRStateManager& VMgr) { | 
| Ted Kremenek | 536aa02 | 2009-03-30 17:53:05 +0000 | [diff] [blame] | 87 |     // First handle the auditors that accept all statements. | 
 | 88 |     bool isSink = false; | 
 | 89 |     for (Checks::iterator I = AllStmts.begin(), E = AllStmts.end(); I!=E; ++I) | 
 | 90 |       isSink |= (*I)->Audit(N, VMgr); | 
 | 91 |      | 
 | 92 |     // Next handle the auditors that accept only specific statements. | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 93 |     Stmt* S = cast<PostStmt>(N->getLocation()).getStmt(); | 
 | 94 |     void* key = reinterpret_cast<void*>((uintptr_t) S->getStmtClass()); | 
 | 95 |     MapTy::iterator MI = M.find(key); | 
| Ted Kremenek | 536aa02 | 2009-03-30 17:53:05 +0000 | [diff] [blame] | 96 |     if (MI != M.end()) {     | 
 | 97 |       for (Checks::iterator I=MI->second.begin(), E=MI->second.end(); I!=E; ++I) | 
 | 98 |         isSink |= (*I)->Audit(N, VMgr); | 
 | 99 |     } | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 100 |      | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 101 |     return isSink;     | 
 | 102 |   } | 
 | 103 | }; | 
 | 104 |  | 
 | 105 | } // end anonymous namespace | 
 | 106 |  | 
 | 107 | //===----------------------------------------------------------------------===// | 
 | 108 | // Engine construction and deletion. | 
 | 109 | //===----------------------------------------------------------------------===// | 
 | 110 |  | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 111 | static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { | 
 | 112 |   IdentifierInfo* II = &Ctx.Idents.get(name); | 
 | 113 |   return Ctx.Selectors.getSelector(0, &II); | 
 | 114 | } | 
 | 115 |  | 
| Ted Kremenek | daa497e | 2008-03-09 18:05:48 +0000 | [diff] [blame] | 116 |  | 
| Ted Kremenek | 8b23361 | 2008-07-02 20:13:38 +0000 | [diff] [blame] | 117 | GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 118 |                            LiveVariables& L, BugReporterData& BRD, | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 119 |                            bool purgeDead, bool eagerlyAssume, | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 120 |                            StoreManagerCreator SMC, | 
 | 121 |                            ConstraintManagerCreator CMC) | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 122 |   : CoreEngine(cfg, CD, Ctx, *this),  | 
 | 123 |     G(CoreEngine.getGraph()), | 
| Ted Kremenek | 8b23361 | 2008-07-02 20:13:38 +0000 | [diff] [blame] | 124 |     Liveness(L), | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 125 |     Builder(NULL), | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 126 |     StateMgr(G.getContext(), SMC, CMC, G.getAllocator(), cfg, CD, L), | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 127 |     SymMgr(StateMgr.getSymbolManager()), | 
| Ted Kremenek | 8e5fb28 | 2009-04-09 16:46:55 +0000 | [diff] [blame] | 128 |     ValMgr(StateMgr.getValueManager()), | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 129 |     CurrentStmt(NULL), | 
| Zhongxing Xu | a5a4166 | 2008-12-22 08:30:52 +0000 | [diff] [blame] | 130 |     NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), | 
 | 131 |     RaiseSel(GetNullarySelector("raise", G.getContext())),  | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 132 |     PurgeDead(purgeDead), | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 133 |     BR(BRD, *this), | 
 | 134 |     EagerlyAssume(eagerlyAssume) {} | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 135 |  | 
| Ted Kremenek | 1a654b6 | 2008-06-20 21:45:25 +0000 | [diff] [blame] | 136 | GRExprEngine::~GRExprEngine() {     | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 137 |   BR.FlushReports(); | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 138 |   delete [] NSExceptionInstanceRaiseSelectors; | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 139 | } | 
 | 140 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 141 | //===----------------------------------------------------------------------===// | 
 | 142 | // Utility methods. | 
 | 143 | //===----------------------------------------------------------------------===// | 
 | 144 |  | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 145 |  | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 146 | void GRExprEngine::setTransferFunctions(GRTransferFuncs* tf) { | 
| Ted Kremenek | 729a9a2 | 2008-07-17 23:15:45 +0000 | [diff] [blame] | 147 |   StateMgr.TF = tf; | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 148 |   tf->RegisterChecks(getBugReporter()); | 
| Ted Kremenek | 1c72ef0 | 2008-08-16 00:49:49 +0000 | [diff] [blame] | 149 |   tf->RegisterPrinters(getStateManager().Printers); | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 150 | } | 
 | 151 |  | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 152 | void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) { | 
 | 153 |   if (!BatchAuditor) | 
 | 154 |     BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator())); | 
 | 155 |    | 
 | 156 |   ((MappedBatchAuditor*) BatchAuditor.get())->AddCheck(A, C); | 
| Ted Kremenek | 50a6d0c | 2008-04-09 21:41:14 +0000 | [diff] [blame] | 157 | } | 
 | 158 |  | 
| Ted Kremenek | 536aa02 | 2009-03-30 17:53:05 +0000 | [diff] [blame] | 159 | void GRExprEngine::AddCheck(GRSimpleAPICheck *A) { | 
 | 160 |   if (!BatchAuditor) | 
 | 161 |     BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator())); | 
 | 162 |  | 
 | 163 |   ((MappedBatchAuditor*) BatchAuditor.get())->AddCheck(A); | 
 | 164 | } | 
 | 165 |  | 
| Ted Kremenek | 4adc81e | 2008-08-13 04:27:00 +0000 | [diff] [blame] | 166 | const GRState* GRExprEngine::getInitialState() { | 
| Ted Kremenek | 52e5602 | 2009-04-10 00:59:50 +0000 | [diff] [blame] | 167 |   const GRState *state = StateMgr.getInitialState(); | 
 | 168 |    | 
 | 169 |   // Precondition: the first argument of 'main' is an integer guaranteed | 
 | 170 |   //  to be > 0. | 
 | 171 |   // FIXME: It would be nice if we had a more general mechanism to add | 
 | 172 |   // such preconditions.  Some day. | 
 | 173 |   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(&StateMgr.getCodeDecl())) | 
 | 174 |     if (strcmp(FD->getIdentifier()->getName(), "main") == 0 && | 
 | 175 |         FD->getNumParams() > 0) { | 
 | 176 |       const ParmVarDecl *PD = FD->getParamDecl(0); | 
 | 177 |       QualType T = PD->getType(); | 
 | 178 |       if (T->isIntegerType()) | 
 | 179 |         if (const MemRegion *R = StateMgr.getRegion(PD)) { | 
 | 180 |           SVal V = GetSVal(state, loc::MemRegionVal(R)); | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 181 |           SVal Constraint = EvalBinOp(state, BinaryOperator::GT, V, | 
| Ted Kremenek | 52e5602 | 2009-04-10 00:59:50 +0000 | [diff] [blame] | 182 |                                       ValMgr.makeZeroVal(T), | 
 | 183 |                                       getContext().IntTy);           | 
 | 184 |           bool isFeasible = false;           | 
 | 185 |           const GRState *newState = Assume(state, Constraint, true, | 
 | 186 |                                            isFeasible); | 
 | 187 |           if (newState) state = newState; | 
 | 188 |         } | 
 | 189 |     } | 
 | 190 |    | 
 | 191 |   return state; | 
| Ted Kremenek | e070a1d | 2008-02-04 21:59:01 +0000 | [diff] [blame] | 192 | } | 
 | 193 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 194 | //===----------------------------------------------------------------------===// | 
 | 195 | // Top-level transfer function logic (Dispatcher). | 
 | 196 | //===----------------------------------------------------------------------===// | 
 | 197 |  | 
 | 198 | void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { | 
 | 199 |    | 
| Ted Kremenek | 0bed8a1 | 2009-03-11 02:41:36 +0000 | [diff] [blame] | 200 |   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), | 
 | 201 |                                 S->getLocStart(), | 
 | 202 |                                 "Error evaluating statement"); | 
 | 203 |    | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 204 |   Builder = &builder; | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 205 |   EntryNode = builder.getLastNode(); | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 206 |    | 
 | 207 |   // FIXME: Consolidate. | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 208 |   CurrentStmt = S; | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 209 |   StateMgr.CurrentStmt = S; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 210 |    | 
 | 211 |   // Set up our simple checks. | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 212 |   if (BatchAuditor) | 
 | 213 |     Builder->setAuditor(BatchAuditor.get()); | 
| Ted Kremenek | 241677a | 2009-01-21 22:26:05 +0000 | [diff] [blame] | 214 |      | 
| Ted Kremenek | bdb435d | 2008-07-11 18:37:32 +0000 | [diff] [blame] | 215 |   // Create the cleaned state.   | 
| Ted Kremenek | 241677a | 2009-01-21 22:26:05 +0000 | [diff] [blame] | 216 |   SymbolReaper SymReaper(Liveness, SymMgr);   | 
 | 217 |   CleanedState = PurgeDead ? StateMgr.RemoveDeadBindings(EntryNode->getState(),  | 
 | 218 |                                                          CurrentStmt, SymReaper) | 
 | 219 |                            : EntryNode->getState(); | 
 | 220 |  | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 221 |   // Process any special transfer function for dead symbols. | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 222 |   NodeSet Tmp; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 223 |    | 
| Ted Kremenek | 241677a | 2009-01-21 22:26:05 +0000 | [diff] [blame] | 224 |   if (!SymReaper.hasDeadSymbols()) | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 225 |     Tmp.Add(EntryNode); | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 226 |   else { | 
 | 227 |     SaveAndRestore<bool> OldSink(Builder->BuildSinks); | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 228 |     SaveOr OldHasGen(Builder->HasGeneratedNode); | 
 | 229 |  | 
| Ted Kremenek | 331b0ac | 2008-06-18 05:34:07 +0000 | [diff] [blame] | 230 |     SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols); | 
 | 231 |     Builder->PurgingDeadSymbols = true; | 
 | 232 |      | 
| Ted Kremenek | 729a9a2 | 2008-07-17 23:15:45 +0000 | [diff] [blame] | 233 |     getTF().EvalDeadSymbols(Tmp, *this, *Builder, EntryNode, S,  | 
| Ted Kremenek | 241677a | 2009-01-21 22:26:05 +0000 | [diff] [blame] | 234 |                             CleanedState, SymReaper); | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 235 |  | 
 | 236 |     if (!Builder->BuildSinks && !Builder->HasGeneratedNode) | 
 | 237 |       Tmp.Add(EntryNode); | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 238 |   } | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 239 |    | 
 | 240 |   bool HasAutoGenerated = false; | 
 | 241 |  | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 242 |   for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 243 |  | 
 | 244 |     NodeSet Dst; | 
 | 245 |      | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 246 |     // Set the cleaned state.   | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 247 |     Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I)); | 
 | 248 |      | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 249 |     // Visit the statement.   | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 250 |     Visit(S, *I, Dst); | 
 | 251 |  | 
 | 252 |     // Do we need to auto-generate a node?  We only need to do this to generate | 
 | 253 |     // a node with a "cleaned" state; GRCoreEngine will actually handle | 
 | 254 |     // auto-transitions for other cases.     | 
 | 255 |     if (Dst.size() == 1 && *Dst.begin() == EntryNode | 
 | 256 |         && !Builder->HasGeneratedNode && !HasAutoGenerated) { | 
 | 257 |       HasAutoGenerated = true; | 
 | 258 |       builder.generateNode(S, GetState(EntryNode), *I); | 
 | 259 |     } | 
| Ted Kremenek | 77d7ef8 | 2008-04-24 18:31:42 +0000 | [diff] [blame] | 260 |   } | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 261 |    | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 262 |   // NULL out these variables to cleanup. | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 263 |   CleanedState = NULL; | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 264 |   EntryNode = NULL; | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 265 |  | 
 | 266 |   // FIXME: Consolidate. | 
 | 267 |   StateMgr.CurrentStmt = 0; | 
 | 268 |   CurrentStmt = 0; | 
 | 269 |    | 
| Ted Kremenek | 846d4e9 | 2008-04-24 23:35:58 +0000 | [diff] [blame] | 270 |   Builder = NULL; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 271 | } | 
 | 272 |  | 
| Ted Kremenek | 0bed8a1 | 2009-03-11 02:41:36 +0000 | [diff] [blame] | 273 | void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {   | 
 | 274 |   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), | 
 | 275 |                                 S->getLocStart(), | 
 | 276 |                                 "Error evaluating statement"); | 
 | 277 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 278 |   // FIXME: add metadata to the CFG so that we can disable | 
 | 279 |   //  this check when we KNOW that there is no block-level subexpression. | 
 | 280 |   //  The motivation is that this check requires a hashtable lookup. | 
 | 281 |    | 
 | 282 |   if (S != CurrentStmt && getCFG().isBlkExpr(S)) { | 
 | 283 |     Dst.Add(Pred); | 
 | 284 |     return; | 
 | 285 |   } | 
 | 286 |    | 
 | 287 |   switch (S->getStmtClass()) { | 
 | 288 |        | 
 | 289 |     default: | 
 | 290 |       // Cases we intentionally have "default" handle: | 
 | 291 |       //   AddrLabelExpr, IntegerLiteral, CharacterLiteral | 
 | 292 |        | 
 | 293 |       Dst.Add(Pred); // No-op. Simply propagate the current state unchanged. | 
 | 294 |       break; | 
| Ted Kremenek | 540cbe2 | 2008-04-22 04:56:29 +0000 | [diff] [blame] | 295 |      | 
 | 296 |     case Stmt::ArraySubscriptExprClass: | 
 | 297 |       VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst, false); | 
 | 298 |       break; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 299 |        | 
 | 300 |     case Stmt::AsmStmtClass: | 
 | 301 |       VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst); | 
 | 302 |       break; | 
 | 303 |        | 
 | 304 |     case Stmt::BinaryOperatorClass: { | 
 | 305 |       BinaryOperator* B = cast<BinaryOperator>(S); | 
 | 306 |        | 
 | 307 |       if (B->isLogicalOp()) { | 
 | 308 |         VisitLogicalExpr(B, Pred, Dst); | 
 | 309 |         break; | 
 | 310 |       } | 
 | 311 |       else if (B->getOpcode() == BinaryOperator::Comma) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 312 |         const GRState* state = GetState(Pred); | 
 | 313 |         MakeNode(Dst, B, Pred, BindExpr(state, B, GetSVal(state, B->getRHS()))); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 314 |         break; | 
 | 315 |       } | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 316 |  | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 317 |       if (EagerlyAssume && (B->isRelationalOp() || B->isEqualityOp())) { | 
 | 318 |         NodeSet Tmp; | 
 | 319 |         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp); | 
| Ted Kremenek | b293902 | 2009-02-25 23:32:10 +0000 | [diff] [blame] | 320 |         EvalEagerlyAssume(Dst, Tmp, cast<Expr>(S));         | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 321 |       } | 
 | 322 |       else | 
 | 323 |         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst); | 
 | 324 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 325 |       break; | 
 | 326 |     } | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 327 |  | 
| Douglas Gregor | b460980 | 2008-11-14 16:09:21 +0000 | [diff] [blame] | 328 |     case Stmt::CallExprClass: | 
 | 329 |     case Stmt::CXXOperatorCallExprClass: { | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 330 |       CallExpr* C = cast<CallExpr>(S); | 
 | 331 |       VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst); | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 332 |       break; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 333 |     } | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 334 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 335 |       // FIXME: ChooseExpr is really a constant.  We need to fix | 
 | 336 |       //        the CFG do not model them as explicit control-flow. | 
 | 337 |        | 
 | 338 |     case Stmt::ChooseExprClass: { // __builtin_choose_expr | 
 | 339 |       ChooseExpr* C = cast<ChooseExpr>(S); | 
 | 340 |       VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst); | 
 | 341 |       break; | 
 | 342 |     } | 
 | 343 |        | 
 | 344 |     case Stmt::CompoundAssignOperatorClass: | 
 | 345 |       VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst); | 
 | 346 |       break; | 
| Zhongxing Xu | f22679e | 2008-11-07 10:38:33 +0000 | [diff] [blame] | 347 |  | 
 | 348 |     case Stmt::CompoundLiteralExprClass: | 
 | 349 |       VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst, false); | 
 | 350 |       break; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 351 |        | 
 | 352 |     case Stmt::ConditionalOperatorClass: { // '?' operator | 
 | 353 |       ConditionalOperator* C = cast<ConditionalOperator>(S); | 
 | 354 |       VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst); | 
 | 355 |       break; | 
 | 356 |     } | 
 | 357 |        | 
 | 358 |     case Stmt::DeclRefExprClass: | 
| Douglas Gregor | 1a49af9 | 2009-01-06 05:10:23 +0000 | [diff] [blame] | 359 |     case Stmt::QualifiedDeclRefExprClass: | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 360 |       VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 361 |       break; | 
 | 362 |        | 
 | 363 |     case Stmt::DeclStmtClass: | 
 | 364 |       VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst); | 
 | 365 |       break; | 
 | 366 |        | 
| Argyrios Kyrtzidis | 0835a3c | 2008-08-18 23:01:59 +0000 | [diff] [blame] | 367 |     case Stmt::ImplicitCastExprClass: | 
| Douglas Gregor | 6eec8e8 | 2008-10-28 15:36:24 +0000 | [diff] [blame] | 368 |     case Stmt::CStyleCastExprClass: { | 
| Argyrios Kyrtzidis | 0835a3c | 2008-08-18 23:01:59 +0000 | [diff] [blame] | 369 |       CastExpr* C = cast<CastExpr>(S); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 370 |       VisitCast(C, C->getSubExpr(), Pred, Dst); | 
 | 371 |       break; | 
 | 372 |     } | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 373 |  | 
 | 374 |     case Stmt::InitListExprClass: | 
 | 375 |       VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst); | 
 | 376 |       break; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 377 |        | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 378 |     case Stmt::MemberExprClass: | 
| Ted Kremenek | 469ecbd | 2008-04-21 23:43:38 +0000 | [diff] [blame] | 379 |       VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst, false); | 
 | 380 |       break; | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 381 |        | 
 | 382 |     case Stmt::ObjCIvarRefExprClass: | 
 | 383 |       VisitObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst, false); | 
 | 384 |       break; | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 385 |  | 
 | 386 |     case Stmt::ObjCForCollectionStmtClass: | 
 | 387 |       VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst); | 
 | 388 |       break; | 
| Ted Kremenek | 469ecbd | 2008-04-21 23:43:38 +0000 | [diff] [blame] | 389 |        | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 390 |     case Stmt::ObjCMessageExprClass: { | 
 | 391 |       VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst); | 
 | 392 |       break; | 
 | 393 |     } | 
 | 394 |        | 
| Ted Kremenek | bbfd07a | 2008-12-09 20:18:58 +0000 | [diff] [blame] | 395 |     case Stmt::ObjCAtThrowStmtClass: { | 
 | 396 |       // FIXME: This is not complete.  We basically treat @throw as | 
 | 397 |       // an abort. | 
 | 398 |       SaveAndRestore<bool> OldSink(Builder->BuildSinks); | 
 | 399 |       Builder->BuildSinks = true; | 
 | 400 |       MakeNode(Dst, S, Pred, GetState(Pred)); | 
 | 401 |       break; | 
 | 402 |     } | 
 | 403 |        | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 404 |     case Stmt::ParenExprClass: | 
| Ted Kremenek | 540cbe2 | 2008-04-22 04:56:29 +0000 | [diff] [blame] | 405 |       Visit(cast<ParenExpr>(S)->getSubExpr()->IgnoreParens(), Pred, Dst); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 406 |       break; | 
 | 407 |        | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 408 |     case Stmt::ReturnStmtClass: | 
 | 409 |       VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst); | 
 | 410 |       break; | 
 | 411 |        | 
| Sebastian Redl | 0518999 | 2008-11-11 17:56:53 +0000 | [diff] [blame] | 412 |     case Stmt::SizeOfAlignOfExprClass: | 
 | 413 |       VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), Pred, Dst); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 414 |       break; | 
 | 415 |        | 
 | 416 |     case Stmt::StmtExprClass: { | 
 | 417 |       StmtExpr* SE = cast<StmtExpr>(S); | 
| Ted Kremenek | a3d1eb8 | 2009-02-14 05:55:08 +0000 | [diff] [blame] | 418 |  | 
 | 419 |       if (SE->getSubStmt()->body_empty()) { | 
 | 420 |         // Empty statement expression. | 
 | 421 |         assert(SE->getType() == getContext().VoidTy | 
 | 422 |                && "Empty statement expression must have void type."); | 
 | 423 |         Dst.Add(Pred); | 
 | 424 |         break; | 
 | 425 |       } | 
 | 426 |                 | 
 | 427 |       if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) { | 
 | 428 |         const GRState* state = GetState(Pred); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 429 |         MakeNode(Dst, SE, Pred, BindExpr(state, SE, GetSVal(state, LastExpr))); | 
| Ted Kremenek | a3d1eb8 | 2009-02-14 05:55:08 +0000 | [diff] [blame] | 430 |       } | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 431 |       else | 
 | 432 |         Dst.Add(Pred); | 
 | 433 |        | 
 | 434 |       break; | 
 | 435 |     } | 
| Zhongxing Xu | 6987c7b | 2008-11-30 05:49:49 +0000 | [diff] [blame] | 436 |  | 
 | 437 |     case Stmt::StringLiteralClass: | 
 | 438 |       VisitLValue(cast<StringLiteral>(S), Pred, Dst); | 
 | 439 |       break; | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 440 |        | 
| Ted Kremenek | 7237459 | 2009-03-18 23:49:26 +0000 | [diff] [blame] | 441 |     case Stmt::UnaryOperatorClass: { | 
 | 442 |       UnaryOperator *U = cast<UnaryOperator>(S); | 
 | 443 |       if (EagerlyAssume && (U->getOpcode() == UnaryOperator::LNot)) { | 
 | 444 |         NodeSet Tmp; | 
 | 445 |         VisitUnaryOperator(U, Pred, Tmp, false); | 
 | 446 |         EvalEagerlyAssume(Dst, Tmp, U); | 
 | 447 |       } | 
 | 448 |       else | 
 | 449 |         VisitUnaryOperator(U, Pred, Dst, false); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 450 |       break; | 
| Ted Kremenek | 7237459 | 2009-03-18 23:49:26 +0000 | [diff] [blame] | 451 |     } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 452 |   } | 
 | 453 | } | 
 | 454 |  | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 455 | void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 456 |    | 
 | 457 |   Ex = Ex->IgnoreParens(); | 
 | 458 |    | 
 | 459 |   if (Ex != CurrentStmt && getCFG().isBlkExpr(Ex)) { | 
 | 460 |     Dst.Add(Pred); | 
 | 461 |     return; | 
 | 462 |   } | 
 | 463 |    | 
 | 464 |   switch (Ex->getStmtClass()) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 465 |        | 
 | 466 |     case Stmt::ArraySubscriptExprClass: | 
 | 467 |       VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true); | 
 | 468 |       return; | 
 | 469 |        | 
 | 470 |     case Stmt::DeclRefExprClass: | 
| Douglas Gregor | 1a49af9 | 2009-01-06 05:10:23 +0000 | [diff] [blame] | 471 |     case Stmt::QualifiedDeclRefExprClass: | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 472 |       VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true); | 
 | 473 |       return; | 
 | 474 |        | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 475 |     case Stmt::ObjCIvarRefExprClass: | 
 | 476 |       VisitObjCIvarRefExpr(cast<ObjCIvarRefExpr>(Ex), Pred, Dst, true); | 
 | 477 |       return; | 
 | 478 |        | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 479 |     case Stmt::UnaryOperatorClass: | 
 | 480 |       VisitUnaryOperator(cast<UnaryOperator>(Ex), Pred, Dst, true); | 
 | 481 |       return; | 
 | 482 |        | 
 | 483 |     case Stmt::MemberExprClass: | 
 | 484 |       VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true); | 
 | 485 |       return; | 
| Ted Kremenek | b6b81d1 | 2008-10-17 17:24:14 +0000 | [diff] [blame] | 486 |        | 
| Ted Kremenek | 4f09027 | 2008-10-27 21:54:31 +0000 | [diff] [blame] | 487 |     case Stmt::CompoundLiteralExprClass: | 
| Zhongxing Xu | f22679e | 2008-11-07 10:38:33 +0000 | [diff] [blame] | 488 |       VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst, true); | 
| Ted Kremenek | 4f09027 | 2008-10-27 21:54:31 +0000 | [diff] [blame] | 489 |       return; | 
 | 490 |        | 
| Ted Kremenek | b6b81d1 | 2008-10-17 17:24:14 +0000 | [diff] [blame] | 491 |     case Stmt::ObjCPropertyRefExprClass: | 
| Ted Kremenek | 868210e | 2009-04-21 23:53:32 +0000 | [diff] [blame] | 492 |     case Stmt::ObjCKVCRefExprClass: | 
| Ted Kremenek | b6b81d1 | 2008-10-17 17:24:14 +0000 | [diff] [blame] | 493 |       // FIXME: Property assignments are lvalues, but not really "locations". | 
 | 494 |       //  e.g.:  self.x = something; | 
 | 495 |       //  Here the "self.x" really can translate to a method call (setter) when | 
 | 496 |       //  the assignment is made.  Moreover, the entire assignment expression | 
 | 497 |       //  evaluate to whatever "something" is, not calling the "getter" for | 
 | 498 |       //  the property (which would make sense since it can have side effects). | 
 | 499 |       //  We'll probably treat this as a location, but not one that we can | 
 | 500 |       //  take the address of.  Perhaps we need a new SVal class for cases | 
 | 501 |       //  like thsis? | 
 | 502 |       //  Note that we have a similar problem for bitfields, since they don't | 
 | 503 |       //  have "locations" in the sense that we can take their address. | 
 | 504 |       Dst.Add(Pred); | 
| Ted Kremenek | c7df6d2 | 2008-10-18 04:08:49 +0000 | [diff] [blame] | 505 |       return; | 
| Zhongxing Xu | 143bf82 | 2008-10-25 14:18:57 +0000 | [diff] [blame] | 506 |  | 
 | 507 |     case Stmt::StringLiteralClass: { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 508 |       const GRState* state = GetState(Pred); | 
 | 509 |       SVal V = StateMgr.GetLValue(state, cast<StringLiteral>(Ex)); | 
 | 510 |       MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V)); | 
| Zhongxing Xu | 143bf82 | 2008-10-25 14:18:57 +0000 | [diff] [blame] | 511 |       return; | 
 | 512 |     } | 
| Ted Kremenek | c7df6d2 | 2008-10-18 04:08:49 +0000 | [diff] [blame] | 513 |        | 
| Ted Kremenek | f8cd1b2 | 2008-10-18 04:15:35 +0000 | [diff] [blame] | 514 |     default: | 
 | 515 |       // Arbitrary subexpressions can return aggregate temporaries that | 
 | 516 |       // can be used in a lvalue context.  We need to enhance our support | 
 | 517 |       // of such temporaries in both the environment and the store, so right | 
 | 518 |       // now we just do a regular visit. | 
| Douglas Gregor | d7eb846 | 2009-01-30 17:31:00 +0000 | [diff] [blame] | 519 |       assert ((Ex->getType()->isAggregateType()) && | 
| Ted Kremenek | 5b2316a | 2008-10-25 20:09:21 +0000 | [diff] [blame] | 520 |               "Other kinds of expressions with non-aggregate/union types do" | 
 | 521 |               " not have lvalues."); | 
| Ted Kremenek | c7df6d2 | 2008-10-18 04:08:49 +0000 | [diff] [blame] | 522 |        | 
| Ted Kremenek | f8cd1b2 | 2008-10-18 04:15:35 +0000 | [diff] [blame] | 523 |       Visit(Ex, Pred, Dst); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 524 |   } | 
 | 525 | } | 
 | 526 |  | 
 | 527 | //===----------------------------------------------------------------------===// | 
 | 528 | // Block entrance.  (Update counters). | 
 | 529 | //===----------------------------------------------------------------------===// | 
 | 530 |  | 
| Ted Kremenek | 4adc81e | 2008-08-13 04:27:00 +0000 | [diff] [blame] | 531 | bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const GRState*, | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 532 |                                         GRBlockCounter BC) { | 
 | 533 |    | 
 | 534 |   return BC.getNumVisited(B->getBlockID()) < 3; | 
 | 535 | } | 
 | 536 |  | 
 | 537 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 538 | // Generic node creation. | 
 | 539 | //===----------------------------------------------------------------------===// | 
 | 540 |  | 
 | 541 | GRExprEngine::NodeTy* GRExprEngine::MakeNode(NodeSet& Dst, Stmt* S, | 
 | 542 |                                              NodeTy* Pred, | 
 | 543 |                                              const GRState* St, | 
 | 544 |                                              ProgramPoint::Kind K, | 
 | 545 |                                              const void *tag) { | 
 | 546 |    | 
 | 547 |   assert (Builder && "GRStmtNodeBuilder not present."); | 
 | 548 |   SaveAndRestore<const void*> OldTag(Builder->Tag); | 
 | 549 |   Builder->Tag = tag; | 
 | 550 |   return Builder->MakeNode(Dst, S, Pred, St, K); | 
 | 551 | } | 
 | 552 |  | 
 | 553 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 554 | // Branch processing. | 
 | 555 | //===----------------------------------------------------------------------===// | 
 | 556 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 557 | const GRState* GRExprEngine::MarkBranch(const GRState* state, | 
| Ted Kremenek | 4323a57 | 2008-07-10 22:03:41 +0000 | [diff] [blame] | 558 |                                            Stmt* Terminator, | 
 | 559 |                                            bool branchTaken) { | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 560 |    | 
 | 561 |   switch (Terminator->getStmtClass()) { | 
 | 562 |     default: | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 563 |       return state; | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 564 |        | 
 | 565 |     case Stmt::BinaryOperatorClass: { // '&&' and '||' | 
 | 566 |        | 
 | 567 |       BinaryOperator* B = cast<BinaryOperator>(Terminator); | 
 | 568 |       BinaryOperator::Opcode Op = B->getOpcode(); | 
 | 569 |        | 
 | 570 |       assert (Op == BinaryOperator::LAnd || Op == BinaryOperator::LOr); | 
 | 571 |        | 
 | 572 |       // For &&, if we take the true branch, then the value of the whole | 
 | 573 |       // expression is that of the RHS expression. | 
 | 574 |       // | 
 | 575 |       // For ||, if we take the false branch, then the value of the whole | 
 | 576 |       // expression is that of the RHS expression. | 
 | 577 |        | 
 | 578 |       Expr* Ex = (Op == BinaryOperator::LAnd && branchTaken) || | 
 | 579 |                  (Op == BinaryOperator::LOr && !branchTaken)   | 
 | 580 |                ? B->getRHS() : B->getLHS(); | 
 | 581 |          | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 582 |       return BindBlkExpr(state, B, UndefinedVal(Ex)); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 583 |     } | 
 | 584 |        | 
 | 585 |     case Stmt::ConditionalOperatorClass: { // ?: | 
 | 586 |        | 
 | 587 |       ConditionalOperator* C = cast<ConditionalOperator>(Terminator); | 
 | 588 |        | 
 | 589 |       // For ?, if branchTaken == true then the value is either the LHS or | 
 | 590 |       // the condition itself. (GNU extension). | 
 | 591 |        | 
 | 592 |       Expr* Ex;       | 
 | 593 |        | 
 | 594 |       if (branchTaken) | 
 | 595 |         Ex = C->getLHS() ? C->getLHS() : C->getCond();         | 
 | 596 |       else | 
 | 597 |         Ex = C->getRHS(); | 
 | 598 |        | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 599 |       return BindBlkExpr(state, C, UndefinedVal(Ex)); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 600 |     } | 
 | 601 |        | 
 | 602 |     case Stmt::ChooseExprClass: { // ?: | 
 | 603 |        | 
 | 604 |       ChooseExpr* C = cast<ChooseExpr>(Terminator); | 
 | 605 |        | 
 | 606 |       Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();       | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 607 |       return BindBlkExpr(state, C, UndefinedVal(Ex)); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 608 |     } | 
 | 609 |   } | 
 | 610 | } | 
 | 611 |  | 
| Ted Kremenek | 6ae8a36 | 2009-03-13 16:32:54 +0000 | [diff] [blame] | 612 | /// RecoverCastedSymbol - A helper function for ProcessBranch that is used | 
 | 613 | /// to try to recover some path-sensitivity for casts of symbolic | 
 | 614 | /// integers that promote their values (which are currently not tracked well). | 
 | 615 | /// This function returns the SVal bound to Condition->IgnoreCasts if all the | 
 | 616 | //  cast(s) did was sign-extend the original value. | 
 | 617 | static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state, | 
 | 618 |                                 Stmt* Condition, ASTContext& Ctx) { | 
 | 619 |  | 
 | 620 |   Expr *Ex = dyn_cast<Expr>(Condition); | 
 | 621 |   if (!Ex) | 
 | 622 |     return UnknownVal(); | 
 | 623 |  | 
 | 624 |   uint64_t bits = 0; | 
 | 625 |   bool bitsInit = false; | 
 | 626 |      | 
 | 627 |   while (CastExpr *CE = dyn_cast<CastExpr>(Ex)) { | 
 | 628 |     QualType T = CE->getType(); | 
 | 629 |  | 
 | 630 |     if (!T->isIntegerType()) | 
 | 631 |       return UnknownVal(); | 
 | 632 |      | 
 | 633 |     uint64_t newBits = Ctx.getTypeSize(T); | 
 | 634 |     if (!bitsInit || newBits < bits) { | 
 | 635 |       bitsInit = true; | 
 | 636 |       bits = newBits; | 
 | 637 |     } | 
 | 638 |        | 
 | 639 |     Ex = CE->getSubExpr(); | 
 | 640 |   } | 
 | 641 |  | 
 | 642 |   // We reached a non-cast.  Is it a symbolic value? | 
 | 643 |   QualType T = Ex->getType(); | 
 | 644 |  | 
 | 645 |   if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits) | 
 | 646 |     return UnknownVal(); | 
 | 647 |    | 
 | 648 |   return StateMgr.GetSVal(state, Ex); | 
 | 649 | } | 
 | 650 |  | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 651 | void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 652 |                                  BranchNodeBuilder& builder) { | 
| Ted Kremenek | 0bed8a1 | 2009-03-11 02:41:36 +0000 | [diff] [blame] | 653 |    | 
| Ted Kremenek | e7d2211 | 2008-02-11 19:21:59 +0000 | [diff] [blame] | 654 |   // Remove old bindings for subexpressions. | 
| Ted Kremenek | 4adc81e | 2008-08-13 04:27:00 +0000 | [diff] [blame] | 655 |   const GRState* PrevState = | 
| Ted Kremenek | 4323a57 | 2008-07-10 22:03:41 +0000 | [diff] [blame] | 656 |     StateMgr.RemoveSubExprBindings(builder.getState()); | 
| Ted Kremenek | f233d48 | 2008-02-05 00:26:40 +0000 | [diff] [blame] | 657 |    | 
| Ted Kremenek | b233183 | 2008-02-15 22:29:00 +0000 | [diff] [blame] | 658 |   // Check for NULL conditions; e.g. "for(;;)" | 
 | 659 |   if (!Condition) {  | 
 | 660 |     builder.markInfeasible(false); | 
| Ted Kremenek | b233183 | 2008-02-15 22:29:00 +0000 | [diff] [blame] | 661 |     return; | 
 | 662 |   } | 
 | 663 |    | 
| Ted Kremenek | 21028dd | 2009-03-11 03:54:24 +0000 | [diff] [blame] | 664 |   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), | 
 | 665 |                                 Condition->getLocStart(), | 
 | 666 |                                 "Error evaluating branch"); | 
 | 667 |    | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 668 |   SVal V = GetSVal(PrevState, Condition); | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 669 |    | 
 | 670 |   switch (V.getBaseKind()) { | 
 | 671 |     default: | 
 | 672 |       break; | 
 | 673 |  | 
| Ted Kremenek | 6ae8a36 | 2009-03-13 16:32:54 +0000 | [diff] [blame] | 674 |     case SVal::UnknownKind: { | 
 | 675 |       if (Expr *Ex = dyn_cast<Expr>(Condition)) { | 
 | 676 |           if (Ex->getType()->isIntegerType()) { | 
 | 677 |           // Try to recover some path-sensitivity.  Right now casts of symbolic | 
 | 678 |           // integers that promote their values are currently not tracked well. | 
 | 679 |           // If 'Condition' is such an expression, try and recover the | 
 | 680 |           // underlying value and use that instead. | 
 | 681 |           SVal recovered = RecoverCastedSymbol(getStateManager(), | 
 | 682 |                                                builder.getState(), Condition, | 
 | 683 |                                                getContext()); | 
 | 684 |              | 
 | 685 |           if (!recovered.isUnknown()) { | 
 | 686 |             V = recovered; | 
 | 687 |             break; | 
 | 688 |           } | 
 | 689 |         } | 
 | 690 |       } | 
 | 691 |      | 
| Ted Kremenek | 58b3321 | 2008-02-26 19:40:44 +0000 | [diff] [blame] | 692 |       builder.generateNode(MarkBranch(PrevState, Term, true), true); | 
 | 693 |       builder.generateNode(MarkBranch(PrevState, Term, false), false); | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 694 |       return; | 
| Ted Kremenek | 6ae8a36 | 2009-03-13 16:32:54 +0000 | [diff] [blame] | 695 |     } | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 696 |        | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 697 |     case SVal::UndefinedKind: {       | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 698 |       NodeTy* N = builder.generateNode(PrevState, true); | 
 | 699 |  | 
 | 700 |       if (N) { | 
 | 701 |         N->markAsSink(); | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 702 |         UndefBranches.insert(N); | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 703 |       } | 
 | 704 |        | 
 | 705 |       builder.markInfeasible(false); | 
 | 706 |       return; | 
 | 707 |     }       | 
 | 708 |   } | 
| Ted Kremenek | 8e49dd6 | 2008-02-12 18:08:17 +0000 | [diff] [blame] | 709 |      | 
| Ted Kremenek | 6a6719a | 2008-02-29 20:27:50 +0000 | [diff] [blame] | 710 |   // Process the true branch. | 
| Ted Kremenek | 8e49dd6 | 2008-02-12 18:08:17 +0000 | [diff] [blame] | 711 |  | 
| Ted Kremenek | 361fa8e | 2008-03-12 21:45:47 +0000 | [diff] [blame] | 712 |   bool isFeasible = false;   | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 713 |   const GRState* state = Assume(PrevState, V, true, isFeasible); | 
| Ted Kremenek | 6a6719a | 2008-02-29 20:27:50 +0000 | [diff] [blame] | 714 |  | 
 | 715 |   if (isFeasible) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 716 |     builder.generateNode(MarkBranch(state, Term, true), true); | 
| Ted Kremenek | 8e49dd6 | 2008-02-12 18:08:17 +0000 | [diff] [blame] | 717 |   else | 
 | 718 |     builder.markInfeasible(true); | 
| Ted Kremenek | 6a6719a | 2008-02-29 20:27:50 +0000 | [diff] [blame] | 719 |        | 
 | 720 |   // Process the false branch.   | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 721 |    | 
| Ted Kremenek | 6a6719a | 2008-02-29 20:27:50 +0000 | [diff] [blame] | 722 |   isFeasible = false; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 723 |   state = Assume(PrevState, V, false, isFeasible); | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 724 |    | 
| Ted Kremenek | 6a6719a | 2008-02-29 20:27:50 +0000 | [diff] [blame] | 725 |   if (isFeasible) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 726 |     builder.generateNode(MarkBranch(state, Term, false), false); | 
| Ted Kremenek | f233d48 | 2008-02-05 00:26:40 +0000 | [diff] [blame] | 727 |   else | 
 | 728 |     builder.markInfeasible(false); | 
| Ted Kremenek | 71c29bd | 2008-01-29 23:32:35 +0000 | [diff] [blame] | 729 | } | 
 | 730 |  | 
| Ted Kremenek | 4d4dd85 | 2008-02-13 17:41:41 +0000 | [diff] [blame] | 731 | /// ProcessIndirectGoto - Called by GRCoreEngine.  Used to generate successor | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 732 | ///  nodes by processing the 'effects' of a computed goto jump. | 
| Ted Kremenek | 4d4dd85 | 2008-02-13 17:41:41 +0000 | [diff] [blame] | 733 | void GRExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) { | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 734 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 735 |   const GRState* state = builder.getState();   | 
 | 736 |   SVal V = GetSVal(state, builder.getTarget()); | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 737 |    | 
 | 738 |   // Three possibilities: | 
 | 739 |   // | 
 | 740 |   //   (1) We know the computed label. | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 741 |   //   (2) The label is NULL (or some other constant), or Undefined. | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 742 |   //   (3) We have no clue about the label.  Dispatch to all targets. | 
 | 743 |   // | 
 | 744 |    | 
 | 745 |   typedef IndirectGotoNodeBuilder::iterator iterator; | 
 | 746 |  | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 747 |   if (isa<loc::GotoLabel>(V)) { | 
 | 748 |     LabelStmt* L = cast<loc::GotoLabel>(V).getLabel(); | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 749 |      | 
 | 750 |     for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) { | 
| Ted Kremenek | 24f1a96 | 2008-02-13 17:27:37 +0000 | [diff] [blame] | 751 |       if (I.getLabel() == L) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 752 |         builder.generateNode(I, state); | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 753 |         return; | 
 | 754 |       } | 
 | 755 |     } | 
 | 756 |      | 
 | 757 |     assert (false && "No block with label."); | 
 | 758 |     return; | 
 | 759 |   } | 
 | 760 |  | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 761 |   if (isa<loc::ConcreteInt>(V) || isa<UndefinedVal>(V)) { | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 762 |     // Dispatch to the first target and mark it as a sink. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 763 |     NodeTy* N = builder.generateNode(builder.begin(), state, true); | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 764 |     UndefBranches.insert(N); | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 765 |     return; | 
 | 766 |   } | 
 | 767 |    | 
 | 768 |   // This is really a catch-all.  We don't support symbolics yet. | 
| Ted Kremenek | b3cfd58 | 2009-04-23 17:49:43 +0000 | [diff] [blame] | 769 |   // FIXME: Implement dispatch for symbolic pointers. | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 770 |    | 
 | 771 |   for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 772 |     builder.generateNode(I, state); | 
| Ted Kremenek | 754607e | 2008-02-13 00:24:44 +0000 | [diff] [blame] | 773 | } | 
| Ted Kremenek | f233d48 | 2008-02-05 00:26:40 +0000 | [diff] [blame] | 774 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 775 |  | 
 | 776 | void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, | 
 | 777 |                                     NodeTy* Pred, NodeSet& Dst) { | 
 | 778 |    | 
 | 779 |   assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex)); | 
 | 780 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 781 |   const GRState* state = GetState(Pred); | 
 | 782 |   SVal X = GetBlkExprSVal(state, Ex); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 783 |    | 
 | 784 |   assert (X.isUndef()); | 
 | 785 |    | 
 | 786 |   Expr* SE = (Expr*) cast<UndefinedVal>(X).getData(); | 
 | 787 |    | 
 | 788 |   assert (SE); | 
 | 789 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 790 |   X = GetBlkExprSVal(state, SE); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 791 |    | 
 | 792 |   // Make sure that we invalidate the previous binding. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 793 |   MakeNode(Dst, Ex, Pred, StateMgr.BindExpr(state, Ex, X, true, true)); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 794 | } | 
 | 795 |  | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 796 | /// ProcessSwitch - Called by GRCoreEngine.  Used to generate successor | 
 | 797 | ///  nodes by processing the 'effects' of a switch statement. | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 798 | void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {   | 
 | 799 |   typedef SwitchNodeBuilder::iterator iterator;   | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 800 |   const GRState* state = builder.getState();   | 
| Ted Kremenek | 692416c | 2008-02-18 22:57:02 +0000 | [diff] [blame] | 801 |   Expr* CondE = builder.getCondition(); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 802 |   SVal  CondV = GetSVal(state, CondE); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 803 |  | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 804 |   if (CondV.isUndef()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 805 |     NodeTy* N = builder.generateDefaultCaseNode(state, true); | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 806 |     UndefBranches.insert(N); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 807 |     return; | 
 | 808 |   } | 
| Ted Kremenek | 692416c | 2008-02-18 22:57:02 +0000 | [diff] [blame] | 809 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 810 |   const GRState*  DefaultSt = state;   | 
| Ted Kremenek | 5014ab1 | 2008-04-23 05:03:18 +0000 | [diff] [blame] | 811 |   bool DefaultFeasible = false; | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 812 |    | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 813 |   for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) { | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 814 |     CaseStmt* Case = cast<CaseStmt>(I.getCase()); | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 815 |  | 
 | 816 |     // Evaluate the LHS of the case value. | 
 | 817 |     Expr::EvalResult V1; | 
 | 818 |     bool b = Case->getLHS()->Evaluate(V1, getContext());     | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 819 |      | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 820 |     // Sanity checks.  These go away in Release builds. | 
 | 821 |     assert(b && V1.Val.isInt() && !V1.HasSideEffects  | 
 | 822 |              && "Case condition must evaluate to an integer constant."); | 
 | 823 |     b = b; // silence unused variable warning     | 
 | 824 |     assert(V1.Val.getInt().getBitWidth() ==  | 
 | 825 |            getContext().getTypeSize(CondE->getType())); | 
 | 826 |             | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 827 |     // Get the RHS of the case, if it exists. | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 828 |     Expr::EvalResult V2; | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 829 |      | 
 | 830 |     if (Expr* E = Case->getRHS()) { | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 831 |       b = E->Evaluate(V2, getContext()); | 
 | 832 |       assert(b && V2.Val.isInt() && !V2.HasSideEffects  | 
 | 833 |              && "Case condition must evaluate to an integer constant."); | 
 | 834 |       b = b; // silence unused variable warning | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 835 |     } | 
| Ted Kremenek | 14a1140 | 2008-03-17 22:17:56 +0000 | [diff] [blame] | 836 |     else | 
 | 837 |       V2 = V1; | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 838 |      | 
 | 839 |     // FIXME: Eventually we should replace the logic below with a range | 
 | 840 |     //  comparison, rather than concretize the values within the range. | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 841 |     //  This should be easy once we have "ranges" for NonLVals. | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 842 |          | 
| Ted Kremenek | 14a1140 | 2008-03-17 22:17:56 +0000 | [diff] [blame] | 843 |     do { | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 844 |       nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));       | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 845 |       SVal Res = EvalBinOp(DefaultSt, BinaryOperator::EQ, CondV, CaseVal, | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 846 |                            getContext().IntTy); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 847 |        | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 848 |       // Now "assume" that the case matches.       | 
| Ted Kremenek | 361fa8e | 2008-03-12 21:45:47 +0000 | [diff] [blame] | 849 |       bool isFeasible = false;       | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 850 |       const GRState* StNew = Assume(state, Res, true, isFeasible); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 851 |        | 
 | 852 |       if (isFeasible) { | 
 | 853 |         builder.generateCaseStmtNode(I, StNew); | 
 | 854 |         | 
 | 855 |         // If CondV evaluates to a constant, then we know that this | 
 | 856 |         // is the *only* case that we can take, so stop evaluating the | 
 | 857 |         // others. | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 858 |         if (isa<nonloc::ConcreteInt>(CondV)) | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 859 |           return; | 
 | 860 |       } | 
 | 861 |        | 
 | 862 |       // Now "assume" that the case doesn't match.  Add this state | 
 | 863 |       // to the default state (if it is feasible). | 
 | 864 |        | 
| Ted Kremenek | 361fa8e | 2008-03-12 21:45:47 +0000 | [diff] [blame] | 865 |       isFeasible = false; | 
| Ted Kremenek | 6cb0b54 | 2008-02-14 19:37:24 +0000 | [diff] [blame] | 866 |       StNew = Assume(DefaultSt, Res, false, isFeasible); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 867 |        | 
| Ted Kremenek | 5014ab1 | 2008-04-23 05:03:18 +0000 | [diff] [blame] | 868 |       if (isFeasible) { | 
 | 869 |         DefaultFeasible = true; | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 870 |         DefaultSt = StNew; | 
| Ted Kremenek | 5014ab1 | 2008-04-23 05:03:18 +0000 | [diff] [blame] | 871 |       } | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 872 |  | 
| Ted Kremenek | 14a1140 | 2008-03-17 22:17:56 +0000 | [diff] [blame] | 873 |       // Concretize the next value in the range. | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 874 |       if (V1.Val.getInt() == V2.Val.getInt()) | 
| Ted Kremenek | 14a1140 | 2008-03-17 22:17:56 +0000 | [diff] [blame] | 875 |         break; | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 876 |        | 
| Ted Kremenek | 72afb37 | 2009-01-17 01:54:16 +0000 | [diff] [blame] | 877 |       ++V1.Val.getInt(); | 
 | 878 |       assert (V1.Val.getInt() <= V2.Val.getInt()); | 
| Ted Kremenek | 14a1140 | 2008-03-17 22:17:56 +0000 | [diff] [blame] | 879 |        | 
 | 880 |     } while (true); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 881 |   } | 
 | 882 |    | 
 | 883 |   // If we reach here, than we know that the default branch is | 
 | 884 |   // possible.   | 
| Ted Kremenek | 5014ab1 | 2008-04-23 05:03:18 +0000 | [diff] [blame] | 885 |   if (DefaultFeasible) builder.generateDefaultCaseNode(DefaultSt); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 886 | } | 
 | 887 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 888 | //===----------------------------------------------------------------------===// | 
 | 889 | // Transfer functions: logical operations ('&&', '||'). | 
 | 890 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 891 |  | 
| Ted Kremenek | 4d4dd85 | 2008-02-13 17:41:41 +0000 | [diff] [blame] | 892 | void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 893 |                                     NodeSet& Dst) { | 
| Ted Kremenek | 9dca062 | 2008-02-19 00:22:37 +0000 | [diff] [blame] | 894 |    | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 895 |   assert (B->getOpcode() == BinaryOperator::LAnd || | 
 | 896 |           B->getOpcode() == BinaryOperator::LOr); | 
 | 897 |    | 
 | 898 |   assert (B == CurrentStmt && getCFG().isBlkExpr(B)); | 
 | 899 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 900 |   const GRState* state = GetState(Pred); | 
 | 901 |   SVal X = GetBlkExprSVal(state, B); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 902 |    | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 903 |   assert (X.isUndef()); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 904 |    | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 905 |   Expr* Ex = (Expr*) cast<UndefinedVal>(X).getData(); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 906 |    | 
 | 907 |   assert (Ex); | 
 | 908 |    | 
 | 909 |   if (Ex == B->getRHS()) { | 
 | 910 |      | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 911 |     X = GetBlkExprSVal(state, Ex); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 912 |      | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 913 |     // Handle undefined values. | 
| Ted Kremenek | 58b3321 | 2008-02-26 19:40:44 +0000 | [diff] [blame] | 914 |      | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 915 |     if (X.isUndef()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 916 |       MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X)); | 
| Ted Kremenek | 58b3321 | 2008-02-26 19:40:44 +0000 | [diff] [blame] | 917 |       return; | 
 | 918 |     } | 
 | 919 |      | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 920 |     // We took the RHS.  Because the value of the '&&' or '||' expression must | 
 | 921 |     // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0 | 
 | 922 |     // or 1.  Alternatively, we could take a lazy approach, and calculate this | 
 | 923 |     // value later when necessary.  We don't have the machinery in place for | 
 | 924 |     // this right now, and since most logical expressions are used for branches, | 
 | 925 |     // the payoff is not likely to be large.  Instead, we do eager evaluation. | 
 | 926 |          | 
 | 927 |     bool isFeasible = false; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 928 |     const GRState* NewState = Assume(state, X, true, isFeasible); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 929 |      | 
 | 930 |     if (isFeasible) | 
| Ted Kremenek | 0e561a3 | 2008-03-21 21:30:14 +0000 | [diff] [blame] | 931 |       MakeNode(Dst, B, Pred, | 
| Zhongxing Xu | 8cd5aae | 2008-10-30 05:33:54 +0000 | [diff] [blame] | 932 |                BindBlkExpr(NewState, B, MakeConstantVal(1U, B))); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 933 |        | 
 | 934 |     isFeasible = false; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 935 |     NewState = Assume(state, X, false, isFeasible); | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 936 |      | 
 | 937 |     if (isFeasible) | 
| Ted Kremenek | 0e561a3 | 2008-03-21 21:30:14 +0000 | [diff] [blame] | 938 |       MakeNode(Dst, B, Pred, | 
| Zhongxing Xu | 8cd5aae | 2008-10-30 05:33:54 +0000 | [diff] [blame] | 939 |                BindBlkExpr(NewState, B, MakeConstantVal(0U, B))); | 
| Ted Kremenek | f233d48 | 2008-02-05 00:26:40 +0000 | [diff] [blame] | 940 |   } | 
 | 941 |   else { | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 942 |     // We took the LHS expression.  Depending on whether we are '&&' or | 
 | 943 |     // '||' we know what the value of the expression is via properties of | 
 | 944 |     // the short-circuiting. | 
 | 945 |      | 
 | 946 |     X = MakeConstantVal( B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U, B); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 947 |     MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X)); | 
| Ted Kremenek | f233d48 | 2008-02-05 00:26:40 +0000 | [diff] [blame] | 948 |   } | 
| Ted Kremenek | f233d48 | 2008-02-05 00:26:40 +0000 | [diff] [blame] | 949 | } | 
| Ted Kremenek | 05a2378 | 2008-02-26 19:05:15 +0000 | [diff] [blame] | 950 |   | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 951 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | ec96a2d | 2008-04-16 18:39:06 +0000 | [diff] [blame] | 952 | // Transfer functions: Loads and stores. | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 953 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | d27f816 | 2008-01-15 23:55:06 +0000 | [diff] [blame] | 954 |  | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 955 | void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst, | 
 | 956 |                                     bool asLValue) { | 
| Ted Kremenek | 3271f8d | 2008-02-07 04:16:04 +0000 | [diff] [blame] | 957 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 958 |   const GRState* state = GetState(Pred); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 959 |  | 
| Douglas Gregor | 8e9bebd | 2008-10-21 16:13:35 +0000 | [diff] [blame] | 960 |   const NamedDecl* D = Ex->getDecl(); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 961 |  | 
 | 962 |   if (const VarDecl* VD = dyn_cast<VarDecl>(D)) { | 
 | 963 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 964 |     SVal V = StateMgr.GetLValue(state, VD); | 
| Zhongxing Xu | a758173 | 2008-10-17 02:20:14 +0000 | [diff] [blame] | 965 |  | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 966 |     if (asLValue) | 
| Ted Kremenek | 7090d54 | 2009-05-07 18:27:16 +0000 | [diff] [blame] | 967 |       MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), | 
 | 968 |                ProgramPoint::PostLValueKind); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 969 |     else | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 970 |       EvalLoad(Dst, Ex, Pred, state, V); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 971 |     return; | 
 | 972 |  | 
 | 973 |   } else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) { | 
 | 974 |     assert(!asLValue && "EnumConstantDecl does not have lvalue."); | 
 | 975 |  | 
 | 976 |     BasicValueFactory& BasicVals = StateMgr.getBasicVals(); | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 977 |     SVal V = nonloc::ConcreteInt(BasicVals.getValue(ED->getInitVal())); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 978 |     MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V)); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 979 |     return; | 
 | 980 |  | 
 | 981 |   } else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) { | 
| Ted Kremenek | 5631a73 | 2008-11-15 02:35:08 +0000 | [diff] [blame] | 982 |     assert(asLValue); | 
| Zhongxing Xu | 369f447 | 2009-04-20 05:24:46 +0000 | [diff] [blame] | 983 |     SVal V = ValMgr.getFunctionPointer(FD); | 
| Ted Kremenek | 7090d54 | 2009-05-07 18:27:16 +0000 | [diff] [blame] | 984 |     MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), | 
 | 985 |              ProgramPoint::PostLValueKind); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 986 |     return; | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 987 |   } | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 988 |    | 
 | 989 |   assert (false && | 
 | 990 |           "ValueDecl support for this ValueDecl not implemented."); | 
| Ted Kremenek | 3271f8d | 2008-02-07 04:16:04 +0000 | [diff] [blame] | 991 | } | 
 | 992 |  | 
| Ted Kremenek | 540cbe2 | 2008-04-22 04:56:29 +0000 | [diff] [blame] | 993 | /// VisitArraySubscriptExpr - Transfer function for array accesses | 
 | 994 | void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, NodeTy* Pred, | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 995 |                                            NodeSet& Dst, bool asLValue) { | 
| Ted Kremenek | 540cbe2 | 2008-04-22 04:56:29 +0000 | [diff] [blame] | 996 |    | 
 | 997 |   Expr* Base = A->getBase()->IgnoreParens(); | 
| Ted Kremenek | 4d0348b | 2008-04-29 23:24:44 +0000 | [diff] [blame] | 998 |   Expr* Idx  = A->getIdx()->IgnoreParens(); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 999 |   NodeSet Tmp; | 
| Ted Kremenek | 265a305 | 2009-02-24 02:23:11 +0000 | [diff] [blame] | 1000 |    | 
 | 1001 |   if (Base->getType()->isVectorType()) { | 
 | 1002 |     // For vector types get its lvalue. | 
 | 1003 |     // FIXME: This may not be correct.  Is the rvalue of a vector its location? | 
 | 1004 |     //  In fact, I think this is just a hack.  We need to get the right | 
 | 1005 |     // semantics. | 
 | 1006 |     VisitLValue(Base, Pred, Tmp); | 
 | 1007 |   } | 
 | 1008 |   else   | 
 | 1009 |     Visit(Base, Pred, Tmp);   // Get Base's rvalue, which should be an LocVal. | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1010 |    | 
| Ted Kremenek | d9bc33e | 2008-10-17 00:51:01 +0000 | [diff] [blame] | 1011 |   for (NodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {     | 
| Ted Kremenek | 4d0348b | 2008-04-29 23:24:44 +0000 | [diff] [blame] | 1012 |     NodeSet Tmp2; | 
| Ted Kremenek | d9bc33e | 2008-10-17 00:51:01 +0000 | [diff] [blame] | 1013 |     Visit(Idx, *I1, Tmp2);     // Evaluate the index. | 
| Ted Kremenek | 4d0348b | 2008-04-29 23:24:44 +0000 | [diff] [blame] | 1014 |        | 
 | 1015 |     for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1016 |       const GRState* state = GetState(*I2); | 
| Ted Kremenek | f936f45 | 2009-05-04 06:18:28 +0000 | [diff] [blame] | 1017 |       SVal V = StateMgr.GetLValue(state, A->getType(), | 
 | 1018 |                                   GetSVal(state, Base), | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1019 |                                   GetSVal(state, Idx)); | 
| Ted Kremenek | 4d0348b | 2008-04-29 23:24:44 +0000 | [diff] [blame] | 1020 |  | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 1021 |       if (asLValue) | 
| Ted Kremenek | 7090d54 | 2009-05-07 18:27:16 +0000 | [diff] [blame] | 1022 |         MakeNode(Dst, A, *I2, BindExpr(state, A, V), | 
 | 1023 |                  ProgramPoint::PostLValueKind); | 
| Ted Kremenek | 4d0348b | 2008-04-29 23:24:44 +0000 | [diff] [blame] | 1024 |       else | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1025 |         EvalLoad(Dst, A, *I2, state, V); | 
| Ted Kremenek | 4d0348b | 2008-04-29 23:24:44 +0000 | [diff] [blame] | 1026 |     } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1027 |   } | 
| Ted Kremenek | 540cbe2 | 2008-04-22 04:56:29 +0000 | [diff] [blame] | 1028 | } | 
 | 1029 |  | 
| Ted Kremenek | 469ecbd | 2008-04-21 23:43:38 +0000 | [diff] [blame] | 1030 | /// VisitMemberExpr - Transfer function for member expressions. | 
 | 1031 | void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 1032 |                                    NodeSet& Dst, bool asLValue) { | 
| Ted Kremenek | 469ecbd | 2008-04-21 23:43:38 +0000 | [diff] [blame] | 1033 |    | 
 | 1034 |   Expr* Base = M->getBase()->IgnoreParens(); | 
| Ted Kremenek | 469ecbd | 2008-04-21 23:43:38 +0000 | [diff] [blame] | 1035 |   NodeSet Tmp; | 
| Ted Kremenek | 5c456fe | 2008-10-18 03:28:48 +0000 | [diff] [blame] | 1036 |    | 
 | 1037 |   if (M->isArrow())  | 
 | 1038 |     Visit(Base, Pred, Tmp);        // p->f = ...  or   ... = p->f | 
 | 1039 |   else | 
 | 1040 |     VisitLValue(Base, Pred, Tmp);  // x.f = ...   or   ... = x.f | 
 | 1041 |      | 
| Douglas Gregor | 86f1940 | 2008-12-20 23:49:58 +0000 | [diff] [blame] | 1042 |   FieldDecl *Field = dyn_cast<FieldDecl>(M->getMemberDecl()); | 
 | 1043 |   if (!Field) // FIXME: skipping member expressions for non-fields | 
 | 1044 |     return; | 
 | 1045 |  | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 1046 |   for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1047 |     const GRState* state = GetState(*I); | 
| Ted Kremenek | d9bc33e | 2008-10-17 00:51:01 +0000 | [diff] [blame] | 1048 |     // FIXME: Should we insert some assumption logic in here to determine | 
 | 1049 |     // if "Base" is a valid piece of memory?  Before we put this assumption | 
| Douglas Gregor | 86f1940 | 2008-12-20 23:49:58 +0000 | [diff] [blame] | 1050 |     // later when using FieldOffset lvals (which we no longer have). | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1051 |     SVal L = StateMgr.GetLValue(state, GetSVal(state, Base), Field); | 
| Ted Kremenek | d9bc33e | 2008-10-17 00:51:01 +0000 | [diff] [blame] | 1052 |  | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 1053 |     if (asLValue) | 
| Ted Kremenek | 7090d54 | 2009-05-07 18:27:16 +0000 | [diff] [blame] | 1054 |       MakeNode(Dst, M, *I, BindExpr(state, M, L), | 
 | 1055 |                ProgramPoint::PostLValueKind); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 1056 |     else | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1057 |       EvalLoad(Dst, M, *I, state, L); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1058 |   } | 
| Ted Kremenek | 469ecbd | 2008-04-21 23:43:38 +0000 | [diff] [blame] | 1059 | } | 
 | 1060 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1061 | /// EvalBind - Handle the semantics of binding a value to a specific location. | 
 | 1062 | ///  This method is used by EvalStore and (soon) VisitDeclStmt, and others. | 
 | 1063 | void GRExprEngine::EvalBind(NodeSet& Dst, Expr* Ex, NodeTy* Pred, | 
 | 1064 |                              const GRState* state, SVal location, SVal Val) { | 
 | 1065 |  | 
| Ted Kremenek | 41573eb | 2009-02-14 01:43:44 +0000 | [diff] [blame] | 1066 |   const GRState* newState = 0; | 
 | 1067 |    | 
 | 1068 |   if (location.isUnknown()) { | 
 | 1069 |     // We know that the new state will be the same as the old state since | 
 | 1070 |     // the location of the binding is "unknown".  Consequently, there | 
 | 1071 |     // is no reason to just create a new node. | 
 | 1072 |     newState = state; | 
 | 1073 |   } | 
 | 1074 |   else { | 
 | 1075 |     // We are binding to a value other than 'unknown'.  Perform the binding | 
 | 1076 |     // using the StoreManager. | 
 | 1077 |     newState = StateMgr.BindLoc(state, cast<Loc>(location), Val); | 
 | 1078 |   } | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1079 |  | 
| Ted Kremenek | 41573eb | 2009-02-14 01:43:44 +0000 | [diff] [blame] | 1080 |   // The next thing to do is check if the GRTransferFuncs object wants to | 
 | 1081 |   // update the state based on the new binding.  If the GRTransferFunc object | 
 | 1082 |   // doesn't do anything, just auto-propagate the current state. | 
 | 1083 |   GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, Pred, newState, Ex, | 
 | 1084 |                                   newState != state); | 
 | 1085 |      | 
 | 1086 |   getTF().EvalBind(BuilderRef, location, Val); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1087 | } | 
 | 1088 |  | 
 | 1089 | /// EvalStore - Handle the semantics of a store via an assignment. | 
 | 1090 | ///  @param Dst The node set to store generated state nodes | 
 | 1091 | ///  @param Ex The expression representing the location of the store | 
 | 1092 | ///  @param state The current simulation state | 
 | 1093 | ///  @param location The location to store the value | 
 | 1094 | ///  @param Val The value to be stored | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1095 | void GRExprEngine::EvalStore(NodeSet& Dst, Expr* Ex, NodeTy* Pred, | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1096 |                              const GRState* state, SVal location, SVal Val, | 
 | 1097 |                              const void *tag) { | 
| Ted Kremenek | ec96a2d | 2008-04-16 18:39:06 +0000 | [diff] [blame] | 1098 |    | 
 | 1099 |   assert (Builder && "GRStmtNodeBuilder must be defined."); | 
 | 1100 |    | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1101 |   // Evaluate the location (checks for bad dereferences). | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1102 |   Pred = EvalLocation(Ex, Pred, state, location, tag); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1103 |    | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1104 |   if (!Pred) | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1105 |     return; | 
| Ted Kremenek | b053396 | 2008-04-18 20:35:30 +0000 | [diff] [blame] | 1106 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1107 |   assert (!location.isUndef()); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1108 |   state = GetState(Pred); | 
 | 1109 |  | 
 | 1110 |   // Proceed with the store.   | 
 | 1111 |   SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind); | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1112 |   SaveAndRestore<const void*> OldTag(Builder->Tag); | 
 | 1113 |   Builder->PointKind = ProgramPoint::PostStoreKind; | 
 | 1114 |   Builder->Tag = tag; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1115 |   EvalBind(Dst, Ex, Pred, state, location, Val); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1116 | } | 
 | 1117 |  | 
 | 1118 | void GRExprEngine::EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred, | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1119 |                             const GRState* state, SVal location, | 
 | 1120 |                             const void *tag) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1121 |  | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1122 |   // Evaluate the location (checks for bad dereferences).   | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1123 |   Pred = EvalLocation(Ex, Pred, state, location, tag); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1124 |    | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1125 |   if (!Pred) | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1126 |     return; | 
 | 1127 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1128 |   state = GetState(Pred); | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1129 |    | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1130 |   // Proceed with the load. | 
| Ted Kremenek | 982e674 | 2008-08-28 18:43:46 +0000 | [diff] [blame] | 1131 |   ProgramPoint::Kind K = ProgramPoint::PostLoadKind; | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1132 |  | 
 | 1133 |   // FIXME: Currently symbolic analysis "generates" new symbols | 
 | 1134 |   //  for the contents of values.  We need a better approach. | 
 | 1135 |  | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1136 |   if (location.isUnknown()) { | 
| Ted Kremenek | 436f2b9 | 2008-04-30 04:23:07 +0000 | [diff] [blame] | 1137 |     // This is important.  We must nuke the old binding. | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1138 |     MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, UnknownVal()), K, tag); | 
| Ted Kremenek | 436f2b9 | 2008-04-30 04:23:07 +0000 | [diff] [blame] | 1139 |   } | 
| Zhongxing Xu | d5b499d | 2008-11-28 08:34:30 +0000 | [diff] [blame] | 1140 |   else { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1141 |     SVal V = GetSVal(state, cast<Loc>(location), Ex->getType()); | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1142 |     MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), K, tag); | 
| Zhongxing Xu | d5b499d | 2008-11-28 08:34:30 +0000 | [diff] [blame] | 1143 |   } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1144 | } | 
 | 1145 |  | 
| Ted Kremenek | 82bae3f | 2008-09-20 01:50:34 +0000 | [diff] [blame] | 1146 | void GRExprEngine::EvalStore(NodeSet& Dst, Expr* Ex, Expr* StoreE, NodeTy* Pred, | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1147 |                              const GRState* state, SVal location, SVal Val, | 
 | 1148 |                              const void *tag) { | 
| Ted Kremenek | 82bae3f | 2008-09-20 01:50:34 +0000 | [diff] [blame] | 1149 |   | 
 | 1150 |   NodeSet TmpDst; | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1151 |   EvalStore(TmpDst, StoreE, Pred, state, location, Val, tag); | 
| Ted Kremenek | 82bae3f | 2008-09-20 01:50:34 +0000 | [diff] [blame] | 1152 |  | 
 | 1153 |   for (NodeSet::iterator I=TmpDst.begin(), E=TmpDst.end(); I!=E; ++I) | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1154 |     MakeNode(Dst, Ex, *I, (*I)->getState(), ProgramPoint::PostStmtKind, tag); | 
| Ted Kremenek | 82bae3f | 2008-09-20 01:50:34 +0000 | [diff] [blame] | 1155 | } | 
 | 1156 |  | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1157 | GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred, | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1158 |                                                  const GRState* state, | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1159 |                                                  SVal location, | 
 | 1160 |                                                  const void *tag) { | 
 | 1161 |    | 
 | 1162 |   SaveAndRestore<const void*> OldTag(Builder->Tag); | 
 | 1163 |   Builder->Tag = tag; | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1164 |    | 
 | 1165 |   // Check for loads/stores from/to undefined values.   | 
 | 1166 |   if (location.isUndef()) { | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1167 |     NodeTy* N = | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1168 |       Builder->generateNode(Ex, state, Pred, | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1169 |                             ProgramPoint::PostUndefLocationCheckFailedKind); | 
| Ted Kremenek | 331b0ac | 2008-06-18 05:34:07 +0000 | [diff] [blame] | 1170 |      | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1171 |     if (N) { | 
 | 1172 |       N->markAsSink(); | 
 | 1173 |       UndefDeref.insert(N); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1174 |     } | 
 | 1175 |      | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1176 |     return 0; | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1177 |   } | 
 | 1178 |    | 
 | 1179 |   // Check for loads/stores from/to unknown locations.  Treat as No-Ops. | 
 | 1180 |   if (location.isUnknown()) | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1181 |     return Pred; | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1182 |    | 
 | 1183 |   // During a load, one of two possible situations arise: | 
 | 1184 |   //  (1) A crash, because the location (pointer) was NULL. | 
 | 1185 |   //  (2) The location (pointer) is not NULL, and the dereference works. | 
 | 1186 |   //  | 
 | 1187 |   // We add these assumptions. | 
 | 1188 |    | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 1189 |   Loc LV = cast<Loc>(location);     | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1190 |    | 
 | 1191 |   // "Assume" that the pointer is not NULL. | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1192 |   bool isFeasibleNotNull = false; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1193 |   const GRState* StNotNull = Assume(state, LV, true, isFeasibleNotNull); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1194 |    | 
 | 1195 |   // "Assume" that the pointer is NULL. | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1196 |   bool isFeasibleNull = false; | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 1197 |   const GRState *StNull = Assume(state, LV, false, isFeasibleNull); | 
| Zhongxing Xu | a1718c7 | 2009-04-03 07:33:13 +0000 | [diff] [blame] | 1198 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1199 |   if (isFeasibleNull) { | 
 | 1200 |      | 
| Ted Kremenek | 7360fda | 2008-09-18 23:09:54 +0000 | [diff] [blame] | 1201 |     // Use the Generic Data Map to mark in the state what lval was null. | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 1202 |     const SVal* PersistentLV = getBasicVals().getPersistentSVal(LV); | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 1203 |     StNull = StNull->set<GRState::NullDerefTag>(PersistentLV); | 
| Ted Kremenek | 7360fda | 2008-09-18 23:09:54 +0000 | [diff] [blame] | 1204 |      | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1205 |     // We don't use "MakeNode" here because the node will be a sink | 
 | 1206 |     // and we have no intention of processing it later. | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1207 |     NodeTy* NullNode = | 
 | 1208 |       Builder->generateNode(Ex, StNull, Pred,  | 
 | 1209 |                             ProgramPoint::PostNullCheckFailedKind); | 
| Ted Kremenek | 331b0ac | 2008-06-18 05:34:07 +0000 | [diff] [blame] | 1210 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1211 |     if (NullNode) { | 
 | 1212 |        | 
 | 1213 |       NullNode->markAsSink(); | 
 | 1214 |        | 
 | 1215 |       if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode); | 
 | 1216 |       else ExplicitNullDeref.insert(NullNode); | 
 | 1217 |     } | 
 | 1218 |   } | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1219 |    | 
 | 1220 |   if (!isFeasibleNotNull) | 
 | 1221 |     return 0; | 
| Zhongxing Xu | 60156f0 | 2008-11-08 03:45:42 +0000 | [diff] [blame] | 1222 |  | 
 | 1223 |   // Check for out-of-bound array access. | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1224 |   if (isa<loc::MemRegionVal>(LV)) { | 
| Zhongxing Xu | 60156f0 | 2008-11-08 03:45:42 +0000 | [diff] [blame] | 1225 |     const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion(); | 
 | 1226 |     if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) { | 
 | 1227 |       // Get the index of the accessed element. | 
 | 1228 |       SVal Idx = ER->getIndex(); | 
 | 1229 |       // Get the extent of the array. | 
| Zhongxing Xu | 1ed8d4b | 2008-11-24 07:02:06 +0000 | [diff] [blame] | 1230 |       SVal NumElements = getStoreManager().getSizeInElements(StNotNull, | 
 | 1231 |                                                           ER->getSuperRegion()); | 
| Zhongxing Xu | 60156f0 | 2008-11-08 03:45:42 +0000 | [diff] [blame] | 1232 |  | 
 | 1233 |       bool isFeasibleInBound = false; | 
 | 1234 |       const GRState* StInBound = AssumeInBound(StNotNull, Idx, NumElements,  | 
 | 1235 |                                                true, isFeasibleInBound); | 
 | 1236 |  | 
 | 1237 |       bool isFeasibleOutBound = false; | 
 | 1238 |       const GRState* StOutBound = AssumeInBound(StNotNull, Idx, NumElements,  | 
 | 1239 |                                                 false, isFeasibleOutBound); | 
 | 1240 |  | 
| Zhongxing Xu | e8a964b | 2008-11-22 13:21:46 +0000 | [diff] [blame] | 1241 |       if (isFeasibleOutBound) { | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1242 |         // Report warning.  Make sink node manually. | 
 | 1243 |         NodeTy* OOBNode = | 
 | 1244 |           Builder->generateNode(Ex, StOutBound, Pred, | 
 | 1245 |                                 ProgramPoint::PostOutOfBoundsCheckFailedKind); | 
| Zhongxing Xu | 1c0c233 | 2008-11-23 05:52:28 +0000 | [diff] [blame] | 1246 |  | 
 | 1247 |         if (OOBNode) { | 
 | 1248 |           OOBNode->markAsSink(); | 
 | 1249 |  | 
 | 1250 |           if (isFeasibleInBound) | 
 | 1251 |             ImplicitOOBMemAccesses.insert(OOBNode); | 
 | 1252 |           else | 
 | 1253 |             ExplicitOOBMemAccesses.insert(OOBNode); | 
 | 1254 |         } | 
| Zhongxing Xu | e8a964b | 2008-11-22 13:21:46 +0000 | [diff] [blame] | 1255 |       } | 
 | 1256 |  | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1257 |       if (!isFeasibleInBound) | 
 | 1258 |         return 0; | 
 | 1259 |        | 
 | 1260 |       StNotNull = StInBound; | 
| Zhongxing Xu | 60156f0 | 2008-11-08 03:45:42 +0000 | [diff] [blame] | 1261 |     } | 
 | 1262 |   } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 1263 |    | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1264 |   // Generate a new node indicating the checks succeed. | 
 | 1265 |   return Builder->generateNode(Ex, StNotNull, Pred, | 
 | 1266 |                                ProgramPoint::PostLocationChecksSucceedKind); | 
| Ted Kremenek | ec96a2d | 2008-04-16 18:39:06 +0000 | [diff] [blame] | 1267 | } | 
 | 1268 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1269 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1270 | // Transfer function: OSAtomics. | 
 | 1271 | // | 
 | 1272 | // FIXME: Eventually refactor into a more "plugin" infrastructure. | 
 | 1273 | //===----------------------------------------------------------------------===// | 
 | 1274 |  | 
 | 1275 | // Mac OS X: | 
 | 1276 | // http://developer.apple.com/documentation/Darwin/Reference/Manpages/man3 | 
 | 1277 | // atomic.3.html | 
 | 1278 | // | 
 | 1279 | static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst, | 
 | 1280 |                                        GRExprEngine& Engine, | 
 | 1281 |                                        GRStmtNodeBuilder<GRState>& Builder, | 
 | 1282 |                                        CallExpr* CE, SVal L,                  | 
 | 1283 |                                        ExplodedNode<GRState>* Pred) { | 
 | 1284 |  | 
 | 1285 |   // Not enough arguments to match OSAtomicCompareAndSwap? | 
 | 1286 |   if (CE->getNumArgs() != 3) | 
 | 1287 |     return false; | 
 | 1288 |    | 
 | 1289 |   ASTContext &C = Engine.getContext(); | 
 | 1290 |   Expr *oldValueExpr = CE->getArg(0); | 
 | 1291 |   QualType oldValueType = C.getCanonicalType(oldValueExpr->getType()); | 
 | 1292 |  | 
 | 1293 |   Expr *newValueExpr = CE->getArg(1); | 
 | 1294 |   QualType newValueType = C.getCanonicalType(newValueExpr->getType()); | 
 | 1295 |    | 
 | 1296 |   // Do the types of 'oldValue' and 'newValue' match? | 
 | 1297 |   if (oldValueType != newValueType) | 
 | 1298 |     return false; | 
 | 1299 |    | 
 | 1300 |   Expr *theValueExpr = CE->getArg(2); | 
 | 1301 |   const PointerType *theValueType = theValueExpr->getType()->getAsPointerType(); | 
 | 1302 |    | 
 | 1303 |   // theValueType not a pointer? | 
 | 1304 |   if (!theValueType) | 
 | 1305 |     return false; | 
 | 1306 |    | 
 | 1307 |   QualType theValueTypePointee = | 
 | 1308 |     C.getCanonicalType(theValueType->getPointeeType()).getUnqualifiedType(); | 
 | 1309 |    | 
 | 1310 |   // The pointee must match newValueType and oldValueType. | 
 | 1311 |   if (theValueTypePointee != newValueType) | 
 | 1312 |     return false; | 
 | 1313 |    | 
 | 1314 |   static unsigned magic_load = 0; | 
 | 1315 |   static unsigned magic_store = 0; | 
 | 1316 |  | 
 | 1317 |   const void *OSAtomicLoadTag = &magic_load; | 
 | 1318 |   const void *OSAtomicStoreTag = &magic_store; | 
 | 1319 |    | 
 | 1320 |   // Load 'theValue'. | 
 | 1321 |   GRStateManager &StateMgr = Engine.getStateManager(); | 
 | 1322 |   const GRState *state = Pred->getState(); | 
 | 1323 |   ExplodedNodeSet<GRState> Tmp; | 
 | 1324 |   SVal location = StateMgr.GetSVal(state, theValueExpr); | 
 | 1325 |   Engine.EvalLoad(Tmp, theValueExpr, Pred, state, location, OSAtomicLoadTag); | 
 | 1326 |  | 
 | 1327 |   for (ExplodedNodeSet<GRState>::iterator I = Tmp.begin(), E = Tmp.end(); | 
 | 1328 |        I != E; ++I) { | 
 | 1329 |    | 
 | 1330 |     ExplodedNode<GRState> *N = *I; | 
 | 1331 |     const GRState *stateLoad = N->getState(); | 
 | 1332 |     SVal theValueVal = StateMgr.GetSVal(stateLoad, theValueExpr); | 
 | 1333 |     SVal oldValueVal = StateMgr.GetSVal(stateLoad, oldValueExpr); | 
 | 1334 |          | 
 | 1335 |     // Perform the comparison. | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 1336 |     SVal Cmp = Engine.EvalBinOp(stateLoad, | 
 | 1337 |                                 BinaryOperator::EQ, theValueVal, oldValueVal, | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1338 |                                 Engine.getContext().IntTy); | 
 | 1339 |     bool isFeasible = false; | 
 | 1340 |     const GRState *stateEqual = StateMgr.Assume(stateLoad, Cmp, true, | 
 | 1341 |                                                 isFeasible); | 
 | 1342 |      | 
 | 1343 |     // Were they equal? | 
 | 1344 |     if (isFeasible) { | 
 | 1345 |       // Perform the store. | 
 | 1346 |       ExplodedNodeSet<GRState> TmpStore; | 
 | 1347 |       Engine.EvalStore(TmpStore, theValueExpr, N, stateEqual, location,  | 
 | 1348 |                        StateMgr.GetSVal(stateEqual, newValueExpr), | 
 | 1349 |                        OSAtomicStoreTag); | 
 | 1350 |        | 
 | 1351 |       // Now bind the result of the comparison. | 
 | 1352 |       for (ExplodedNodeSet<GRState>::iterator I2 = TmpStore.begin(), | 
 | 1353 |            E2 = TmpStore.end(); I2 != E2; ++I2) { | 
 | 1354 |         ExplodedNode<GRState> *predNew = *I2; | 
 | 1355 |         const GRState *stateNew = predNew->getState(); | 
 | 1356 |         SVal Res = Engine.getValueManager().makeTruthVal(true, CE->getType()); | 
 | 1357 |         Engine.MakeNode(Dst, CE, predNew, Engine.BindExpr(stateNew, CE, Res)); | 
 | 1358 |       } | 
 | 1359 |     } | 
 | 1360 |      | 
 | 1361 |     // Were they not equal? | 
 | 1362 |     isFeasible = false; | 
 | 1363 |     const GRState *stateNotEqual = StateMgr.Assume(stateLoad, Cmp, false, | 
 | 1364 |                                                    isFeasible); | 
 | 1365 |      | 
 | 1366 |     if (isFeasible) { | 
 | 1367 |       SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType()); | 
 | 1368 |       Engine.MakeNode(Dst, CE, N, Engine.BindExpr(stateNotEqual, CE, Res)); | 
 | 1369 |     } | 
 | 1370 |   } | 
 | 1371 |        | 
 | 1372 |   return true; | 
 | 1373 | } | 
 | 1374 |  | 
 | 1375 | static bool EvalOSAtomic(ExplodedNodeSet<GRState>& Dst, | 
 | 1376 |                          GRExprEngine& Engine, | 
 | 1377 |                          GRStmtNodeBuilder<GRState>& Builder, | 
 | 1378 |                          CallExpr* CE, SVal L, | 
 | 1379 |                          ExplodedNode<GRState>* Pred) { | 
| Zhongxing Xu | 369f447 | 2009-04-20 05:24:46 +0000 | [diff] [blame] | 1380 |   const FunctionDecl* FD = L.getAsFunctionDecl(); | 
 | 1381 |   if (!FD) | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1382 |     return false; | 
| Zhongxing Xu | 369f447 | 2009-04-20 05:24:46 +0000 | [diff] [blame] | 1383 |  | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1384 |   const char *FName = FD->getNameAsCString(); | 
 | 1385 |    | 
 | 1386 |   // Check for compare and swap. | 
| Ted Kremenek | b3bf76f | 2009-04-11 00:54:13 +0000 | [diff] [blame] | 1387 |   if (strncmp(FName, "OSAtomicCompareAndSwap", 22) == 0 || | 
 | 1388 |       strncmp(FName, "objc_atomicCompareAndSwap", 25) == 0) | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1389 |     return EvalOSAtomicCompareAndSwap(Dst, Engine, Builder, CE, L, Pred); | 
| Ted Kremenek | b3bf76f | 2009-04-11 00:54:13 +0000 | [diff] [blame] | 1390 |  | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1391 |   // FIXME: Other atomics. | 
 | 1392 |   return false; | 
 | 1393 | } | 
 | 1394 |  | 
 | 1395 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1396 | // Transfer function: Function calls. | 
 | 1397 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | 1670e40 | 2009-04-11 00:11:10 +0000 | [diff] [blame] | 1398 |  | 
 | 1399 | void GRExprEngine::EvalCall(NodeSet& Dst, CallExpr* CE, SVal L, NodeTy* Pred) { | 
 | 1400 |   assert (Builder && "GRStmtNodeBuilder must be defined."); | 
 | 1401 |    | 
 | 1402 |   // FIXME: Allow us to chain together transfer functions. | 
 | 1403 |   if (EvalOSAtomic(Dst, *this, *Builder, CE, L, Pred)) | 
 | 1404 |       return; | 
 | 1405 |        | 
 | 1406 |   getTF().EvalCall(Dst, *this, *Builder, CE, L, Pred); | 
 | 1407 | } | 
 | 1408 |  | 
| Ted Kremenek | de43424 | 2008-02-19 01:44:53 +0000 | [diff] [blame] | 1409 | void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 1410 |                              CallExpr::arg_iterator AI, | 
 | 1411 |                              CallExpr::arg_iterator AE, | 
| Douglas Gregor | 9d293df | 2008-10-28 00:22:11 +0000 | [diff] [blame] | 1412 |                              NodeSet& Dst) | 
 | 1413 | { | 
 | 1414 |   // Determine the type of function we're calling (if available). | 
| Douglas Gregor | 72564e7 | 2009-02-26 23:50:07 +0000 | [diff] [blame] | 1415 |   const FunctionProtoType *Proto = NULL; | 
| Douglas Gregor | 9d293df | 2008-10-28 00:22:11 +0000 | [diff] [blame] | 1416 |   QualType FnType = CE->getCallee()->IgnoreParens()->getType(); | 
 | 1417 |   if (const PointerType *FnTypePtr = FnType->getAsPointerType()) | 
| Douglas Gregor | 72564e7 | 2009-02-26 23:50:07 +0000 | [diff] [blame] | 1418 |     Proto = FnTypePtr->getPointeeType()->getAsFunctionProtoType(); | 
| Douglas Gregor | 9d293df | 2008-10-28 00:22:11 +0000 | [diff] [blame] | 1419 |  | 
 | 1420 |   VisitCallRec(CE, Pred, AI, AE, Dst, Proto, /*ParamIdx=*/0); | 
 | 1421 | } | 
 | 1422 |  | 
 | 1423 | void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, | 
 | 1424 |                                 CallExpr::arg_iterator AI, | 
 | 1425 |                                 CallExpr::arg_iterator AE, | 
| Douglas Gregor | 72564e7 | 2009-02-26 23:50:07 +0000 | [diff] [blame] | 1426 |                                 NodeSet& Dst, const FunctionProtoType *Proto, | 
| Douglas Gregor | 9d293df | 2008-10-28 00:22:11 +0000 | [diff] [blame] | 1427 |                                 unsigned ParamIdx) { | 
| Ted Kremenek | de43424 | 2008-02-19 01:44:53 +0000 | [diff] [blame] | 1428 |    | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 1429 |   // Process the arguments. | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 1430 |   if (AI != AE) { | 
| Douglas Gregor | 9d293df | 2008-10-28 00:22:11 +0000 | [diff] [blame] | 1431 |     // If the call argument is being bound to a reference parameter, | 
 | 1432 |     // visit it as an lvalue, not an rvalue. | 
 | 1433 |     bool VisitAsLvalue = false; | 
 | 1434 |     if (Proto && ParamIdx < Proto->getNumArgs()) | 
 | 1435 |       VisitAsLvalue = Proto->getArgType(ParamIdx)->isReferenceType(); | 
 | 1436 |  | 
 | 1437 |     NodeSet DstTmp;   | 
 | 1438 |     if (VisitAsLvalue) | 
 | 1439 |       VisitLValue(*AI, Pred, DstTmp);     | 
 | 1440 |     else | 
 | 1441 |       Visit(*AI, Pred, DstTmp);     | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 1442 |     ++AI; | 
 | 1443 |      | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1444 |     for (NodeSet::iterator DI=DstTmp.begin(), DE=DstTmp.end(); DI != DE; ++DI) | 
| Douglas Gregor | 9d293df | 2008-10-28 00:22:11 +0000 | [diff] [blame] | 1445 |       VisitCallRec(CE, *DI, AI, AE, Dst, Proto, ParamIdx + 1); | 
| Ted Kremenek | de43424 | 2008-02-19 01:44:53 +0000 | [diff] [blame] | 1446 |      | 
 | 1447 |     return; | 
 | 1448 |   } | 
 | 1449 |  | 
 | 1450 |   // If we reach here we have processed all of the arguments.  Evaluate | 
 | 1451 |   // the callee expression. | 
| Ted Kremenek | a1354a5 | 2008-03-03 16:47:31 +0000 | [diff] [blame] | 1452 |    | 
| Ted Kremenek | 994a09b | 2008-02-25 21:16:03 +0000 | [diff] [blame] | 1453 |   NodeSet DstTmp;     | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 1454 |   Expr* Callee = CE->getCallee()->IgnoreParens(); | 
| Ted Kremenek | a1354a5 | 2008-03-03 16:47:31 +0000 | [diff] [blame] | 1455 |  | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 1456 |   Visit(Callee, Pred, DstTmp); | 
| Ted Kremenek | a1354a5 | 2008-03-03 16:47:31 +0000 | [diff] [blame] | 1457 |    | 
| Ted Kremenek | de43424 | 2008-02-19 01:44:53 +0000 | [diff] [blame] | 1458 |   // Finally, evaluate the function call. | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 1459 |   for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) { | 
 | 1460 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1461 |     const GRState* state = GetState(*DI); | 
 | 1462 |     SVal L = GetSVal(state, Callee); | 
| Ted Kremenek | de43424 | 2008-02-19 01:44:53 +0000 | [diff] [blame] | 1463 |  | 
| Ted Kremenek | a1354a5 | 2008-03-03 16:47:31 +0000 | [diff] [blame] | 1464 |     // FIXME: Add support for symbolic function calls (calls involving | 
 | 1465 |     //  function pointer values that are symbolic). | 
 | 1466 |      | 
 | 1467 |     // Check for undefined control-flow or calls to NULL. | 
 | 1468 |      | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 1469 |     if (L.isUndef() || isa<loc::ConcreteInt>(L)) {       | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1470 |       NodeTy* N = Builder->generateNode(CE, state, *DI); | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1471 |        | 
| Ted Kremenek | 2ded35a | 2008-02-29 23:53:11 +0000 | [diff] [blame] | 1472 |       if (N) { | 
 | 1473 |         N->markAsSink(); | 
 | 1474 |         BadCalls.insert(N); | 
 | 1475 |       } | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1476 |        | 
| Ted Kremenek | de43424 | 2008-02-19 01:44:53 +0000 | [diff] [blame] | 1477 |       continue; | 
| Ted Kremenek | 4bf38da | 2008-03-05 21:15:02 +0000 | [diff] [blame] | 1478 |     } | 
 | 1479 |      | 
 | 1480 |     // Check for the "noreturn" attribute. | 
 | 1481 |      | 
 | 1482 |     SaveAndRestore<bool> OldSink(Builder->BuildSinks); | 
| Zhongxing Xu | 369f447 | 2009-04-20 05:24:46 +0000 | [diff] [blame] | 1483 |     const FunctionDecl* FD = L.getAsFunctionDecl(); | 
 | 1484 |     if (FD) {       | 
| Ted Kremenek | b725232 | 2009-04-10 00:01:14 +0000 | [diff] [blame] | 1485 |       if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>()) | 
| Ted Kremenek | 4bf38da | 2008-03-05 21:15:02 +0000 | [diff] [blame] | 1486 |         Builder->BuildSinks = true; | 
| Ted Kremenek | 636e6ba | 2008-03-14 21:58:42 +0000 | [diff] [blame] | 1487 |       else { | 
 | 1488 |         // HACK: Some functions are not marked noreturn, and don't return. | 
 | 1489 |         //  Here are a few hardwired ones.  If this takes too long, we can | 
 | 1490 |         //  potentially cache these results. | 
 | 1491 |         const char* s = FD->getIdentifier()->getName(); | 
 | 1492 |         unsigned n = strlen(s); | 
 | 1493 |          | 
 | 1494 |         switch (n) { | 
 | 1495 |           default: | 
 | 1496 |             break; | 
| Ted Kremenek | 76fdbde | 2008-03-14 23:25:49 +0000 | [diff] [blame] | 1497 |              | 
| Ted Kremenek | 636e6ba | 2008-03-14 21:58:42 +0000 | [diff] [blame] | 1498 |           case 4: | 
| Ted Kremenek | 76fdbde | 2008-03-14 23:25:49 +0000 | [diff] [blame] | 1499 |             if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true; | 
 | 1500 |             break; | 
 | 1501 |  | 
 | 1502 |           case 5: | 
 | 1503 |             if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true; | 
| Zhongxing Xu | bb316c5 | 2008-10-07 10:06:03 +0000 | [diff] [blame] | 1504 |             else if (!memcmp(s, "error", 5)) { | 
| Zhongxing Xu | a90d56e | 2008-10-09 03:19:06 +0000 | [diff] [blame] | 1505 |               if (CE->getNumArgs() > 0) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1506 |                 SVal X = GetSVal(state, *CE->arg_begin()); | 
| Zhongxing Xu | a90d56e | 2008-10-09 03:19:06 +0000 | [diff] [blame] | 1507 |                 // FIXME: use Assume to inspect the possible symbolic value of | 
 | 1508 |                 // X. Also check the specific signature of error(). | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 1509 |                 nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X); | 
| Zhongxing Xu | a90d56e | 2008-10-09 03:19:06 +0000 | [diff] [blame] | 1510 |                 if (CI && CI->getValue() != 0) | 
| Zhongxing Xu | bb316c5 | 2008-10-07 10:06:03 +0000 | [diff] [blame] | 1511 |                   Builder->BuildSinks = true; | 
| Zhongxing Xu | a90d56e | 2008-10-09 03:19:06 +0000 | [diff] [blame] | 1512 |               } | 
| Zhongxing Xu | bb316c5 | 2008-10-07 10:06:03 +0000 | [diff] [blame] | 1513 |             } | 
| Ted Kremenek | 76fdbde | 2008-03-14 23:25:49 +0000 | [diff] [blame] | 1514 |             break; | 
| Ted Kremenek | 29ba6b4 | 2009-02-17 17:48:52 +0000 | [diff] [blame] | 1515 |  | 
| Ted Kremenek | 9a094cb | 2008-04-22 05:37:33 +0000 | [diff] [blame] | 1516 |           case 6: | 
| Ted Kremenek | 489ecd5 | 2008-05-17 00:42:01 +0000 | [diff] [blame] | 1517 |             if (!memcmp(s, "Assert", 6)) { | 
 | 1518 |               Builder->BuildSinks = true; | 
 | 1519 |               break; | 
 | 1520 |             } | 
| Ted Kremenek | c7122d5 | 2008-05-01 15:55:59 +0000 | [diff] [blame] | 1521 |              | 
 | 1522 |             // FIXME: This is just a wrapper around throwing an exception. | 
 | 1523 |             //  Eventually inter-procedural analysis should handle this easily. | 
 | 1524 |             if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true; | 
 | 1525 |  | 
| Ted Kremenek | 9a094cb | 2008-04-22 05:37:33 +0000 | [diff] [blame] | 1526 |             break; | 
| Ted Kremenek | 688738f | 2008-04-23 00:41:25 +0000 | [diff] [blame] | 1527 |            | 
 | 1528 |           case 7: | 
 | 1529 |             if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true; | 
 | 1530 |             break; | 
| Ted Kremenek | 9a108ae | 2008-04-22 06:09:33 +0000 | [diff] [blame] | 1531 |              | 
| Ted Kremenek | f47bb78 | 2008-04-30 17:54:04 +0000 | [diff] [blame] | 1532 |           case 8: | 
| Ted Kremenek | 29ba6b4 | 2009-02-17 17:48:52 +0000 | [diff] [blame] | 1533 |             if (!memcmp(s ,"db_error", 8) ||  | 
 | 1534 |                 !memcmp(s, "__assert", 8)) | 
 | 1535 |               Builder->BuildSinks = true; | 
| Ted Kremenek | f47bb78 | 2008-04-30 17:54:04 +0000 | [diff] [blame] | 1536 |             break; | 
| Ted Kremenek | 24cb8a2 | 2008-05-01 17:52:49 +0000 | [diff] [blame] | 1537 |            | 
 | 1538 |           case 12: | 
 | 1539 |             if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true; | 
 | 1540 |             break; | 
| Ted Kremenek | f47bb78 | 2008-04-30 17:54:04 +0000 | [diff] [blame] | 1541 |              | 
| Ted Kremenek | f968308 | 2008-09-19 02:30:47 +0000 | [diff] [blame] | 1542 |           case 13: | 
 | 1543 |             if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true; | 
 | 1544 |             break; | 
 | 1545 |              | 
| Ted Kremenek | 9a108ae | 2008-04-22 06:09:33 +0000 | [diff] [blame] | 1546 |           case 14: | 
| Ted Kremenek | 2598b57 | 2008-10-30 00:00:57 +0000 | [diff] [blame] | 1547 |             if (!memcmp(s, "dtrace_assfail", 14) || | 
 | 1548 |                 !memcmp(s, "yy_fatal_error", 14)) | 
 | 1549 |               Builder->BuildSinks = true; | 
| Ted Kremenek | 9a108ae | 2008-04-22 06:09:33 +0000 | [diff] [blame] | 1550 |             break; | 
| Ted Kremenek | ec8a1cb | 2008-05-17 00:33:23 +0000 | [diff] [blame] | 1551 |              | 
 | 1552 |           case 26: | 
| Ted Kremenek | 7386d77 | 2008-07-18 16:28:33 +0000 | [diff] [blame] | 1553 |             if (!memcmp(s, "_XCAssertionFailureHandler", 26) || | 
| Ted Kremenek | 40bbff0 | 2009-02-17 23:27:17 +0000 | [diff] [blame] | 1554 |                 !memcmp(s, "_DTAssertionFailureHandler", 26) || | 
 | 1555 |                 !memcmp(s, "_TSAssertionFailureHandler", 26)) | 
| Ted Kremenek | 05a9112 | 2008-05-17 00:40:45 +0000 | [diff] [blame] | 1556 |               Builder->BuildSinks = true; | 
| Ted Kremenek | 7386d77 | 2008-07-18 16:28:33 +0000 | [diff] [blame] | 1557 |  | 
| Ted Kremenek | ec8a1cb | 2008-05-17 00:33:23 +0000 | [diff] [blame] | 1558 |             break; | 
| Ted Kremenek | 636e6ba | 2008-03-14 21:58:42 +0000 | [diff] [blame] | 1559 |         } | 
| Ted Kremenek | 9a108ae | 2008-04-22 06:09:33 +0000 | [diff] [blame] | 1560 |          | 
| Ted Kremenek | 636e6ba | 2008-03-14 21:58:42 +0000 | [diff] [blame] | 1561 |       } | 
 | 1562 |     } | 
| Ted Kremenek | 4bf38da | 2008-03-05 21:15:02 +0000 | [diff] [blame] | 1563 |      | 
 | 1564 |     // Evaluate the call. | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 1565 |  | 
| Zhongxing Xu | 369f447 | 2009-04-20 05:24:46 +0000 | [diff] [blame] | 1566 |     if (FD) { | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1567 |        | 
| Zhongxing Xu | 369f447 | 2009-04-20 05:24:46 +0000 | [diff] [blame] | 1568 |       if (unsigned id = FD->getBuiltinID(getContext())) | 
| Ted Kremenek | 55aea31 | 2008-03-05 22:59:42 +0000 | [diff] [blame] | 1569 |         switch (id) { | 
 | 1570 |           case Builtin::BI__builtin_expect: { | 
 | 1571 |             // For __builtin_expect, just return the value of the subexpression. | 
 | 1572 |             assert (CE->arg_begin() != CE->arg_end());             | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1573 |             SVal X = GetSVal(state, *(CE->arg_begin())); | 
 | 1574 |             MakeNode(Dst, CE, *DI, BindExpr(state, CE, X)); | 
| Ted Kremenek | 55aea31 | 2008-03-05 22:59:42 +0000 | [diff] [blame] | 1575 |             continue;             | 
 | 1576 |           } | 
 | 1577 |              | 
| Ted Kremenek | b302133 | 2008-11-02 00:35:01 +0000 | [diff] [blame] | 1578 |           case Builtin::BI__builtin_alloca: { | 
| Ted Kremenek | b302133 | 2008-11-02 00:35:01 +0000 | [diff] [blame] | 1579 |             // FIXME: Refactor into StoreManager itself? | 
 | 1580 |             MemRegionManager& RM = getStateManager().getRegionManager(); | 
 | 1581 |             const MemRegion* R = | 
| Zhongxing Xu | 6d82f9d | 2008-11-13 07:58:20 +0000 | [diff] [blame] | 1582 |               RM.getAllocaRegion(CE, Builder->getCurrentBlockCount()); | 
| Zhongxing Xu | baf03a7 | 2008-11-24 09:44:56 +0000 | [diff] [blame] | 1583 |  | 
 | 1584 |             // Set the extent of the region in bytes. This enables us to use the | 
 | 1585 |             // SVal of the argument directly. If we save the extent in bits, we | 
 | 1586 |             // cannot represent values like symbol*8. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1587 |             SVal Extent = GetSVal(state, *(CE->arg_begin())); | 
 | 1588 |             state = getStoreManager().setExtent(state, R, Extent); | 
| Zhongxing Xu | baf03a7 | 2008-11-24 09:44:56 +0000 | [diff] [blame] | 1589 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1590 |             MakeNode(Dst, CE, *DI, BindExpr(state, CE, loc::MemRegionVal(R))); | 
| Ted Kremenek | b302133 | 2008-11-02 00:35:01 +0000 | [diff] [blame] | 1591 |             continue;             | 
 | 1592 |           } | 
 | 1593 |              | 
| Ted Kremenek | 55aea31 | 2008-03-05 22:59:42 +0000 | [diff] [blame] | 1594 |           default: | 
| Ted Kremenek | 55aea31 | 2008-03-05 22:59:42 +0000 | [diff] [blame] | 1595 |             break; | 
 | 1596 |         } | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1597 |     } | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 1598 |  | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 1599 |     // Check any arguments passed-by-value against being undefined. | 
 | 1600 |  | 
 | 1601 |     bool badArg = false; | 
 | 1602 |      | 
 | 1603 |     for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); | 
 | 1604 |          I != E; ++I) { | 
 | 1605 |  | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 1606 |       if (GetSVal(GetState(*DI), *I).isUndef()) {         | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 1607 |         NodeTy* N = Builder->generateNode(CE, GetState(*DI), *DI); | 
| Ted Kremenek | 4bf38da | 2008-03-05 21:15:02 +0000 | [diff] [blame] | 1608 |        | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 1609 |         if (N) { | 
 | 1610 |           N->markAsSink(); | 
 | 1611 |           UndefArgs[N] = *I; | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1612 |         } | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1613 |          | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 1614 |         badArg = true; | 
 | 1615 |         break; | 
 | 1616 |       } | 
| Ted Kremenek | d753f3c | 2008-03-04 22:01:56 +0000 | [diff] [blame] | 1617 |     } | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 1618 |      | 
 | 1619 |     if (badArg) | 
 | 1620 |       continue;         | 
 | 1621 |  | 
 | 1622 |     // Dispatch to the plug-in transfer function.       | 
 | 1623 |      | 
 | 1624 |     unsigned size = Dst.size(); | 
 | 1625 |     SaveOr OldHasGen(Builder->HasGeneratedNode); | 
 | 1626 |     EvalCall(Dst, CE, L, *DI); | 
 | 1627 |      | 
 | 1628 |     // Handle the case where no nodes where generated.  Auto-generate that | 
 | 1629 |     // contains the updated state if we aren't generating sinks. | 
 | 1630 |      | 
 | 1631 |     if (!Builder->BuildSinks && Dst.size() == size && | 
 | 1632 |         !Builder->HasGeneratedNode) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1633 |       MakeNode(Dst, CE, *DI, state); | 
| Ted Kremenek | de43424 | 2008-02-19 01:44:53 +0000 | [diff] [blame] | 1634 |   } | 
 | 1635 | } | 
 | 1636 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1637 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 1638 | // Transfer function: Objective-C ivar references. | 
 | 1639 | //===----------------------------------------------------------------------===// | 
 | 1640 |  | 
| Ted Kremenek | f5cae63 | 2009-02-28 20:50:43 +0000 | [diff] [blame] | 1641 | static std::pair<const void*,const void*> EagerlyAssumeTag | 
 | 1642 |   = std::pair<const void*,const void*>(&EagerlyAssumeTag,0); | 
 | 1643 |  | 
| Ted Kremenek | b293902 | 2009-02-25 23:32:10 +0000 | [diff] [blame] | 1644 | void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) { | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 1645 |   for (NodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) { | 
 | 1646 |     NodeTy *Pred = *I; | 
| Ted Kremenek | b293902 | 2009-02-25 23:32:10 +0000 | [diff] [blame] | 1647 |      | 
 | 1648 |     // Test if the previous node was as the same expression.  This can happen | 
 | 1649 |     // when the expression fails to evaluate to anything meaningful and | 
 | 1650 |     // (as an optimization) we don't generate a node. | 
 | 1651 |     ProgramPoint P = Pred->getLocation();     | 
 | 1652 |     if (!isa<PostStmt>(P) || cast<PostStmt>(P).getStmt() != Ex) { | 
 | 1653 |       Dst.Add(Pred);       | 
 | 1654 |       continue; | 
 | 1655 |     }     | 
 | 1656 |  | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 1657 |     const GRState* state = Pred->getState();     | 
| Ted Kremenek | b293902 | 2009-02-25 23:32:10 +0000 | [diff] [blame] | 1658 |     SVal V = GetSVal(state, Ex);     | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 1659 |     if (isa<nonloc::SymExprVal>(V)) { | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 1660 |       // First assume that the condition is true. | 
 | 1661 |       bool isFeasible = false; | 
 | 1662 |       const GRState *stateTrue = Assume(state, V, true, isFeasible); | 
 | 1663 |       if (isFeasible) { | 
| Ted Kremenek | b293902 | 2009-02-25 23:32:10 +0000 | [diff] [blame] | 1664 |         stateTrue = BindExpr(stateTrue, Ex, MakeConstantVal(1U, Ex));         | 
 | 1665 |         Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag), | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 1666 |                                       stateTrue, Pred)); | 
 | 1667 |       } | 
 | 1668 |          | 
 | 1669 |       // Next, assume that the condition is false. | 
 | 1670 |       isFeasible = false; | 
 | 1671 |       const GRState *stateFalse = Assume(state, V, false, isFeasible); | 
 | 1672 |       if (isFeasible) { | 
| Ted Kremenek | b293902 | 2009-02-25 23:32:10 +0000 | [diff] [blame] | 1673 |         stateFalse = BindExpr(stateFalse, Ex, MakeConstantVal(0U, Ex)); | 
 | 1674 |         Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag), | 
| Ted Kremenek | 48af2a9 | 2009-02-25 22:32:02 +0000 | [diff] [blame] | 1675 |                                       stateFalse, Pred)); | 
 | 1676 |       } | 
 | 1677 |     } | 
 | 1678 |     else | 
 | 1679 |       Dst.Add(Pred); | 
 | 1680 |   } | 
 | 1681 | } | 
 | 1682 |  | 
 | 1683 | //===----------------------------------------------------------------------===// | 
 | 1684 | // Transfer function: Objective-C ivar references. | 
 | 1685 | //===----------------------------------------------------------------------===// | 
 | 1686 |  | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 1687 | void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, | 
 | 1688 |                                             NodeTy* Pred, NodeSet& Dst, | 
 | 1689 |                                             bool asLValue) { | 
 | 1690 |    | 
 | 1691 |   Expr* Base = cast<Expr>(Ex->getBase()); | 
 | 1692 |   NodeSet Tmp; | 
 | 1693 |   Visit(Base, Pred, Tmp); | 
 | 1694 |    | 
 | 1695 |   for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1696 |     const GRState* state = GetState(*I); | 
 | 1697 |     SVal BaseVal = GetSVal(state, Base); | 
 | 1698 |     SVal location = StateMgr.GetLValue(state, Ex->getDecl(), BaseVal); | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 1699 |      | 
 | 1700 |     if (asLValue) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1701 |       MakeNode(Dst, Ex, *I, BindExpr(state, Ex, location)); | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 1702 |     else | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1703 |       EvalLoad(Dst, Ex, *I, state, location); | 
| Ted Kremenek | 97ed4f6 | 2008-10-17 00:03:18 +0000 | [diff] [blame] | 1704 |   } | 
 | 1705 | } | 
 | 1706 |  | 
 | 1707 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1708 | // Transfer function: Objective-C fast enumeration 'for' statements. | 
 | 1709 | //===----------------------------------------------------------------------===// | 
 | 1710 |  | 
 | 1711 | void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, | 
 | 1712 |                                               NodeTy* Pred, NodeSet& Dst) { | 
 | 1713 |      | 
 | 1714 |   // ObjCForCollectionStmts are processed in two places.  This method | 
 | 1715 |   // handles the case where an ObjCForCollectionStmt* occurs as one of the | 
 | 1716 |   // statements within a basic block.  This transfer function does two things: | 
 | 1717 |   // | 
 | 1718 |   //  (1) binds the next container value to 'element'.  This creates a new | 
 | 1719 |   //      node in the ExplodedGraph. | 
 | 1720 |   // | 
 | 1721 |   //  (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating | 
 | 1722 |   //      whether or not the container has any more elements.  This value | 
 | 1723 |   //      will be tested in ProcessBranch.  We need to explicitly bind | 
 | 1724 |   //      this value because a container can contain nil elements. | 
 | 1725 |   //   | 
 | 1726 |   // FIXME: Eventually this logic should actually do dispatches to | 
 | 1727 |   //   'countByEnumeratingWithState:objects:count:' (NSFastEnumeration). | 
 | 1728 |   //   This will require simulating a temporary NSFastEnumerationState, either | 
 | 1729 |   //   through an SVal or through the use of MemRegions.  This value can | 
 | 1730 |   //   be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop | 
 | 1731 |   //   terminates we reclaim the temporary (it goes out of scope) and we | 
 | 1732 |   //   we can test if the SVal is 0 or if the MemRegion is null (depending | 
 | 1733 |   //   on what approach we take). | 
 | 1734 |   // | 
 | 1735 |   //  For now: simulate (1) by assigning either a symbol or nil if the | 
 | 1736 |   //    container is empty.  Thus this transfer function will by default | 
 | 1737 |   //    result in state splitting. | 
 | 1738 |    | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1739 |   Stmt* elem = S->getElement(); | 
 | 1740 |   SVal ElementV; | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1741 |      | 
 | 1742 |   if (DeclStmt* DS = dyn_cast<DeclStmt>(elem)) { | 
| Chris Lattner | 7e24e82 | 2009-03-28 06:33:19 +0000 | [diff] [blame] | 1743 |     VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl()); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1744 |     assert (ElemD->getInit() == 0); | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1745 |     ElementV = getStateManager().GetLValue(GetState(Pred), ElemD); | 
 | 1746 |     VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV); | 
 | 1747 |     return; | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1748 |   } | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1749 |  | 
 | 1750 |   NodeSet Tmp; | 
 | 1751 |   VisitLValue(cast<Expr>(elem), Pred, Tmp); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1752 |    | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1753 |   for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) { | 
 | 1754 |     const GRState* state = GetState(*I); | 
 | 1755 |     VisitObjCForCollectionStmtAux(S, *I, Dst, GetSVal(state, elem)); | 
 | 1756 |   } | 
 | 1757 | } | 
 | 1758 |  | 
 | 1759 | void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, | 
 | 1760 |                                                  NodeTy* Pred, NodeSet& Dst, | 
 | 1761 |                                                  SVal ElementV) { | 
 | 1762 |      | 
 | 1763 |  | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1764 |    | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1765 |   // Get the current state.  Use 'EvalLocation' to determine if it is a null | 
 | 1766 |   // pointer, etc. | 
 | 1767 |   Stmt* elem = S->getElement(); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1768 |    | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1769 |   Pred = EvalLocation(elem, Pred, GetState(Pred), ElementV); | 
 | 1770 |   if (!Pred) | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1771 |     return; | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 1772 |      | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 1773 |   const GRState *state = GetState(Pred); | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1774 |  | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1775 |   // Handle the case where the container still has elements. | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1776 |   QualType IntTy = getContext().IntTy; | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1777 |   SVal TrueV = NonLoc::MakeVal(getBasicVals(), 1, IntTy); | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 1778 |   const GRState *hasElems = state->bindExpr(S, TrueV); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1779 |    | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1780 |   // Handle the case where the container has no elements. | 
| Ted Kremenek | 116ed0a | 2008-11-12 21:12:46 +0000 | [diff] [blame] | 1781 |   SVal FalseV = NonLoc::MakeVal(getBasicVals(), 0, IntTy); | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 1782 |   const GRState *noElems = state->bindExpr(S, FalseV); | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1783 |    | 
 | 1784 |   if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV)) | 
 | 1785 |     if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) { | 
 | 1786 |       // FIXME: The proper thing to do is to really iterate over the | 
 | 1787 |       //  container.  We will do this with dispatch logic to the store. | 
 | 1788 |       //  For now, just 'conjure' up a symbolic value. | 
| Zhongxing Xu | a82d8aa | 2009-05-09 03:57:34 +0000 | [diff] [blame] | 1789 |       QualType T = R->getValueType(getContext()); | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1790 |       assert (Loc::IsLocType(T)); | 
 | 1791 |       unsigned Count = Builder->getCurrentBlockCount(); | 
| Zhongxing Xu | ea7c5ce | 2009-04-09 06:49:52 +0000 | [diff] [blame] | 1792 |       SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count); | 
 | 1793 |       SVal V = Loc::MakeVal(getStoreManager().getRegionManager().getSymbolicRegion(Sym)); | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 1794 |       hasElems = hasElems->bindLoc(ElementV, V); | 
| Ted Kremenek | 116ed0a | 2008-11-12 21:12:46 +0000 | [diff] [blame] | 1795 |  | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1796 |       // Bind the location to 'nil' on the false branch. | 
 | 1797 |       SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, T));       | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 1798 |       noElems = noElems->bindLoc(ElementV, nilV);       | 
| Ted Kremenek | 06fb99f | 2008-11-14 19:47:18 +0000 | [diff] [blame] | 1799 |     } | 
 | 1800 |    | 
| Ted Kremenek | 116ed0a | 2008-11-12 21:12:46 +0000 | [diff] [blame] | 1801 |   // Create the new nodes. | 
 | 1802 |   MakeNode(Dst, S, Pred, hasElems); | 
 | 1803 |   MakeNode(Dst, S, Pred, noElems); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 1804 | } | 
 | 1805 |  | 
 | 1806 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1807 | // Transfer function: Objective-C message expressions. | 
 | 1808 | //===----------------------------------------------------------------------===// | 
 | 1809 |  | 
 | 1810 | void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, | 
 | 1811 |                                         NodeSet& Dst){ | 
 | 1812 |    | 
 | 1813 |   VisitObjCMessageExprArgHelper(ME, ME->arg_begin(), ME->arg_end(), | 
 | 1814 |                                 Pred, Dst); | 
 | 1815 | }   | 
 | 1816 |  | 
 | 1817 | void GRExprEngine::VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME, | 
| Zhongxing Xu | d3118bd | 2008-10-31 07:26:14 +0000 | [diff] [blame] | 1818 |                                               ObjCMessageExpr::arg_iterator AI, | 
 | 1819 |                                               ObjCMessageExpr::arg_iterator AE, | 
 | 1820 |                                               NodeTy* Pred, NodeSet& Dst) { | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1821 |   if (AI == AE) { | 
 | 1822 |      | 
 | 1823 |     // Process the receiver. | 
 | 1824 |      | 
 | 1825 |     if (Expr* Receiver = ME->getReceiver()) { | 
 | 1826 |       NodeSet Tmp; | 
 | 1827 |       Visit(Receiver, Pred, Tmp); | 
 | 1828 |        | 
 | 1829 |       for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI) | 
 | 1830 |         VisitObjCMessageExprDispatchHelper(ME, *NI, Dst); | 
 | 1831 |        | 
 | 1832 |       return; | 
 | 1833 |     } | 
 | 1834 |      | 
 | 1835 |     VisitObjCMessageExprDispatchHelper(ME, Pred, Dst); | 
 | 1836 |     return; | 
 | 1837 |   } | 
 | 1838 |    | 
 | 1839 |   NodeSet Tmp; | 
 | 1840 |   Visit(*AI, Pred, Tmp); | 
 | 1841 |    | 
 | 1842 |   ++AI; | 
 | 1843 |    | 
 | 1844 |   for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI) | 
 | 1845 |     VisitObjCMessageExprArgHelper(ME, AI, AE, *NI, Dst); | 
 | 1846 | } | 
 | 1847 |  | 
 | 1848 | void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, | 
 | 1849 |                                                       NodeTy* Pred, | 
 | 1850 |                                                       NodeSet& Dst) { | 
 | 1851 |    | 
 | 1852 |   // FIXME: More logic for the processing the method call.  | 
 | 1853 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1854 |   const GRState* state = GetState(Pred); | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 1855 |   bool RaisesException = false; | 
 | 1856 |    | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1857 |    | 
 | 1858 |   if (Expr* Receiver = ME->getReceiver()) { | 
 | 1859 |      | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1860 |     SVal L = GetSVal(state, Receiver); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1861 |      | 
| Ted Kremenek | 21fe837 | 2009-02-19 04:06:22 +0000 | [diff] [blame] | 1862 |     // Check for undefined control-flow.     | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1863 |     if (L.isUndef()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 1864 |       NodeTy* N = Builder->generateNode(ME, state, Pred); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1865 |        | 
 | 1866 |       if (N) { | 
 | 1867 |         N->markAsSink(); | 
 | 1868 |         UndefReceivers.insert(N); | 
 | 1869 |       } | 
 | 1870 |        | 
 | 1871 |       return; | 
 | 1872 |     } | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 1873 |      | 
| Ted Kremenek | 21fe837 | 2009-02-19 04:06:22 +0000 | [diff] [blame] | 1874 |     // "Assume" that the receiver is not NULL.     | 
 | 1875 |     bool isFeasibleNotNull = false; | 
| Ted Kremenek | da9ae60 | 2009-04-08 18:51:08 +0000 | [diff] [blame] | 1876 |     const GRState *StNotNull = Assume(state, L, true, isFeasibleNotNull); | 
| Ted Kremenek | 21fe837 | 2009-02-19 04:06:22 +0000 | [diff] [blame] | 1877 |      | 
 | 1878 |     // "Assume" that the receiver is NULL.     | 
 | 1879 |     bool isFeasibleNull = false; | 
 | 1880 |     const GRState *StNull = Assume(state, L, false, isFeasibleNull); | 
 | 1881 |      | 
 | 1882 |     if (isFeasibleNull) { | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1883 |       QualType RetTy = ME->getType(); | 
 | 1884 |        | 
| Ted Kremenek | 21fe837 | 2009-02-19 04:06:22 +0000 | [diff] [blame] | 1885 |       // Check if the receiver was nil and the return value a struct. | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1886 |       if(RetTy->isRecordType()) { | 
| Ted Kremenek | e8dbf06 | 2009-04-09 00:00:02 +0000 | [diff] [blame] | 1887 |         if (BR.getParentMap().isConsumedExpr(ME)) { | 
| Ted Kremenek | 899b3de | 2009-04-08 03:07:17 +0000 | [diff] [blame] | 1888 |           // The [0 ...] expressions will return garbage.  Flag either an | 
 | 1889 |           // explicit or implicit error.  Because of the structure of this | 
 | 1890 |           // function we currently do not bifurfacte the state graph at | 
 | 1891 |           // this point. | 
 | 1892 |           // FIXME: We should bifurcate and fill the returned struct with | 
 | 1893 |           //  garbage.                 | 
 | 1894 |           if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) { | 
 | 1895 |             N->markAsSink(); | 
 | 1896 |             if (isFeasibleNotNull) | 
 | 1897 |               NilReceiverStructRetImplicit.insert(N); | 
| Ted Kremenek | f8769c8 | 2009-04-09 06:02:06 +0000 | [diff] [blame] | 1898 |             else | 
| Ted Kremenek | e644939 | 2009-04-09 04:06:51 +0000 | [diff] [blame] | 1899 |               NilReceiverStructRetExplicit.insert(N);             | 
| Ted Kremenek | 899b3de | 2009-04-08 03:07:17 +0000 | [diff] [blame] | 1900 |           } | 
 | 1901 |         } | 
| Ted Kremenek | e8dbf06 | 2009-04-09 00:00:02 +0000 | [diff] [blame] | 1902 |       } | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1903 |       else { | 
| Ted Kremenek | e8dbf06 | 2009-04-09 00:00:02 +0000 | [diff] [blame] | 1904 |         ASTContext& Ctx = getContext(); | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1905 |         if (RetTy != Ctx.VoidTy) { | 
 | 1906 |           if (BR.getParentMap().isConsumedExpr(ME)) { | 
 | 1907 |             // sizeof(void *) | 
 | 1908 |             const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy); | 
 | 1909 |             // sizeof(return type) | 
 | 1910 |             const uint64_t returnTypeSize = Ctx.getTypeSize(ME->getType()); | 
| Ted Kremenek | e8dbf06 | 2009-04-09 00:00:02 +0000 | [diff] [blame] | 1911 |  | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1912 |             if(voidPtrSize < returnTypeSize) { | 
 | 1913 |               if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) { | 
 | 1914 |                 N->markAsSink(); | 
 | 1915 |                 if(isFeasibleNotNull) | 
 | 1916 |                   NilReceiverLargerThanVoidPtrRetImplicit.insert(N); | 
| Ted Kremenek | f8769c8 | 2009-04-09 06:02:06 +0000 | [diff] [blame] | 1917 |                 else | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1918 |                   NilReceiverLargerThanVoidPtrRetExplicit.insert(N);             | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1919 |               } | 
 | 1920 |             } | 
 | 1921 |             else if (!isFeasibleNotNull) { | 
 | 1922 |               // Handle the safe cases where the return value is 0 if the | 
 | 1923 |               // receiver is nil. | 
 | 1924 |               // | 
 | 1925 |               // FIXME: For now take the conservative approach that we only | 
 | 1926 |               // return null values if we *know* that the receiver is nil. | 
 | 1927 |               // This is because we can have surprises like: | 
 | 1928 |               // | 
 | 1929 |               //   ... = [[NSScreens screens] objectAtIndex:0]; | 
 | 1930 |               // | 
 | 1931 |               // What can happen is that [... screens] could return nil, but | 
 | 1932 |               // it most likely isn't nil.  We should assume the semantics | 
 | 1933 |               // of this case unless we have *a lot* more knowledge. | 
 | 1934 |               // | 
| Ted Kremenek | 8e5fb28 | 2009-04-09 16:46:55 +0000 | [diff] [blame] | 1935 |               SVal V = ValMgr.makeZeroVal(ME->getType()); | 
| Ted Kremenek | fe630b9 | 2009-04-09 05:45:56 +0000 | [diff] [blame] | 1936 |               MakeNode(Dst, ME, Pred, BindExpr(StNull, ME, V)); | 
| Ted Kremenek | e644939 | 2009-04-09 04:06:51 +0000 | [diff] [blame] | 1937 |               return; | 
 | 1938 |             } | 
| Ted Kremenek | 899b3de | 2009-04-08 03:07:17 +0000 | [diff] [blame] | 1939 |           } | 
| Ted Kremenek | e8dbf06 | 2009-04-09 00:00:02 +0000 | [diff] [blame] | 1940 |         } | 
| Ted Kremenek | 21fe837 | 2009-02-19 04:06:22 +0000 | [diff] [blame] | 1941 |       } | 
| Ted Kremenek | da9ae60 | 2009-04-08 18:51:08 +0000 | [diff] [blame] | 1942 |       // We have handled the cases where the receiver is nil.  The remainder | 
| Ted Kremenek | f8769c8 | 2009-04-09 06:02:06 +0000 | [diff] [blame] | 1943 |       // of this method should assume that the receiver is not nil. | 
 | 1944 |       if (!StNotNull) | 
 | 1945 |         return; | 
 | 1946 |         | 
| Ted Kremenek | da9ae60 | 2009-04-08 18:51:08 +0000 | [diff] [blame] | 1947 |       state = StNotNull; | 
| Ted Kremenek | 21fe837 | 2009-02-19 04:06:22 +0000 | [diff] [blame] | 1948 |     } | 
 | 1949 |      | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 1950 |     // Check if the "raise" message was sent. | 
 | 1951 |     if (ME->getSelector() == RaiseSel) | 
 | 1952 |       RaisesException = true; | 
 | 1953 |   } | 
 | 1954 |   else { | 
 | 1955 |      | 
 | 1956 |     IdentifierInfo* ClsName = ME->getClassName(); | 
 | 1957 |     Selector S = ME->getSelector(); | 
 | 1958 |      | 
 | 1959 |     // Check for special instance methods. | 
 | 1960 |          | 
 | 1961 |     if (!NSExceptionII) {       | 
 | 1962 |       ASTContext& Ctx = getContext(); | 
 | 1963 |        | 
 | 1964 |       NSExceptionII = &Ctx.Idents.get("NSException"); | 
 | 1965 |     } | 
 | 1966 |      | 
 | 1967 |     if (ClsName == NSExceptionII) { | 
 | 1968 |          | 
 | 1969 |       enum { NUM_RAISE_SELECTORS = 2 }; | 
 | 1970 |        | 
 | 1971 |       // Lazily create a cache of the selectors. | 
 | 1972 |  | 
 | 1973 |       if (!NSExceptionInstanceRaiseSelectors) { | 
 | 1974 |          | 
 | 1975 |         ASTContext& Ctx = getContext(); | 
 | 1976 |          | 
 | 1977 |         NSExceptionInstanceRaiseSelectors = new Selector[NUM_RAISE_SELECTORS]; | 
 | 1978 |        | 
 | 1979 |         llvm::SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II; | 
 | 1980 |         unsigned idx = 0; | 
 | 1981 |          | 
 | 1982 |         // raise:format:       | 
| Ted Kremenek | 6ff6f8b | 2008-05-02 17:12:56 +0000 | [diff] [blame] | 1983 |         II.push_back(&Ctx.Idents.get("raise")); | 
 | 1984 |         II.push_back(&Ctx.Idents.get("format"));       | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 1985 |         NSExceptionInstanceRaiseSelectors[idx++] = | 
 | 1986 |           Ctx.Selectors.getSelector(II.size(), &II[0]);       | 
 | 1987 |          | 
 | 1988 |         // raise:format::arguments:       | 
| Ted Kremenek | 6ff6f8b | 2008-05-02 17:12:56 +0000 | [diff] [blame] | 1989 |         II.push_back(&Ctx.Idents.get("arguments")); | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 1990 |         NSExceptionInstanceRaiseSelectors[idx++] = | 
 | 1991 |           Ctx.Selectors.getSelector(II.size(), &II[0]); | 
 | 1992 |       } | 
 | 1993 |        | 
 | 1994 |       for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) | 
 | 1995 |         if (S == NSExceptionInstanceRaiseSelectors[i]) { | 
 | 1996 |           RaisesException = true; break; | 
 | 1997 |         } | 
 | 1998 |     } | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 1999 |   } | 
 | 2000 |    | 
 | 2001 |   // Check for any arguments that are uninitialized/undefined. | 
 | 2002 |    | 
 | 2003 |   for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end(); | 
 | 2004 |        I != E; ++I) { | 
 | 2005 |      | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2006 |     if (GetSVal(state, *I).isUndef()) { | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 2007 |        | 
 | 2008 |       // Generate an error node for passing an uninitialized/undefined value | 
 | 2009 |       // as an argument to a message expression.  This node is a sink. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2010 |       NodeTy* N = Builder->generateNode(ME, state, Pred); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 2011 |        | 
 | 2012 |       if (N) { | 
 | 2013 |         N->markAsSink(); | 
 | 2014 |         MsgExprUndefArgs[N] = *I; | 
 | 2015 |       } | 
 | 2016 |        | 
 | 2017 |       return; | 
 | 2018 |     }     | 
| Ted Kremenek | e448ab4 | 2008-05-01 18:33:28 +0000 | [diff] [blame] | 2019 |   } | 
 | 2020 |    | 
 | 2021 |   // Check if we raise an exception.  For now treat these as sinks.  Eventually | 
 | 2022 |   // we will want to handle exceptions properly. | 
 | 2023 |    | 
 | 2024 |   SaveAndRestore<bool> OldSink(Builder->BuildSinks); | 
 | 2025 |  | 
 | 2026 |   if (RaisesException) | 
 | 2027 |     Builder->BuildSinks = true; | 
 | 2028 |    | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 2029 |   // Dispatch to plug-in transfer function. | 
 | 2030 |    | 
 | 2031 |   unsigned size = Dst.size(); | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 2032 |   SaveOr OldHasGen(Builder->HasGeneratedNode); | 
| Ted Kremenek | b053396 | 2008-04-18 20:35:30 +0000 | [diff] [blame] | 2033 |   | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 2034 |   EvalObjCMessageExpr(Dst, ME, Pred); | 
 | 2035 |    | 
 | 2036 |   // Handle the case where no nodes where generated.  Auto-generate that | 
 | 2037 |   // contains the updated state if we aren't generating sinks. | 
 | 2038 |    | 
| Ted Kremenek | b053396 | 2008-04-18 20:35:30 +0000 | [diff] [blame] | 2039 |   if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2040 |     MakeNode(Dst, ME, Pred, state); | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 2041 | } | 
 | 2042 |  | 
 | 2043 | //===----------------------------------------------------------------------===// | 
 | 2044 | // Transfer functions: Miscellaneous statements. | 
 | 2045 | //===----------------------------------------------------------------------===// | 
 | 2046 |  | 
| Ted Kremenek | e1c2a67 | 2009-01-13 01:04:21 +0000 | [diff] [blame] | 2047 | void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state, | 
 | 2048 |                                              QualType PtrTy, | 
 | 2049 |                                              Expr* CastE, NodeTy* Pred, | 
 | 2050 |                                              NodeSet& Dst) { | 
 | 2051 |   if (!V.isUnknownOrUndef()) { | 
 | 2052 |     // FIXME: Determine if the number of bits of the target type is  | 
 | 2053 |     // equal or exceeds the number of bits to store the pointer value. | 
| Ted Kremenek | e121da4 | 2009-03-05 03:42:31 +0000 | [diff] [blame] | 2054 |     // If not, flag an error.     | 
| Ted Kremenek | ac78d6b | 2009-03-05 03:44:53 +0000 | [diff] [blame] | 2055 |     MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, EvalCast(cast<Loc>(V), | 
 | 2056 |                                                                CastE->getType()))); | 
| Ted Kremenek | e1c2a67 | 2009-01-13 01:04:21 +0000 | [diff] [blame] | 2057 |   } | 
| Ted Kremenek | e121da4 | 2009-03-05 03:42:31 +0000 | [diff] [blame] | 2058 |   else   | 
 | 2059 |     MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, V)); | 
| Ted Kremenek | e1c2a67 | 2009-01-13 01:04:21 +0000 | [diff] [blame] | 2060 | } | 
 | 2061 |  | 
 | 2062 |    | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2063 | void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ | 
| Ted Kremenek | 5d3003a | 2008-02-19 18:52:54 +0000 | [diff] [blame] | 2064 |   NodeSet S1; | 
| Ted Kremenek | 5d3003a | 2008-02-19 18:52:54 +0000 | [diff] [blame] | 2065 |   QualType T = CastE->getType(); | 
| Zhongxing Xu | 933c3e1 | 2008-10-21 06:54:23 +0000 | [diff] [blame] | 2066 |   QualType ExTy = Ex->getType(); | 
| Zhongxing Xu | ed340f7 | 2008-10-22 08:02:16 +0000 | [diff] [blame] | 2067 |  | 
| Zhongxing Xu | d3118bd | 2008-10-31 07:26:14 +0000 | [diff] [blame] | 2068 |   if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE)) | 
| Douglas Gregor | 49badde | 2008-10-27 19:41:14 +0000 | [diff] [blame] | 2069 |     T = ExCast->getTypeAsWritten(); | 
 | 2070 |  | 
| Zhongxing Xu | ed340f7 | 2008-10-22 08:02:16 +0000 | [diff] [blame] | 2071 |   if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType()) | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2072 |     VisitLValue(Ex, Pred, S1); | 
| Ted Kremenek | 65cfb73 | 2008-03-04 22:16:08 +0000 | [diff] [blame] | 2073 |   else | 
 | 2074 |     Visit(Ex, Pred, S1); | 
 | 2075 |    | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2076 |   // Check for casting to "void". | 
| Ted Kremenek | dc40290 | 2009-03-04 00:14:35 +0000 | [diff] [blame] | 2077 |   if (T->isVoidType()) {     | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2078 |     for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) | 
| Ted Kremenek | 5d3003a | 2008-02-19 18:52:54 +0000 | [diff] [blame] | 2079 |       Dst.Add(*I1); | 
 | 2080 |  | 
| Ted Kremenek | 874d63f | 2008-01-24 02:02:54 +0000 | [diff] [blame] | 2081 |     return; | 
 | 2082 |   } | 
 | 2083 |    | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2084 |   // FIXME: The rest of this should probably just go into EvalCall, and | 
 | 2085 |   //   let the transfer function object be responsible for constructing | 
 | 2086 |   //   nodes. | 
 | 2087 |    | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2088 |   for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) { | 
| Ted Kremenek | 874d63f | 2008-01-24 02:02:54 +0000 | [diff] [blame] | 2089 |     NodeTy* N = *I1; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2090 |     const GRState* state = GetState(N); | 
 | 2091 |     SVal V = GetSVal(state, Ex); | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2092 |     ASTContext& C = getContext(); | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2093 |  | 
 | 2094 |     // Unknown? | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2095 |     if (V.isUnknown()) { | 
 | 2096 |       Dst.Add(N); | 
 | 2097 |       continue; | 
 | 2098 |     } | 
 | 2099 |      | 
 | 2100 |     // Undefined? | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2101 |     if (V.isUndef()) | 
 | 2102 |       goto PassThrough; | 
| Ted Kremenek | a8fe39f | 2008-09-19 20:51:22 +0000 | [diff] [blame] | 2103 |      | 
 | 2104 |     // For const casts, just propagate the value. | 
| Ted Kremenek | a8fe39f | 2008-09-19 20:51:22 +0000 | [diff] [blame] | 2105 |     if (C.getCanonicalType(T).getUnqualifiedType() ==  | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2106 |         C.getCanonicalType(ExTy).getUnqualifiedType()) | 
 | 2107 |       goto PassThrough; | 
| Ted Kremenek | 16aac32 | 2009-03-05 02:33:55 +0000 | [diff] [blame] | 2108 |        | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2109 |     // Check for casts from pointers to integers. | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2110 |     if (T->isIntegerType() && Loc::IsLocType(ExTy)) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2111 |       VisitCastPointerToInteger(V, state, ExTy, CastE, N, Dst); | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2112 |       continue; | 
 | 2113 |     } | 
 | 2114 |      | 
 | 2115 |     // Check for casts from integers to pointers. | 
| Ted Kremenek | 16aac32 | 2009-03-05 02:33:55 +0000 | [diff] [blame] | 2116 |     if (Loc::IsLocType(T) && ExTy->isIntegerType()) { | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2117 |       if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&V)) { | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2118 |         // Just unpackage the lval and return it. | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2119 |         V = LV->getLoc(); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2120 |         MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2121 |         continue; | 
| Ted Kremenek | 0fe33bc | 2008-04-22 21:10:18 +0000 | [diff] [blame] | 2122 |       } | 
| Ted Kremenek | e121da4 | 2009-03-05 03:42:31 +0000 | [diff] [blame] | 2123 |        | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2124 |       goto DispatchCast; | 
| Ted Kremenek | 16aac32 | 2009-03-05 02:33:55 +0000 | [diff] [blame] | 2125 |     } | 
 | 2126 |      | 
 | 2127 |     // Just pass through function and block pointers. | 
 | 2128 |     if (ExTy->isBlockPointerType() || ExTy->isFunctionPointerType()) { | 
 | 2129 |       assert(Loc::IsLocType(T)); | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2130 |       goto PassThrough; | 
| Ted Kremenek | 16aac32 | 2009-03-05 02:33:55 +0000 | [diff] [blame] | 2131 |     } | 
 | 2132 |      | 
| Ted Kremenek | e1c2a67 | 2009-01-13 01:04:21 +0000 | [diff] [blame] | 2133 |     // Check for casts from array type to another type. | 
| Zhongxing Xu | e1911af | 2008-10-23 03:10:39 +0000 | [diff] [blame] | 2134 |     if (ExTy->isArrayType()) { | 
| Ted Kremenek | e1c2a67 | 2009-01-13 01:04:21 +0000 | [diff] [blame] | 2135 |       // We will always decay to a pointer. | 
| Zhongxing Xu | f1d537f | 2009-03-30 05:55:46 +0000 | [diff] [blame] | 2136 |       V = StateMgr.ArrayToPointer(cast<Loc>(V)); | 
| Ted Kremenek | e1c2a67 | 2009-01-13 01:04:21 +0000 | [diff] [blame] | 2137 |        | 
 | 2138 |       // Are we casting from an array to a pointer?  If so just pass on | 
 | 2139 |       // the decayed value. | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2140 |       if (T->isPointerType()) | 
 | 2141 |         goto PassThrough; | 
| Ted Kremenek | e1c2a67 | 2009-01-13 01:04:21 +0000 | [diff] [blame] | 2142 |        | 
 | 2143 |       // Are we casting from an array to an integer?  If so, cast the decayed | 
 | 2144 |       // pointer value to an integer. | 
 | 2145 |       assert(T->isIntegerType()); | 
 | 2146 |       QualType ElemTy = cast<ArrayType>(ExTy)->getElementType(); | 
 | 2147 |       QualType PointerTy = getContext().getPointerType(ElemTy); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2148 |       VisitCastPointerToInteger(V, state, PointerTy, CastE, N, Dst); | 
| Zhongxing Xu | e1911af | 2008-10-23 03:10:39 +0000 | [diff] [blame] | 2149 |       continue; | 
 | 2150 |     } | 
 | 2151 |  | 
| Ted Kremenek | 6eddeb1 | 2008-12-13 21:49:13 +0000 | [diff] [blame] | 2152 |     // Check for casts from a region to a specific type. | 
| Ted Kremenek | 5c42f9b | 2009-03-05 22:47:06 +0000 | [diff] [blame] | 2153 |     if (loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(&V)) {       | 
 | 2154 |       // FIXME: For TypedViewRegions, we should handle the case where the | 
 | 2155 |       //  underlying symbolic pointer is a function pointer or | 
 | 2156 |       //  block pointer. | 
 | 2157 |        | 
 | 2158 |       // FIXME: We should handle the case where we strip off view layers to get | 
 | 2159 |       //  to a desugared type. | 
 | 2160 |        | 
| Zhongxing Xu | dc0a25d | 2008-11-16 04:07:26 +0000 | [diff] [blame] | 2161 |       assert(Loc::IsLocType(T)); | 
| Zhongxing Xu | a1718c7 | 2009-04-03 07:33:13 +0000 | [diff] [blame] | 2162 |       // We get a symbolic function pointer for a dereference of a function | 
 | 2163 |       // pointer, but it is of function type. Example: | 
 | 2164 |  | 
 | 2165 |       //  struct FPRec { | 
 | 2166 |       //    void (*my_func)(int * x);   | 
 | 2167 |       //  }; | 
 | 2168 |       // | 
 | 2169 |       //  int bar(int x); | 
 | 2170 |       // | 
 | 2171 |       //  int f1_a(struct FPRec* foo) { | 
 | 2172 |       //    int x; | 
 | 2173 |       //    (*foo->my_func)(&x); | 
 | 2174 |       //    return bar(x)+1; // no-warning | 
 | 2175 |       //  } | 
 | 2176 |  | 
 | 2177 |       assert(Loc::IsLocType(ExTy) || ExTy->isFunctionType()); | 
| Zhongxing Xu | dc0a25d | 2008-11-16 04:07:26 +0000 | [diff] [blame] | 2178 |  | 
| Ted Kremenek | 6eddeb1 | 2008-12-13 21:49:13 +0000 | [diff] [blame] | 2179 |       const MemRegion* R = RV->getRegion(); | 
 | 2180 |       StoreManager& StoreMgr = getStoreManager(); | 
 | 2181 |        | 
 | 2182 |       // Delegate to store manager to get the result of casting a region | 
 | 2183 |       // to a different type. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2184 |       const StoreManager::CastResult& Res = StoreMgr.CastRegion(state, R, T); | 
| Ted Kremenek | 6eddeb1 | 2008-12-13 21:49:13 +0000 | [diff] [blame] | 2185 |        | 
 | 2186 |       // Inspect the result.  If the MemRegion* returned is NULL, this | 
 | 2187 |       // expression evaluates to UnknownVal. | 
 | 2188 |       R = Res.getRegion(); | 
 | 2189 |       if (R) { V = loc::MemRegionVal(R); } else { V = UnknownVal(); } | 
 | 2190 |        | 
 | 2191 |       // Generate the new node in the ExplodedGraph. | 
 | 2192 |       MakeNode(Dst, CastE, N, BindExpr(Res.getState(), CastE, V)); | 
| Ted Kremenek | abb042f | 2008-12-13 19:24:37 +0000 | [diff] [blame] | 2193 |       continue; | 
| Zhongxing Xu | dc0a25d | 2008-11-16 04:07:26 +0000 | [diff] [blame] | 2194 |     } | 
| Zhongxing Xu | 3330dcb | 2009-04-10 06:06:13 +0000 | [diff] [blame] | 2195 |     // All other cases. | 
| Ted Kremenek | c530291 | 2009-03-05 20:22:13 +0000 | [diff] [blame] | 2196 |     DispatchCast: { | 
 | 2197 |       MakeNode(Dst, CastE, N, BindExpr(state, CastE, | 
 | 2198 |                                        EvalCast(V, CastE->getType()))); | 
 | 2199 |       continue; | 
 | 2200 |     } | 
 | 2201 |      | 
 | 2202 |     PassThrough: { | 
 | 2203 |       MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); | 
 | 2204 |     } | 
| Ted Kremenek | 874d63f | 2008-01-24 02:02:54 +0000 | [diff] [blame] | 2205 |   } | 
| Ted Kremenek | 9de04c4 | 2008-01-24 20:55:43 +0000 | [diff] [blame] | 2206 | } | 
 | 2207 |  | 
| Ted Kremenek | 4f09027 | 2008-10-27 21:54:31 +0000 | [diff] [blame] | 2208 | void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, | 
| Zhongxing Xu | f22679e | 2008-11-07 10:38:33 +0000 | [diff] [blame] | 2209 |                                             NodeTy* Pred, NodeSet& Dst,  | 
 | 2210 |                                             bool asLValue) { | 
| Ted Kremenek | 4f09027 | 2008-10-27 21:54:31 +0000 | [diff] [blame] | 2211 |   InitListExpr* ILE = cast<InitListExpr>(CL->getInitializer()->IgnoreParens()); | 
 | 2212 |   NodeSet Tmp; | 
 | 2213 |   Visit(ILE, Pred, Tmp); | 
 | 2214 |    | 
 | 2215 |   for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2216 |     const GRState* state = GetState(*I); | 
 | 2217 |     SVal ILV = GetSVal(state, ILE); | 
 | 2218 |     state = StateMgr.BindCompoundLiteral(state, CL, ILV); | 
| Ted Kremenek | 4f09027 | 2008-10-27 21:54:31 +0000 | [diff] [blame] | 2219 |  | 
| Zhongxing Xu | f22679e | 2008-11-07 10:38:33 +0000 | [diff] [blame] | 2220 |     if (asLValue) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2221 |       MakeNode(Dst, CL, *I, BindExpr(state, CL, StateMgr.GetLValue(state, CL))); | 
| Zhongxing Xu | f22679e | 2008-11-07 10:38:33 +0000 | [diff] [blame] | 2222 |     else | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2223 |       MakeNode(Dst, CL, *I, BindExpr(state, CL, ILV)); | 
| Ted Kremenek | 4f09027 | 2008-10-27 21:54:31 +0000 | [diff] [blame] | 2224 |   } | 
 | 2225 | } | 
 | 2226 |  | 
| Ted Kremenek | 5b7dcce | 2008-04-22 22:25:27 +0000 | [diff] [blame] | 2227 | void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {   | 
| Ted Kremenek | 5b7dcce | 2008-04-22 22:25:27 +0000 | [diff] [blame] | 2228 |  | 
| Ted Kremenek | 8369a8b | 2008-10-06 18:43:53 +0000 | [diff] [blame] | 2229 |   // The CFG has one DeclStmt per Decl.   | 
| Douglas Gregor | 4afa39d | 2009-01-20 01:17:11 +0000 | [diff] [blame] | 2230 |   Decl* D = *DS->decl_begin(); | 
| Ted Kremenek | e6c62e3 | 2008-08-28 18:34:26 +0000 | [diff] [blame] | 2231 |    | 
 | 2232 |   if (!D || !isa<VarDecl>(D)) | 
| Ted Kremenek | 5b7dcce | 2008-04-22 22:25:27 +0000 | [diff] [blame] | 2233 |     return; | 
| Ted Kremenek | 9de04c4 | 2008-01-24 20:55:43 +0000 | [diff] [blame] | 2234 |    | 
| Ted Kremenek | efd5994 | 2008-12-08 22:47:34 +0000 | [diff] [blame] | 2235 |   const VarDecl* VD = dyn_cast<VarDecl>(D);     | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 2236 |   Expr* InitEx = const_cast<Expr*>(VD->getInit()); | 
| Ted Kremenek | 5b7dcce | 2008-04-22 22:25:27 +0000 | [diff] [blame] | 2237 |  | 
 | 2238 |   // FIXME: static variables may have an initializer, but the second | 
 | 2239 |   //  time a function is called those values may not be current. | 
 | 2240 |   NodeSet Tmp; | 
 | 2241 |  | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 2242 |   if (InitEx) | 
 | 2243 |     Visit(InitEx, Pred, Tmp); | 
| Ted Kremenek | e6c62e3 | 2008-08-28 18:34:26 +0000 | [diff] [blame] | 2244 |  | 
 | 2245 |   if (Tmp.empty()) | 
 | 2246 |     Tmp.Add(Pred); | 
| Ted Kremenek | 5b7dcce | 2008-04-22 22:25:27 +0000 | [diff] [blame] | 2247 |    | 
 | 2248 |   for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2249 |     const GRState* state = GetState(*I); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 2250 |     unsigned Count = Builder->getCurrentBlockCount(); | 
| Zhongxing Xu | 4193eca | 2008-12-20 06:32:12 +0000 | [diff] [blame] | 2251 |  | 
| Ted Kremenek | 5b8d901 | 2009-02-14 01:54:57 +0000 | [diff] [blame] | 2252 |     // Check if 'VD' is a VLA and if so check if has a non-zero size. | 
 | 2253 |     QualType T = getContext().getCanonicalType(VD->getType()); | 
 | 2254 |     if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) { | 
 | 2255 |       // FIXME: Handle multi-dimensional VLAs. | 
 | 2256 |        | 
 | 2257 |       Expr* SE = VLA->getSizeExpr(); | 
 | 2258 |       SVal Size = GetSVal(state, SE); | 
 | 2259 |        | 
 | 2260 |       if (Size.isUndef()) { | 
 | 2261 |         if (NodeTy* N = Builder->generateNode(DS, state, Pred)) { | 
 | 2262 |           N->markAsSink();           | 
 | 2263 |           ExplicitBadSizedVLA.insert(N); | 
 | 2264 |         } | 
 | 2265 |         continue; | 
 | 2266 |       } | 
 | 2267 |        | 
 | 2268 |       bool isFeasibleZero = false; | 
 | 2269 |       const GRState* ZeroSt =  Assume(state, Size, false, isFeasibleZero); | 
 | 2270 |        | 
 | 2271 |       bool isFeasibleNotZero = false; | 
 | 2272 |       state = Assume(state, Size, true, isFeasibleNotZero); | 
 | 2273 |        | 
 | 2274 |       if (isFeasibleZero) { | 
 | 2275 |         if (NodeTy* N = Builder->generateNode(DS, ZeroSt, Pred)) { | 
 | 2276 |           N->markAsSink();           | 
 | 2277 |           if (isFeasibleNotZero) ImplicitBadSizedVLA.insert(N); | 
 | 2278 |           else ExplicitBadSizedVLA.insert(N); | 
 | 2279 |         } | 
 | 2280 |       } | 
 | 2281 |        | 
 | 2282 |       if (!isFeasibleNotZero) | 
 | 2283 |         continue;       | 
 | 2284 |     } | 
 | 2285 |      | 
| Zhongxing Xu | 4193eca | 2008-12-20 06:32:12 +0000 | [diff] [blame] | 2286 |     // Decls without InitExpr are not initialized explicitly. | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 2287 |     if (InitEx) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2288 |       SVal InitVal = GetSVal(state, InitEx); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 2289 |       QualType T = VD->getType(); | 
 | 2290 |        | 
 | 2291 |       // Recover some path-sensitivity if a scalar value evaluated to | 
 | 2292 |       // UnknownVal. | 
| Ted Kremenek | 276c6ac | 2009-03-11 02:24:48 +0000 | [diff] [blame] | 2293 |       if (InitVal.isUnknown() ||  | 
 | 2294 |           !getConstraintManager().canReasonAbout(InitVal)) { | 
| Ted Kremenek | 8d7f548 | 2009-04-09 22:22:44 +0000 | [diff] [blame] | 2295 |         InitVal = ValMgr.getConjuredSymbolVal(InitEx, Count); | 
| Ted Kremenek | af33741 | 2008-11-12 19:24:17 +0000 | [diff] [blame] | 2296 |       }         | 
 | 2297 |        | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2298 |       state = StateMgr.BindDecl(state, VD, InitVal); | 
| Ted Kremenek | 5b8d901 | 2009-02-14 01:54:57 +0000 | [diff] [blame] | 2299 |        | 
 | 2300 |       // The next thing to do is check if the GRTransferFuncs object wants to | 
 | 2301 |       // update the state based on the new binding.  If the GRTransferFunc | 
 | 2302 |       // object doesn't do anything, just auto-propagate the current state. | 
 | 2303 |       GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, state, DS,true); | 
 | 2304 |       getTF().EvalBind(BuilderRef, loc::MemRegionVal(StateMgr.getRegion(VD)), | 
 | 2305 |                        InitVal);       | 
 | 2306 |     }  | 
 | 2307 |     else { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2308 |       state = StateMgr.BindDeclWithNoInit(state, VD); | 
| Ted Kremenek | 5b8d901 | 2009-02-14 01:54:57 +0000 | [diff] [blame] | 2309 |       MakeNode(Dst, DS, *I, state); | 
| Ted Kremenek | efd5994 | 2008-12-08 22:47:34 +0000 | [diff] [blame] | 2310 |     } | 
| Ted Kremenek | 5b7dcce | 2008-04-22 22:25:27 +0000 | [diff] [blame] | 2311 |   } | 
| Ted Kremenek | 9de04c4 | 2008-01-24 20:55:43 +0000 | [diff] [blame] | 2312 | } | 
| Ted Kremenek | 874d63f | 2008-01-24 02:02:54 +0000 | [diff] [blame] | 2313 |  | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2314 | namespace { | 
 | 2315 |   // This class is used by VisitInitListExpr as an item in a worklist | 
 | 2316 |   // for processing the values contained in an InitListExpr. | 
 | 2317 | class VISIBILITY_HIDDEN InitListWLItem { | 
 | 2318 | public: | 
 | 2319 |   llvm::ImmutableList<SVal> Vals; | 
 | 2320 |   GRExprEngine::NodeTy* N; | 
 | 2321 |   InitListExpr::reverse_iterator Itr; | 
 | 2322 |    | 
 | 2323 |   InitListWLItem(GRExprEngine::NodeTy* n, llvm::ImmutableList<SVal> vals, | 
 | 2324 |          InitListExpr::reverse_iterator itr) | 
 | 2325 |   : Vals(vals), N(n), Itr(itr) {} | 
 | 2326 | }; | 
 | 2327 | } | 
 | 2328 |  | 
 | 2329 |  | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2330 | void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,  | 
 | 2331 |                                      NodeSet& Dst) { | 
| Ted Kremenek | a49e367 | 2008-10-30 23:14:36 +0000 | [diff] [blame] | 2332 |  | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2333 |   const GRState* state = GetState(Pred); | 
| Ted Kremenek | 76dba7b | 2008-11-13 05:05:34 +0000 | [diff] [blame] | 2334 |   QualType T = getContext().getCanonicalType(E->getType()); | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2335 |   unsigned NumInitElements = E->getNumInits();   | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2336 |  | 
| Zhongxing Xu | 05d1c57 | 2008-10-30 05:35:59 +0000 | [diff] [blame] | 2337 |   if (T->isArrayType() || T->isStructureType()) { | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2338 |  | 
| Ted Kremenek | a49e367 | 2008-10-30 23:14:36 +0000 | [diff] [blame] | 2339 |     llvm::ImmutableList<SVal> StartVals = getBasicVals().getEmptySValList(); | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2340 |      | 
| Ted Kremenek | a49e367 | 2008-10-30 23:14:36 +0000 | [diff] [blame] | 2341 |     // Handle base case where the initializer has no elements. | 
 | 2342 |     // e.g: static int* myArray[] = {}; | 
 | 2343 |     if (NumInitElements == 0) { | 
 | 2344 |       SVal V = NonLoc::MakeCompoundVal(T, StartVals, getBasicVals()); | 
 | 2345 |       MakeNode(Dst, E, Pred, BindExpr(state, E, V)); | 
 | 2346 |       return; | 
 | 2347 |     }       | 
 | 2348 |      | 
 | 2349 |     // Create a worklist to process the initializers. | 
 | 2350 |     llvm::SmallVector<InitListWLItem, 10> WorkList; | 
 | 2351 |     WorkList.reserve(NumInitElements);   | 
 | 2352 |     WorkList.push_back(InitListWLItem(Pred, StartVals, E->rbegin()));     | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2353 |     InitListExpr::reverse_iterator ItrEnd = E->rend(); | 
 | 2354 |      | 
| Ted Kremenek | a49e367 | 2008-10-30 23:14:36 +0000 | [diff] [blame] | 2355 |     // Process the worklist until it is empty. | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2356 |     while (!WorkList.empty()) { | 
 | 2357 |       InitListWLItem X = WorkList.back(); | 
 | 2358 |       WorkList.pop_back(); | 
 | 2359 |        | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2360 |       NodeSet Tmp; | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2361 |       Visit(*X.Itr, X.N, Tmp); | 
 | 2362 |        | 
 | 2363 |       InitListExpr::reverse_iterator NewItr = X.Itr + 1; | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2364 |  | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2365 |       for (NodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) { | 
 | 2366 |         // Get the last initializer value. | 
 | 2367 |         state = GetState(*NI); | 
 | 2368 |         SVal InitV = GetSVal(state, cast<Expr>(*X.Itr)); | 
 | 2369 |          | 
 | 2370 |         // Construct the new list of values by prepending the new value to | 
 | 2371 |         // the already constructed list. | 
 | 2372 |         llvm::ImmutableList<SVal> NewVals = | 
 | 2373 |           getBasicVals().consVals(InitV, X.Vals); | 
 | 2374 |          | 
 | 2375 |         if (NewItr == ItrEnd) { | 
| Zhongxing Xu | a189dca | 2008-10-31 03:01:26 +0000 | [diff] [blame] | 2376 |           // Now we have a list holding all init values. Make CompoundValData. | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2377 |           SVal V = NonLoc::MakeCompoundVal(T, NewVals, getBasicVals()); | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2378 |  | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2379 |           // Make final state and node. | 
| Ted Kremenek | 4456da5 | 2008-10-30 18:37:08 +0000 | [diff] [blame] | 2380 |           MakeNode(Dst, E, *NI, BindExpr(state, E, V)); | 
| Ted Kremenek | f75b186 | 2008-10-30 17:47:32 +0000 | [diff] [blame] | 2381 |         } | 
 | 2382 |         else { | 
 | 2383 |           // Still some initializer values to go.  Push them onto the worklist. | 
 | 2384 |           WorkList.push_back(InitListWLItem(*NI, NewVals, NewItr)); | 
 | 2385 |         } | 
 | 2386 |       } | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2387 |     } | 
| Ted Kremenek | 8790307 | 2008-10-30 18:34:31 +0000 | [diff] [blame] | 2388 |      | 
 | 2389 |     return; | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2390 |   } | 
 | 2391 |  | 
| Ted Kremenek | 062e2f9 | 2008-11-13 06:10:40 +0000 | [diff] [blame] | 2392 |   if (T->isUnionType() || T->isVectorType()) { | 
 | 2393 |     // FIXME: to be implemented. | 
 | 2394 |     // Note: That vectors can return true for T->isIntegerType() | 
 | 2395 |     MakeNode(Dst, E, Pred, state); | 
 | 2396 |     return; | 
 | 2397 |   } | 
 | 2398 |    | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2399 |   if (Loc::IsLocType(T) || T->isIntegerType()) { | 
 | 2400 |     assert (E->getNumInits() == 1); | 
 | 2401 |     NodeSet Tmp; | 
 | 2402 |     Expr* Init = E->getInit(0); | 
 | 2403 |     Visit(Init, Pred, Tmp); | 
 | 2404 |     for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I != EI; ++I) { | 
 | 2405 |       state = GetState(*I); | 
| Zhongxing Xu | 8cd5aae | 2008-10-30 05:33:54 +0000 | [diff] [blame] | 2406 |       MakeNode(Dst, E, *I, BindExpr(state, E, GetSVal(state, Init))); | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2407 |     } | 
 | 2408 |     return; | 
 | 2409 |   } | 
 | 2410 |  | 
| Zhongxing Xu | c4f8706 | 2008-10-30 05:02:23 +0000 | [diff] [blame] | 2411 |  | 
 | 2412 |   printf("InitListExpr type = %s\n", T.getAsString().c_str()); | 
 | 2413 |   assert(0 && "unprocessed InitListExpr type"); | 
 | 2414 | } | 
| Ted Kremenek | f233d48 | 2008-02-05 00:26:40 +0000 | [diff] [blame] | 2415 |  | 
| Sebastian Redl | 0518999 | 2008-11-11 17:56:53 +0000 | [diff] [blame] | 2416 | /// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type). | 
 | 2417 | void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, | 
 | 2418 |                                           NodeTy* Pred, | 
 | 2419 |                                           NodeSet& Dst) { | 
 | 2420 |   QualType T = Ex->getTypeOfArgument(); | 
| Ted Kremenek | 87e8034 | 2008-03-15 03:13:20 +0000 | [diff] [blame] | 2421 |   uint64_t amt;   | 
 | 2422 |    | 
 | 2423 |   if (Ex->isSizeOf()) { | 
| Ted Kremenek | 55f7bcb | 2008-12-15 18:51:00 +0000 | [diff] [blame] | 2424 |     if (T == getContext().VoidTy) {           | 
 | 2425 |       // sizeof(void) == 1 byte. | 
 | 2426 |       amt = 1; | 
 | 2427 |     } | 
 | 2428 |     else if (!T.getTypePtr()->isConstantSizeType()) { | 
 | 2429 |       // FIXME: Add support for VLAs. | 
| Ted Kremenek | 87e8034 | 2008-03-15 03:13:20 +0000 | [diff] [blame] | 2430 |       return; | 
| Ted Kremenek | 55f7bcb | 2008-12-15 18:51:00 +0000 | [diff] [blame] | 2431 |     } | 
 | 2432 |     else if (T->isObjCInterfaceType()) { | 
 | 2433 |       // Some code tries to take the sizeof an ObjCInterfaceType, relying that | 
 | 2434 |       // the compiler has laid out its representation.  Just report Unknown | 
 | 2435 |       // for these.       | 
| Ted Kremenek | f342d18 | 2008-04-30 21:31:12 +0000 | [diff] [blame] | 2436 |       return; | 
| Ted Kremenek | 55f7bcb | 2008-12-15 18:51:00 +0000 | [diff] [blame] | 2437 |     } | 
 | 2438 |     else { | 
 | 2439 |       // All other cases. | 
| Ted Kremenek | 87e8034 | 2008-03-15 03:13:20 +0000 | [diff] [blame] | 2440 |       amt = getContext().getTypeSize(T) / 8; | 
| Ted Kremenek | 55f7bcb | 2008-12-15 18:51:00 +0000 | [diff] [blame] | 2441 |     }     | 
| Ted Kremenek | 87e8034 | 2008-03-15 03:13:20 +0000 | [diff] [blame] | 2442 |   } | 
 | 2443 |   else  // Get alignment of the type. | 
| Ted Kremenek | 897781a | 2008-03-15 03:13:55 +0000 | [diff] [blame] | 2444 |     amt = getContext().getTypeAlign(T) / 8; | 
| Ted Kremenek | d9435bf | 2008-02-12 19:49:57 +0000 | [diff] [blame] | 2445 |    | 
| Ted Kremenek | 0e561a3 | 2008-03-21 21:30:14 +0000 | [diff] [blame] | 2446 |   MakeNode(Dst, Ex, Pred, | 
| Zhongxing Xu | 8cd5aae | 2008-10-30 05:33:54 +0000 | [diff] [blame] | 2447 |            BindExpr(GetState(Pred), Ex, | 
 | 2448 |                     NonLoc::MakeVal(getBasicVals(), amt, Ex->getType())));   | 
| Ted Kremenek | d9435bf | 2008-02-12 19:49:57 +0000 | [diff] [blame] | 2449 | } | 
 | 2450 |  | 
| Ted Kremenek | d8e9f0d | 2008-02-20 04:02:35 +0000 | [diff] [blame] | 2451 |  | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2452 | void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2453 |                                       NodeSet& Dst, bool asLValue) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2454 |  | 
| Ted Kremenek | d8e9f0d | 2008-02-20 04:02:35 +0000 | [diff] [blame] | 2455 |   switch (U->getOpcode()) { | 
| Ted Kremenek | d8e9f0d | 2008-02-20 04:02:35 +0000 | [diff] [blame] | 2456 |        | 
 | 2457 |     default: | 
| Ted Kremenek | d8e9f0d | 2008-02-20 04:02:35 +0000 | [diff] [blame] | 2458 |       break; | 
| Ted Kremenek | b8e26e6 | 2008-06-19 17:55:38 +0000 | [diff] [blame] | 2459 |            | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2460 |     case UnaryOperator::Deref: { | 
 | 2461 |        | 
 | 2462 |       Expr* Ex = U->getSubExpr()->IgnoreParens(); | 
 | 2463 |       NodeSet Tmp; | 
 | 2464 |       Visit(Ex, Pred, Tmp); | 
 | 2465 |        | 
 | 2466 |       for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2467 |          | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2468 |         const GRState* state = GetState(*I); | 
 | 2469 |         SVal location = GetSVal(state, Ex); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2470 |          | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2471 |         if (asLValue) | 
| Ted Kremenek | 7090d54 | 2009-05-07 18:27:16 +0000 | [diff] [blame] | 2472 |           MakeNode(Dst, U, *I, BindExpr(state, U, location), | 
 | 2473 |                    ProgramPoint::PostLValueKind); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2474 |         else | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2475 |           EvalLoad(Dst, U, *I, state, location); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2476 |       }  | 
 | 2477 |  | 
 | 2478 |       return; | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2479 |     } | 
| Ted Kremenek | a084bb6 | 2008-04-30 21:45:55 +0000 | [diff] [blame] | 2480 |        | 
| Ted Kremenek | b8e26e6 | 2008-06-19 17:55:38 +0000 | [diff] [blame] | 2481 |     case UnaryOperator::Real: { | 
 | 2482 |        | 
 | 2483 |       Expr* Ex = U->getSubExpr()->IgnoreParens(); | 
 | 2484 |       NodeSet Tmp; | 
 | 2485 |       Visit(Ex, Pred, Tmp); | 
 | 2486 |        | 
 | 2487 |       for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { | 
 | 2488 |          | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2489 |         // FIXME: We don't have complex SValues yet. | 
| Ted Kremenek | b8e26e6 | 2008-06-19 17:55:38 +0000 | [diff] [blame] | 2490 |         if (Ex->getType()->isAnyComplexType()) { | 
 | 2491 |           // Just report "Unknown." | 
 | 2492 |           Dst.Add(*I); | 
 | 2493 |           continue; | 
 | 2494 |         } | 
 | 2495 |          | 
 | 2496 |         // For all other types, UnaryOperator::Real is an identity operation. | 
 | 2497 |         assert (U->getType() == Ex->getType()); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2498 |         const GRState* state = GetState(*I); | 
 | 2499 |         MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex))); | 
| Ted Kremenek | b8e26e6 | 2008-06-19 17:55:38 +0000 | [diff] [blame] | 2500 |       }  | 
 | 2501 |        | 
 | 2502 |       return; | 
 | 2503 |     } | 
 | 2504 |        | 
 | 2505 |     case UnaryOperator::Imag: { | 
 | 2506 |        | 
 | 2507 |       Expr* Ex = U->getSubExpr()->IgnoreParens(); | 
 | 2508 |       NodeSet Tmp; | 
 | 2509 |       Visit(Ex, Pred, Tmp); | 
 | 2510 |        | 
 | 2511 |       for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2512 |         // FIXME: We don't have complex SValues yet. | 
| Ted Kremenek | b8e26e6 | 2008-06-19 17:55:38 +0000 | [diff] [blame] | 2513 |         if (Ex->getType()->isAnyComplexType()) { | 
 | 2514 |           // Just report "Unknown." | 
 | 2515 |           Dst.Add(*I); | 
 | 2516 |           continue; | 
 | 2517 |         } | 
 | 2518 |          | 
 | 2519 |         // For all other types, UnaryOperator::Float returns 0. | 
 | 2520 |         assert (Ex->getType()->isIntegerType()); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2521 |         const GRState* state = GetState(*I); | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2522 |         SVal X = NonLoc::MakeVal(getBasicVals(), 0, Ex->getType()); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2523 |         MakeNode(Dst, U, *I, BindExpr(state, U, X)); | 
| Ted Kremenek | b8e26e6 | 2008-06-19 17:55:38 +0000 | [diff] [blame] | 2524 |       } | 
 | 2525 |        | 
 | 2526 |       return; | 
 | 2527 |     } | 
 | 2528 |        | 
 | 2529 |       // FIXME: Just report "Unknown" for OffsetOf.       | 
| Ted Kremenek | a084bb6 | 2008-04-30 21:45:55 +0000 | [diff] [blame] | 2530 |     case UnaryOperator::OffsetOf: | 
| Ted Kremenek | a084bb6 | 2008-04-30 21:45:55 +0000 | [diff] [blame] | 2531 |       Dst.Add(Pred); | 
 | 2532 |       return; | 
 | 2533 |        | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2534 |     case UnaryOperator::Plus: assert (!asLValue);  // FALL-THROUGH. | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2535 |     case UnaryOperator::Extension: { | 
 | 2536 |        | 
 | 2537 |       // Unary "+" is a no-op, similar to a parentheses.  We still have places | 
 | 2538 |       // where it may be a block-level expression, so we need to | 
 | 2539 |       // generate an extra node that just propagates the value of the | 
 | 2540 |       // subexpression. | 
 | 2541 |  | 
 | 2542 |       Expr* Ex = U->getSubExpr()->IgnoreParens(); | 
 | 2543 |       NodeSet Tmp; | 
 | 2544 |       Visit(Ex, Pred, Tmp); | 
 | 2545 |        | 
 | 2546 |       for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {         | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2547 |         const GRState* state = GetState(*I); | 
 | 2548 |         MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex))); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2549 |       } | 
 | 2550 |        | 
 | 2551 |       return; | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2552 |     } | 
| Ted Kremenek | 7b8009a | 2008-01-24 02:28:56 +0000 | [diff] [blame] | 2553 |      | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2554 |     case UnaryOperator::AddrOf: { | 
| Ted Kremenek | d8e9f0d | 2008-02-20 04:02:35 +0000 | [diff] [blame] | 2555 |        | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2556 |       assert(!asLValue); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2557 |       Expr* Ex = U->getSubExpr()->IgnoreParens(); | 
 | 2558 |       NodeSet Tmp; | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2559 |       VisitLValue(Ex, Pred, Tmp); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2560 |       | 
 | 2561 |       for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {         | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2562 |         const GRState* state = GetState(*I); | 
 | 2563 |         SVal V = GetSVal(state, Ex); | 
 | 2564 |         state = BindExpr(state, U, V); | 
 | 2565 |         MakeNode(Dst, U, *I, state); | 
| Ted Kremenek | 89063af | 2008-02-21 19:15:37 +0000 | [diff] [blame] | 2566 |       } | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2567 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2568 |       return;  | 
 | 2569 |     } | 
 | 2570 |        | 
 | 2571 |     case UnaryOperator::LNot: | 
 | 2572 |     case UnaryOperator::Minus: | 
 | 2573 |     case UnaryOperator::Not: { | 
 | 2574 |        | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2575 |       assert (!asLValue); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2576 |       Expr* Ex = U->getSubExpr()->IgnoreParens(); | 
 | 2577 |       NodeSet Tmp; | 
 | 2578 |       Visit(Ex, Pred, Tmp); | 
 | 2579 |        | 
 | 2580 |       for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {         | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2581 |         const GRState* state = GetState(*I); | 
| Ted Kremenek | 855cd90 | 2008-09-30 05:32:44 +0000 | [diff] [blame] | 2582 |          | 
 | 2583 |         // Get the value of the subexpression. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2584 |         SVal V = GetSVal(state, Ex); | 
| Ted Kremenek | 855cd90 | 2008-09-30 05:32:44 +0000 | [diff] [blame] | 2585 |  | 
| Ted Kremenek | e04a5cb | 2008-11-15 00:20:05 +0000 | [diff] [blame] | 2586 |         if (V.isUnknownOrUndef()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2587 |           MakeNode(Dst, U, *I, BindExpr(state, U, V)); | 
| Ted Kremenek | e04a5cb | 2008-11-15 00:20:05 +0000 | [diff] [blame] | 2588 |           continue; | 
 | 2589 |         } | 
 | 2590 |          | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 2591 | //        QualType DstT = getContext().getCanonicalType(U->getType()); | 
 | 2592 | //        QualType SrcT = getContext().getCanonicalType(Ex->getType()); | 
 | 2593 | //         | 
 | 2594 | //        if (DstT != SrcT) // Perform promotions. | 
 | 2595 | //          V = EvalCast(V, DstT);  | 
 | 2596 | //         | 
 | 2597 | //        if (V.isUnknownOrUndef()) { | 
 | 2598 | //          MakeNode(Dst, U, *I, BindExpr(St, U, V)); | 
 | 2599 | //          continue; | 
 | 2600 | //        } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2601 |          | 
 | 2602 |         switch (U->getOpcode()) { | 
 | 2603 |           default: | 
 | 2604 |             assert(false && "Invalid Opcode."); | 
 | 2605 |             break; | 
 | 2606 |              | 
 | 2607 |           case UnaryOperator::Not: | 
| Ted Kremenek | 60a6e0c | 2008-10-01 00:21:14 +0000 | [diff] [blame] | 2608 |             // FIXME: Do we need to handle promotions? | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2609 |             state = BindExpr(state, U, EvalComplement(cast<NonLoc>(V))); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2610 |             break;             | 
 | 2611 |              | 
 | 2612 |           case UnaryOperator::Minus: | 
| Ted Kremenek | 60a6e0c | 2008-10-01 00:21:14 +0000 | [diff] [blame] | 2613 |             // FIXME: Do we need to handle promotions? | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2614 |             state = BindExpr(state, U, EvalMinus(U, cast<NonLoc>(V))); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2615 |             break;    | 
 | 2616 |              | 
 | 2617 |           case UnaryOperator::LNot:    | 
 | 2618 |              | 
 | 2619 |             // C99 6.5.3.3: "The expression !E is equivalent to (0==E)." | 
 | 2620 |             // | 
 | 2621 |             //  Note: technically we do "E == 0", but this is the same in the | 
 | 2622 |             //    transfer functions as "0 == E". | 
 | 2623 |              | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2624 |             if (isa<Loc>(V)) { | 
| Ted Kremenek | da9ae60 | 2009-04-08 18:51:08 +0000 | [diff] [blame] | 2625 |               Loc X = Loc::MakeNull(getBasicVals()); | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 2626 |               SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast<Loc>(V), X, | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 2627 |                                       U->getType()); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2628 |               state = BindExpr(state, U, Result); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2629 |             } | 
 | 2630 |             else { | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 2631 |               nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 2632 | #if 0             | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2633 |               SVal Result = EvalBinOp(BinaryOperator::EQ, cast<NonLoc>(V), X); | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2634 |               state = SetSVal(state, U, Result); | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 2635 | #else | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 2636 |               EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLoc>(V), X, *I, | 
 | 2637 |                         U->getType()); | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 2638 |               continue; | 
 | 2639 | #endif | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2640 |             } | 
 | 2641 |              | 
 | 2642 |             break; | 
 | 2643 |         } | 
 | 2644 |          | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2645 |         MakeNode(Dst, U, *I, state); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2646 |       } | 
 | 2647 |        | 
 | 2648 |       return; | 
 | 2649 |     } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2650 |   } | 
 | 2651 |  | 
 | 2652 |   // Handle ++ and -- (both pre- and post-increment). | 
 | 2653 |  | 
 | 2654 |   assert (U->isIncrementDecrementOp()); | 
 | 2655 |   NodeSet Tmp; | 
 | 2656 |   Expr* Ex = U->getSubExpr()->IgnoreParens(); | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2657 |   VisitLValue(Ex, Pred, Tmp); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2658 |    | 
 | 2659 |   for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) { | 
 | 2660 |      | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2661 |     const GRState* state = GetState(*I); | 
 | 2662 |     SVal V1 = GetSVal(state, Ex); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2663 |      | 
 | 2664 |     // Perform a load.       | 
 | 2665 |     NodeSet Tmp2; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2666 |     EvalLoad(Tmp2, Ex, *I, state, V1); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2667 |  | 
 | 2668 |     for (NodeSet::iterator I2 = Tmp2.begin(), E2 = Tmp2.end(); I2!=E2; ++I2) { | 
 | 2669 |          | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2670 |       state = GetState(*I2); | 
 | 2671 |       SVal V2 = GetSVal(state, Ex); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2672 |          | 
 | 2673 |       // Propagate unknown and undefined values.       | 
 | 2674 |       if (V2.isUnknownOrUndef()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2675 |         MakeNode(Dst, U, *I2, BindExpr(state, U, V2)); | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2676 |         continue; | 
 | 2677 |       } | 
 | 2678 |        | 
| Ted Kremenek | 21028dd | 2009-03-11 03:54:24 +0000 | [diff] [blame] | 2679 |       // Handle all other values.       | 
| Ted Kremenek | 50d0ac2 | 2008-02-15 22:09:30 +0000 | [diff] [blame] | 2680 |       BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add | 
 | 2681 |                                                      : BinaryOperator::Sub; | 
| Ted Kremenek | 21028dd | 2009-03-11 03:54:24 +0000 | [diff] [blame] | 2682 |  | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 2683 |       SVal Result = EvalBinOp(state, Op, V2, MakeConstantVal(1U, U),  | 
 | 2684 |                               U->getType());     | 
| Ted Kremenek | bb9b271 | 2009-03-20 20:10:45 +0000 | [diff] [blame] | 2685 |        | 
 | 2686 |       // Conjure a new symbol if necessary to recover precision. | 
| Ted Kremenek | af48fdd | 2009-04-21 22:38:05 +0000 | [diff] [blame] | 2687 |       if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){ | 
| Ted Kremenek | 8d7f548 | 2009-04-09 22:22:44 +0000 | [diff] [blame] | 2688 |         Result = ValMgr.getConjuredSymbolVal(Ex, | 
 | 2689 |                                              Builder->getCurrentBlockCount()); | 
| Ted Kremenek | af48fdd | 2009-04-21 22:38:05 +0000 | [diff] [blame] | 2690 |          | 
 | 2691 |         // If the value is a location, ++/-- should always preserve | 
 | 2692 |         // non-nullness.  Check if the original value was non-null, and if so propagate | 
 | 2693 |         // that constraint.         | 
 | 2694 |         if (Loc::IsLocType(U->getType())) { | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 2695 |           SVal Constraint = EvalBinOp(state, BinaryOperator::EQ, V2, | 
| Ted Kremenek | af48fdd | 2009-04-21 22:38:05 +0000 | [diff] [blame] | 2696 |                                       ValMgr.makeZeroVal(U->getType()), | 
 | 2697 |                                       getContext().IntTy);           | 
 | 2698 |            | 
 | 2699 |           bool isFeasible = false; | 
 | 2700 |           Assume(state, Constraint, true, isFeasible); | 
 | 2701 |           if (!isFeasible) { | 
 | 2702 |             // It isn't feasible for the original value to be null. | 
 | 2703 |             // Propagate this constraint. | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 2704 |             Constraint = EvalBinOp(state, BinaryOperator::EQ, Result, | 
| Ted Kremenek | af48fdd | 2009-04-21 22:38:05 +0000 | [diff] [blame] | 2705 |                                    ValMgr.makeZeroVal(U->getType()), | 
 | 2706 |                                    getContext().IntTy); | 
 | 2707 |              | 
 | 2708 |             bool isFeasible = false; | 
 | 2709 |             state = Assume(state, Constraint, false, isFeasible); | 
 | 2710 |             assert(isFeasible && state); | 
 | 2711 |           }             | 
 | 2712 |         }         | 
 | 2713 |       } | 
| Ted Kremenek | bb9b271 | 2009-03-20 20:10:45 +0000 | [diff] [blame] | 2714 |        | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2715 |       state = BindExpr(state, U, U->isPostfix() ? V2 : Result); | 
| Ted Kremenek | cf78b6a | 2008-02-06 22:50:25 +0000 | [diff] [blame] | 2716 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2717 |       // Perform the store.       | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2718 |       EvalStore(Dst, U, *I2, state, V1, Result); | 
| Ted Kremenek | 5b6dc2d | 2008-02-07 01:08:27 +0000 | [diff] [blame] | 2719 |     } | 
| Ted Kremenek | 469ecbd | 2008-04-21 23:43:38 +0000 | [diff] [blame] | 2720 |   } | 
| Ted Kremenek | 5b6dc2d | 2008-02-07 01:08:27 +0000 | [diff] [blame] | 2721 | } | 
 | 2722 |  | 
| Ted Kremenek | ef44bfb | 2008-03-17 21:11:24 +0000 | [diff] [blame] | 2723 | void GRExprEngine::VisitAsmStmt(AsmStmt* A, NodeTy* Pred, NodeSet& Dst) { | 
 | 2724 |   VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst); | 
 | 2725 | }   | 
 | 2726 |  | 
 | 2727 | void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A, | 
 | 2728 |                                              AsmStmt::outputs_iterator I, | 
 | 2729 |                                              AsmStmt::outputs_iterator E, | 
 | 2730 |                                              NodeTy* Pred, NodeSet& Dst) { | 
 | 2731 |   if (I == E) { | 
 | 2732 |     VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst); | 
 | 2733 |     return; | 
 | 2734 |   } | 
 | 2735 |    | 
 | 2736 |   NodeSet Tmp; | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2737 |   VisitLValue(*I, Pred, Tmp); | 
| Ted Kremenek | ef44bfb | 2008-03-17 21:11:24 +0000 | [diff] [blame] | 2738 |    | 
 | 2739 |   ++I; | 
 | 2740 |    | 
 | 2741 |   for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI) | 
 | 2742 |     VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst); | 
 | 2743 | } | 
 | 2744 |  | 
 | 2745 | void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A, | 
 | 2746 |                                             AsmStmt::inputs_iterator I, | 
 | 2747 |                                             AsmStmt::inputs_iterator E, | 
 | 2748 |                                             NodeTy* Pred, NodeSet& Dst) { | 
 | 2749 |   if (I == E) { | 
 | 2750 |      | 
 | 2751 |     // We have processed both the inputs and the outputs.  All of the outputs | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2752 |     // should evaluate to Locs.  Nuke all of their values. | 
| Ted Kremenek | ef44bfb | 2008-03-17 21:11:24 +0000 | [diff] [blame] | 2753 |      | 
 | 2754 |     // FIXME: Some day in the future it would be nice to allow a "plug-in" | 
 | 2755 |     // which interprets the inline asm and stores proper results in the | 
 | 2756 |     // outputs. | 
 | 2757 |      | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2758 |     const GRState* state = GetState(Pred); | 
| Ted Kremenek | ef44bfb | 2008-03-17 21:11:24 +0000 | [diff] [blame] | 2759 |      | 
 | 2760 |     for (AsmStmt::outputs_iterator OI = A->begin_outputs(), | 
 | 2761 |                                    OE = A->end_outputs(); OI != OE; ++OI) { | 
 | 2762 |        | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2763 |       SVal X = GetSVal(state, *OI);       | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2764 |       assert (!isa<NonLoc>(X));  // Should be an Lval, or unknown, undef. | 
| Ted Kremenek | ef44bfb | 2008-03-17 21:11:24 +0000 | [diff] [blame] | 2765 |        | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2766 |       if (isa<Loc>(X)) | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2767 |         state = BindLoc(state, cast<Loc>(X), UnknownVal()); | 
| Ted Kremenek | ef44bfb | 2008-03-17 21:11:24 +0000 | [diff] [blame] | 2768 |     } | 
 | 2769 |      | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2770 |     MakeNode(Dst, A, Pred, state); | 
| Ted Kremenek | ef44bfb | 2008-03-17 21:11:24 +0000 | [diff] [blame] | 2771 |     return; | 
 | 2772 |   } | 
 | 2773 |    | 
 | 2774 |   NodeSet Tmp; | 
 | 2775 |   Visit(*I, Pred, Tmp); | 
 | 2776 |    | 
 | 2777 |   ++I; | 
 | 2778 |    | 
 | 2779 |   for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI) | 
 | 2780 |     VisitAsmStmtHelperInputs(A, I, E, *NI, Dst); | 
 | 2781 | } | 
 | 2782 |  | 
| Ted Kremenek | 6b31e8e | 2008-04-16 23:05:51 +0000 | [diff] [blame] | 2783 | void GRExprEngine::EvalReturn(NodeSet& Dst, ReturnStmt* S, NodeTy* Pred) { | 
 | 2784 |   assert (Builder && "GRStmtNodeBuilder must be defined."); | 
 | 2785 |    | 
 | 2786 |   unsigned size = Dst.size();   | 
| Ted Kremenek | b053396 | 2008-04-18 20:35:30 +0000 | [diff] [blame] | 2787 |  | 
| Ted Kremenek | 186350f | 2008-04-23 20:12:28 +0000 | [diff] [blame] | 2788 |   SaveAndRestore<bool> OldSink(Builder->BuildSinks); | 
 | 2789 |   SaveOr OldHasGen(Builder->HasGeneratedNode); | 
| Ted Kremenek | b053396 | 2008-04-18 20:35:30 +0000 | [diff] [blame] | 2790 |  | 
| Ted Kremenek | 729a9a2 | 2008-07-17 23:15:45 +0000 | [diff] [blame] | 2791 |   getTF().EvalReturn(Dst, *this, *Builder, S, Pred); | 
| Ted Kremenek | 6b31e8e | 2008-04-16 23:05:51 +0000 | [diff] [blame] | 2792 |    | 
| Ted Kremenek | b053396 | 2008-04-18 20:35:30 +0000 | [diff] [blame] | 2793 |   // Handle the case where no nodes where generated. | 
| Ted Kremenek | 6b31e8e | 2008-04-16 23:05:51 +0000 | [diff] [blame] | 2794 |    | 
| Ted Kremenek | b053396 | 2008-04-18 20:35:30 +0000 | [diff] [blame] | 2795 |   if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode) | 
| Ted Kremenek | 6b31e8e | 2008-04-16 23:05:51 +0000 | [diff] [blame] | 2796 |     MakeNode(Dst, S, Pred, GetState(Pred)); | 
 | 2797 | } | 
 | 2798 |  | 
| Ted Kremenek | 02737ed | 2008-03-31 15:02:58 +0000 | [diff] [blame] | 2799 | void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) { | 
 | 2800 |  | 
 | 2801 |   Expr* R = S->getRetValue(); | 
 | 2802 |    | 
 | 2803 |   if (!R) { | 
| Ted Kremenek | 6b31e8e | 2008-04-16 23:05:51 +0000 | [diff] [blame] | 2804 |     EvalReturn(Dst, S, Pred); | 
| Ted Kremenek | 02737ed | 2008-03-31 15:02:58 +0000 | [diff] [blame] | 2805 |     return; | 
 | 2806 |   } | 
| Ted Kremenek | 6b31e8e | 2008-04-16 23:05:51 +0000 | [diff] [blame] | 2807 |  | 
| Ted Kremenek | 5917d78 | 2008-11-21 00:27:44 +0000 | [diff] [blame] | 2808 |   NodeSet Tmp; | 
 | 2809 |   Visit(R, Pred, Tmp); | 
| Ted Kremenek | 02737ed | 2008-03-31 15:02:58 +0000 | [diff] [blame] | 2810 |  | 
| Ted Kremenek | 5917d78 | 2008-11-21 00:27:44 +0000 | [diff] [blame] | 2811 |   for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) { | 
 | 2812 |     SVal X = GetSVal((*I)->getState(), R); | 
 | 2813 |      | 
 | 2814 |     // Check if we return the address of a stack variable. | 
 | 2815 |     if (isa<loc::MemRegionVal>(X)) { | 
 | 2816 |       // Determine if the value is on the stack. | 
 | 2817 |       const MemRegion* R = cast<loc::MemRegionVal>(&X)->getRegion(); | 
| Ted Kremenek | 02737ed | 2008-03-31 15:02:58 +0000 | [diff] [blame] | 2818 |        | 
| Ted Kremenek | 5917d78 | 2008-11-21 00:27:44 +0000 | [diff] [blame] | 2819 |       if (R && getStateManager().hasStackStorage(R)) { | 
 | 2820 |         // Create a special node representing the error. | 
 | 2821 |         if (NodeTy* N = Builder->generateNode(S, GetState(*I), *I)) { | 
 | 2822 |           N->markAsSink(); | 
 | 2823 |           RetsStackAddr.insert(N); | 
 | 2824 |         } | 
 | 2825 |         continue; | 
 | 2826 |       } | 
| Ted Kremenek | 02737ed | 2008-03-31 15:02:58 +0000 | [diff] [blame] | 2827 |     } | 
| Ted Kremenek | 5917d78 | 2008-11-21 00:27:44 +0000 | [diff] [blame] | 2828 |     // Check if we return an undefined value. | 
 | 2829 |     else if (X.isUndef()) { | 
 | 2830 |       if (NodeTy* N = Builder->generateNode(S, GetState(*I), *I)) { | 
 | 2831 |         N->markAsSink(); | 
 | 2832 |         RetsUndef.insert(N); | 
 | 2833 |       } | 
 | 2834 |       continue; | 
 | 2835 |     } | 
 | 2836 |      | 
| Ted Kremenek | 6b31e8e | 2008-04-16 23:05:51 +0000 | [diff] [blame] | 2837 |     EvalReturn(Dst, S, *I); | 
| Ted Kremenek | 5917d78 | 2008-11-21 00:27:44 +0000 | [diff] [blame] | 2838 |   } | 
| Ted Kremenek | 02737ed | 2008-03-31 15:02:58 +0000 | [diff] [blame] | 2839 | } | 
| Ted Kremenek | 55deb97 | 2008-03-25 00:34:37 +0000 | [diff] [blame] | 2840 |  | 
| Ted Kremenek | e695e1c | 2008-04-15 23:06:53 +0000 | [diff] [blame] | 2841 | //===----------------------------------------------------------------------===// | 
 | 2842 | // Transfer functions: Binary operators. | 
 | 2843 | //===----------------------------------------------------------------------===// | 
 | 2844 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2845 | const GRState* GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* state, | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 2846 |                                              NodeTy* Pred, SVal Denom) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2847 |    | 
 | 2848 |   // Divide by undefined? (potentially zero) | 
 | 2849 |    | 
 | 2850 |   if (Denom.isUndef()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2851 |     NodeTy* DivUndef = Builder->generateNode(Ex, state, Pred); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2852 |      | 
 | 2853 |     if (DivUndef) { | 
 | 2854 |       DivUndef->markAsSink(); | 
 | 2855 |       ExplicitBadDivides.insert(DivUndef); | 
 | 2856 |     } | 
 | 2857 |      | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 2858 |     return 0; | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2859 |   } | 
 | 2860 |    | 
 | 2861 |   // Check for divide/remainder-by-zero. | 
 | 2862 |   // First, "assume" that the denominator is 0 or undefined.             | 
 | 2863 |    | 
 | 2864 |   bool isFeasibleZero = false; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2865 |   const GRState* ZeroSt =  Assume(state, Denom, false, isFeasibleZero); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2866 |    | 
 | 2867 |   // Second, "assume" that the denominator cannot be 0.             | 
 | 2868 |    | 
 | 2869 |   bool isFeasibleNotZero = false; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2870 |   state = Assume(state, Denom, true, isFeasibleNotZero); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2871 |    | 
 | 2872 |   // Create the node for the divide-by-zero (if it occurred). | 
 | 2873 |    | 
 | 2874 |   if (isFeasibleZero) | 
 | 2875 |     if (NodeTy* DivZeroNode = Builder->generateNode(Ex, ZeroSt, Pred)) { | 
 | 2876 |       DivZeroNode->markAsSink(); | 
 | 2877 |        | 
 | 2878 |       if (isFeasibleNotZero) | 
 | 2879 |         ImplicitBadDivides.insert(DivZeroNode); | 
 | 2880 |       else | 
 | 2881 |         ExplicitBadDivides.insert(DivZeroNode); | 
 | 2882 |        | 
 | 2883 |     } | 
 | 2884 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2885 |   return isFeasibleNotZero ? state : 0; | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2886 | } | 
 | 2887 |  | 
| Ted Kremenek | 4d4dd85 | 2008-02-13 17:41:41 +0000 | [diff] [blame] | 2888 | void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 2889 |                                        GRExprEngine::NodeTy* Pred, | 
 | 2890 |                                        GRExprEngine::NodeSet& Dst) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2891 |  | 
 | 2892 |   NodeSet Tmp1; | 
 | 2893 |   Expr* LHS = B->getLHS()->IgnoreParens(); | 
 | 2894 |   Expr* RHS = B->getRHS()->IgnoreParens(); | 
| Ted Kremenek | 5b6dc2d | 2008-02-07 01:08:27 +0000 | [diff] [blame] | 2895 |    | 
| Ted Kremenek | 759623e | 2008-12-06 02:39:30 +0000 | [diff] [blame] | 2896 |   // FIXME: Add proper support for ObjCKVCRefExpr. | 
 | 2897 |   if (isa<ObjCKVCRefExpr>(LHS)) { | 
 | 2898 |     Visit(RHS, Pred, Dst);    | 
 | 2899 |     return; | 
 | 2900 |   } | 
 | 2901 |    | 
| Ted Kremenek | 5b6dc2d | 2008-02-07 01:08:27 +0000 | [diff] [blame] | 2902 |   if (B->isAssignmentOp()) | 
| Zhongxing Xu | 6d69b5d | 2008-10-16 06:09:51 +0000 | [diff] [blame] | 2903 |     VisitLValue(LHS, Pred, Tmp1); | 
| Ted Kremenek | 5b6dc2d | 2008-02-07 01:08:27 +0000 | [diff] [blame] | 2904 |   else | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2905 |     Visit(LHS, Pred, Tmp1); | 
| Ted Kremenek | cb448ca | 2008-01-16 00:53:15 +0000 | [diff] [blame] | 2906 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2907 |   for (NodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1 != E1; ++I1) { | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2908 |  | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 2909 |     SVal LeftV = GetSVal((*I1)->getState(), LHS); | 
| Ted Kremenek | e00fe3f | 2008-01-17 00:52:48 +0000 | [diff] [blame] | 2910 |      | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2911 |     // Process the RHS. | 
 | 2912 |      | 
 | 2913 |     NodeSet Tmp2; | 
 | 2914 |     Visit(RHS, *I1, Tmp2); | 
 | 2915 |      | 
 | 2916 |     // With both the LHS and RHS evaluated, process the operation itself. | 
 | 2917 |      | 
 | 2918 |     for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2 != E2; ++I2) { | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2919 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2920 |       const GRState* state = GetState(*I2); | 
 | 2921 |       const GRState* OldSt = state; | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 2922 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2923 |       SVal RightV = GetSVal(state, RHS); | 
| Ted Kremenek | cf78b6a | 2008-02-06 22:50:25 +0000 | [diff] [blame] | 2924 |       BinaryOperator::Opcode Op = B->getOpcode(); | 
 | 2925 |        | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2926 |       switch (Op) { | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2927 |            | 
| Ted Kremenek | ab2b8c5 | 2008-01-23 19:59:44 +0000 | [diff] [blame] | 2928 |         case BinaryOperator::Assign: { | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2929 |            | 
| Ted Kremenek | 361fa8e | 2008-03-12 21:45:47 +0000 | [diff] [blame] | 2930 |           // EXPERIMENTAL: "Conjured" symbols. | 
| Ted Kremenek | fd30194 | 2008-10-17 22:23:12 +0000 | [diff] [blame] | 2931 |           // FIXME: Handle structs. | 
 | 2932 |           QualType T = RHS->getType(); | 
| Ted Kremenek | 361fa8e | 2008-03-12 21:45:47 +0000 | [diff] [blame] | 2933 |            | 
| Ted Kremenek | 276c6ac | 2009-03-11 02:24:48 +0000 | [diff] [blame] | 2934 |           if ((RightV.isUnknown() ||  | 
 | 2935 |                !getConstraintManager().canReasonAbout(RightV))               | 
 | 2936 |               && (Loc::IsLocType(T) ||  | 
 | 2937 |                   (T->isScalarType() && T->isIntegerType()))) { | 
| Ted Kremenek | 8d7f548 | 2009-04-09 22:22:44 +0000 | [diff] [blame] | 2938 |             unsigned Count = Builder->getCurrentBlockCount();             | 
 | 2939 |             RightV = ValMgr.getConjuredSymbolVal(B->getRHS(), Count); | 
| Ted Kremenek | 361fa8e | 2008-03-12 21:45:47 +0000 | [diff] [blame] | 2940 |           } | 
 | 2941 |            | 
| Ted Kremenek | 361fa8e | 2008-03-12 21:45:47 +0000 | [diff] [blame] | 2942 |           // Simulate the effects of a "store":  bind the value of the RHS | 
| Ted Kremenek | 276c6ac | 2009-03-11 02:24:48 +0000 | [diff] [blame] | 2943 |           // to the L-Value represented by the LHS.           | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2944 |           EvalStore(Dst, B, LHS, *I2, BindExpr(state, B, RightV), LeftV, | 
 | 2945 |                     RightV); | 
| Ted Kremenek | e38718e | 2008-04-16 18:21:25 +0000 | [diff] [blame] | 2946 |           continue; | 
| Ted Kremenek | ab2b8c5 | 2008-01-23 19:59:44 +0000 | [diff] [blame] | 2947 |         } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2948 |            | 
 | 2949 |         case BinaryOperator::Div: | 
 | 2950 |         case BinaryOperator::Rem: | 
 | 2951 |            | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 2952 |           // Special checking for integer denominators.           | 
| Ted Kremenek | 062e2f9 | 2008-11-13 06:10:40 +0000 | [diff] [blame] | 2953 |           if (RHS->getType()->isIntegerType() &&  | 
 | 2954 |               RHS->getType()->isScalarType()) { | 
 | 2955 |              | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2956 |             state = CheckDivideZero(B, state, *I2, RightV); | 
 | 2957 |             if (!state) continue; | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 2958 |           } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2959 |            | 
 | 2960 |           // FALL-THROUGH. | 
| Ted Kremenek | ab2b8c5 | 2008-01-23 19:59:44 +0000 | [diff] [blame] | 2961 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2962 |         default: { | 
 | 2963 |        | 
 | 2964 |           if (B->isAssignmentOp()) | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2965 |             break; | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2966 |            | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2967 |           // Process non-assignements except commas or short-circuited | 
 | 2968 |           // logical expressions (LAnd and LOr). | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2969 |            | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 2970 |           SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType()); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2971 |            | 
 | 2972 |           if (Result.isUnknown()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2973 |             if (OldSt != state) { | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 2974 |               // Generate a new node if we have already created a new state. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2975 |               MakeNode(Dst, B, *I2, state); | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 2976 |             } | 
 | 2977 |             else | 
 | 2978 |               Dst.Add(*I2); | 
 | 2979 |              | 
| Ted Kremenek | 89063af | 2008-02-21 19:15:37 +0000 | [diff] [blame] | 2980 |             continue; | 
 | 2981 |           } | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2982 |            | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2983 |           if (Result.isUndef() && !LeftV.isUndef() && !RightV.isUndef()) { | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 2984 |              | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2985 |             // The operands were *not* undefined, but the result is undefined. | 
 | 2986 |             // This is a special node that should be flagged as an error. | 
| Ted Kremenek | 3c8d0c5 | 2008-02-25 18:42:54 +0000 | [diff] [blame] | 2987 |              | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2988 |             if (NodeTy* UndefNode = Builder->generateNode(B, state, *I2)) { | 
| Ted Kremenek | 8cc13ea | 2008-02-28 20:32:03 +0000 | [diff] [blame] | 2989 |               UndefNode->markAsSink();             | 
 | 2990 |               UndefResults.insert(UndefNode); | 
 | 2991 |             } | 
 | 2992 |              | 
 | 2993 |             continue; | 
 | 2994 |           } | 
 | 2995 |            | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 2996 |           // Otherwise, create a new node. | 
 | 2997 |            | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 2998 |           MakeNode(Dst, B, *I2, BindExpr(state, B, Result)); | 
| Ted Kremenek | e38718e | 2008-04-16 18:21:25 +0000 | [diff] [blame] | 2999 |           continue; | 
| Ted Kremenek | cf78b6a | 2008-02-06 22:50:25 +0000 | [diff] [blame] | 3000 |         } | 
| Ted Kremenek | ab2b8c5 | 2008-01-23 19:59:44 +0000 | [diff] [blame] | 3001 |       } | 
| Ted Kremenek | aa1c4e5 | 2008-02-21 18:02:17 +0000 | [diff] [blame] | 3002 |      | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3003 |       assert (B->isCompoundAssignmentOp()); | 
 | 3004 |  | 
| Ted Kremenek | cad2996 | 2009-02-07 00:52:24 +0000 | [diff] [blame] | 3005 |       switch (Op) { | 
 | 3006 |         default: | 
 | 3007 |           assert(0 && "Invalid opcode for compound assignment."); | 
 | 3008 |         case BinaryOperator::MulAssign: Op = BinaryOperator::Mul; break; | 
 | 3009 |         case BinaryOperator::DivAssign: Op = BinaryOperator::Div; break; | 
 | 3010 |         case BinaryOperator::RemAssign: Op = BinaryOperator::Rem; break; | 
 | 3011 |         case BinaryOperator::AddAssign: Op = BinaryOperator::Add; break; | 
 | 3012 |         case BinaryOperator::SubAssign: Op = BinaryOperator::Sub; break; | 
 | 3013 |         case BinaryOperator::ShlAssign: Op = BinaryOperator::Shl; break; | 
 | 3014 |         case BinaryOperator::ShrAssign: Op = BinaryOperator::Shr; break; | 
 | 3015 |         case BinaryOperator::AndAssign: Op = BinaryOperator::And; break; | 
 | 3016 |         case BinaryOperator::XorAssign: Op = BinaryOperator::Xor; break; | 
 | 3017 |         case BinaryOperator::OrAssign:  Op = BinaryOperator::Or;  break; | 
| Ted Kremenek | 934e3e9 | 2008-10-27 23:02:39 +0000 | [diff] [blame] | 3018 |       } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3019 |            | 
 | 3020 |       // Perform a load (the LHS).  This performs the checks for | 
 | 3021 |       // null dereferences, and so on. | 
 | 3022 |       NodeSet Tmp3; | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3023 |       SVal location = GetSVal(state, LHS); | 
 | 3024 |       EvalLoad(Tmp3, LHS, *I2, state, location); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3025 |        | 
 | 3026 |       for (NodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3; ++I3) { | 
 | 3027 |          | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3028 |         state = GetState(*I3); | 
 | 3029 |         SVal V = GetSVal(state, LHS); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3030 |  | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 3031 |         // Check for divide-by-zero. | 
 | 3032 |         if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem) | 
| Ted Kremenek | 062e2f9 | 2008-11-13 06:10:40 +0000 | [diff] [blame] | 3033 |             && RHS->getType()->isIntegerType() | 
 | 3034 |             && RHS->getType()->isScalarType()) { | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 3035 |            | 
 | 3036 |           // CheckDivideZero returns a new state where the denominator | 
 | 3037 |           // is assumed to be non-zero. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3038 |           state = CheckDivideZero(B, state, *I3, RightV); | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 3039 |            | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3040 |           if (!state) | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 3041 |             continue; | 
 | 3042 |         } | 
 | 3043 |          | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3044 |         // Propagate undefined values (left-side).           | 
 | 3045 |         if (V.isUndef()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3046 |           EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, V), location, V); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3047 |           continue; | 
 | 3048 |         } | 
 | 3049 |          | 
 | 3050 |         // Propagate unknown values (left and right-side). | 
 | 3051 |         if (RightV.isUnknown() || V.isUnknown()) { | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3052 |           EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, UnknownVal()), | 
 | 3053 |                     location, UnknownVal()); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3054 |           continue; | 
 | 3055 |         } | 
 | 3056 |  | 
 | 3057 |         // At this point: | 
 | 3058 |         // | 
 | 3059 |         //  The LHS is not Undef/Unknown. | 
 | 3060 |         //  The RHS is not Unknown. | 
 | 3061 |          | 
 | 3062 |         // Get the computation type. | 
| Eli Friedman | ab3a852 | 2009-03-28 01:22:36 +0000 | [diff] [blame] | 3063 |         QualType CTy = cast<CompoundAssignOperator>(B)->getComputationResultType(); | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3064 |         CTy = getContext().getCanonicalType(CTy); | 
| Eli Friedman | ab3a852 | 2009-03-28 01:22:36 +0000 | [diff] [blame] | 3065 |  | 
 | 3066 |         QualType CLHSTy = cast<CompoundAssignOperator>(B)->getComputationLHSType(); | 
 | 3067 |         CLHSTy = getContext().getCanonicalType(CTy); | 
 | 3068 |  | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3069 |         QualType LTy = getContext().getCanonicalType(LHS->getType()); | 
 | 3070 |         QualType RTy = getContext().getCanonicalType(RHS->getType()); | 
| Eli Friedman | ab3a852 | 2009-03-28 01:22:36 +0000 | [diff] [blame] | 3071 |  | 
 | 3072 |         // Promote LHS. | 
 | 3073 |         V = EvalCast(V, CLHSTy); | 
 | 3074 |  | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3075 |         // Evaluate operands and promote to result type.                     | 
| Ted Kremenek | c13b6e2 | 2008-10-20 23:40:25 +0000 | [diff] [blame] | 3076 |         if (RightV.isUndef()) {             | 
| Ted Kremenek | 82bae3f | 2008-09-20 01:50:34 +0000 | [diff] [blame] | 3077 |           // Propagate undefined values (right-side).           | 
| Ted Kremenek | e121da4 | 2009-03-05 03:42:31 +0000 | [diff] [blame] | 3078 |           EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, RightV), location, | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3079 |                     RightV); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3080 |           continue; | 
 | 3081 |         } | 
 | 3082 |        | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3083 |         // Compute the result of the operation.       | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 3084 |         SVal Result = EvalCast(EvalBinOp(state, Op, V, RightV, CTy),  | 
 | 3085 |                                B->getType()); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3086 |            | 
 | 3087 |         if (Result.isUndef()) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3088 |           // The operands were not undefined, but the result is undefined. | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3089 |           if (NodeTy* UndefNode = Builder->generateNode(B, state, *I3)) { | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3090 |             UndefNode->markAsSink();             | 
 | 3091 |             UndefResults.insert(UndefNode); | 
 | 3092 |           } | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3093 |           continue; | 
 | 3094 |         } | 
| Ted Kremenek | 9ff267d | 2008-10-20 23:13:25 +0000 | [diff] [blame] | 3095 |  | 
 | 3096 |         // EXPERIMENTAL: "Conjured" symbols. | 
 | 3097 |         // FIXME: Handle structs. | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3098 |          | 
 | 3099 |         SVal LHSVal; | 
 | 3100 |          | 
| Ted Kremenek | 276c6ac | 2009-03-11 02:24:48 +0000 | [diff] [blame] | 3101 |         if ((Result.isUnknown() ||  | 
 | 3102 |              !getConstraintManager().canReasonAbout(Result)) | 
 | 3103 |             && (Loc::IsLocType(CTy)  | 
 | 3104 |                 || (CTy->isScalarType() && CTy->isIntegerType()))) { | 
| Ted Kremenek | 0944ccc | 2008-10-21 19:49:01 +0000 | [diff] [blame] | 3105 |            | 
| Ted Kremenek | 9ff267d | 2008-10-20 23:13:25 +0000 | [diff] [blame] | 3106 |           unsigned Count = Builder->getCurrentBlockCount(); | 
| Ted Kremenek | 9ff267d | 2008-10-20 23:13:25 +0000 | [diff] [blame] | 3107 |            | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3108 |           // The symbolic value is actually for the type of the left-hand side | 
 | 3109 |           // expression, not the computation type, as this is the value the | 
 | 3110 |           // LValue on the LHS will bind to. | 
| Ted Kremenek | 8d7f548 | 2009-04-09 22:22:44 +0000 | [diff] [blame] | 3111 |           LHSVal = ValMgr.getConjuredSymbolVal(B->getRHS(), LTy, Count); | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3112 |            | 
| Zhongxing Xu | 1c0c233 | 2008-11-23 05:52:28 +0000 | [diff] [blame] | 3113 |           // However, we need to convert the symbol to the computation type. | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3114 |           Result = (LTy == CTy) ? LHSVal : EvalCast(LHSVal,CTy); | 
| Ted Kremenek | 9ff267d | 2008-10-20 23:13:25 +0000 | [diff] [blame] | 3115 |         } | 
| Ted Kremenek | 60595da | 2008-11-15 04:01:56 +0000 | [diff] [blame] | 3116 |         else { | 
 | 3117 |           // The left-hand side may bind to a different value then the | 
 | 3118 |           // computation type. | 
 | 3119 |           LHSVal = (LTy == CTy) ? Result : EvalCast(Result,LTy); | 
 | 3120 |         } | 
 | 3121 |            | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3122 |         EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, Result), location, | 
 | 3123 |                   LHSVal); | 
| Ted Kremenek | 1b8bd4d | 2008-04-29 21:04:26 +0000 | [diff] [blame] | 3124 |       } | 
| Ted Kremenek | cb448ca | 2008-01-16 00:53:15 +0000 | [diff] [blame] | 3125 |     } | 
| Ted Kremenek | d27f816 | 2008-01-15 23:55:06 +0000 | [diff] [blame] | 3126 |   } | 
| Ted Kremenek | d27f816 | 2008-01-15 23:55:06 +0000 | [diff] [blame] | 3127 | } | 
| Ted Kremenek | ee98546 | 2008-01-16 18:18:48 +0000 | [diff] [blame] | 3128 |  | 
 | 3129 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 3130 | // Transfer-function Helpers. | 
 | 3131 | //===----------------------------------------------------------------------===// | 
 | 3132 |  | 
| Ted Kremenek | 4adc81e | 2008-08-13 04:27:00 +0000 | [diff] [blame] | 3133 | void GRExprEngine::EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex, | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 3134 |                              BinaryOperator::Opcode Op, | 
| Zhongxing Xu | 1c96b24 | 2008-10-17 05:57:07 +0000 | [diff] [blame] | 3135 |                              NonLoc L, NonLoc R, | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 3136 |                              ExplodedNode<GRState>* Pred, QualType T) { | 
| Ted Kremenek | 6297a8e | 2008-07-18 05:53:58 +0000 | [diff] [blame] | 3137 |  | 
| Ted Kremenek | 4adc81e | 2008-08-13 04:27:00 +0000 | [diff] [blame] | 3138 |   GRStateSet OStates; | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 3139 |   EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R, T); | 
| Ted Kremenek | 6297a8e | 2008-07-18 05:53:58 +0000 | [diff] [blame] | 3140 |  | 
| Ted Kremenek | 4adc81e | 2008-08-13 04:27:00 +0000 | [diff] [blame] | 3141 |   for (GRStateSet::iterator I=OStates.begin(), E=OStates.end(); I!=E; ++I) | 
| Ted Kremenek | 6297a8e | 2008-07-18 05:53:58 +0000 | [diff] [blame] | 3142 |     MakeNode(Dst, Ex, Pred, *I); | 
 | 3143 | } | 
 | 3144 |  | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3145 | void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* state, | 
| Ted Kremenek | 6297a8e | 2008-07-18 05:53:58 +0000 | [diff] [blame] | 3146 |                              Expr* Ex, BinaryOperator::Opcode Op, | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 3147 |                              NonLoc L, NonLoc R, QualType T) { | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 3148 |    | 
| Ted Kremenek | a8538d9 | 2009-02-13 01:45:31 +0000 | [diff] [blame] | 3149 |   GRStateSet::AutoPopulate AP(OStates, state); | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 3150 |   if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R, T); | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 3151 | } | 
 | 3152 |  | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 3153 | SVal GRExprEngine::EvalBinOp(const GRState* state, BinaryOperator::Opcode Op,  | 
 | 3154 |                              SVal L, SVal R, QualType T) { | 
| Ted Kremenek | 1e2b1fc | 2009-01-30 19:27:39 +0000 | [diff] [blame] | 3155 |    | 
 | 3156 |   if (L.isUndef() || R.isUndef()) | 
 | 3157 |     return UndefinedVal(); | 
 | 3158 |    | 
 | 3159 |   if (L.isUnknown() || R.isUnknown()) | 
 | 3160 |     return UnknownVal(); | 
 | 3161 |    | 
 | 3162 |   if (isa<Loc>(L)) { | 
 | 3163 |     if (isa<Loc>(R)) | 
 | 3164 |       return getTF().EvalBinOp(*this, Op, cast<Loc>(L), cast<Loc>(R)); | 
 | 3165 |     else | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 3166 |       return getTF().EvalBinOp(*this, state, Op, cast<Loc>(L), cast<NonLoc>(R)); | 
| Ted Kremenek | 1e2b1fc | 2009-01-30 19:27:39 +0000 | [diff] [blame] | 3167 |   } | 
 | 3168 |    | 
 | 3169 |   if (isa<Loc>(R)) { | 
 | 3170 |     // Support pointer arithmetic where the increment/decrement operand | 
 | 3171 |     // is on the left and the pointer on the right. | 
 | 3172 |      | 
 | 3173 |     assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub); | 
 | 3174 |      | 
 | 3175 |     // Commute the operands. | 
| Zhongxing Xu | 262fd03 | 2009-05-20 09:00:16 +0000 | [diff] [blame] | 3176 |     return getTF().EvalBinOp(*this, state, Op, cast<Loc>(R), cast<NonLoc>(L)); | 
| Ted Kremenek | 1e2b1fc | 2009-01-30 19:27:39 +0000 | [diff] [blame] | 3177 |   } | 
 | 3178 |   else | 
 | 3179 |     return getTF().DetermEvalBinOpNN(*this, Op, cast<NonLoc>(L), | 
| Ted Kremenek | e0e4ebf | 2009-03-26 03:35:11 +0000 | [diff] [blame] | 3180 |                                      cast<NonLoc>(R), T); | 
| Ted Kremenek | 1e2b1fc | 2009-01-30 19:27:39 +0000 | [diff] [blame] | 3181 | } | 
 | 3182 |  | 
| Ted Kremenek | df7533b | 2008-07-17 21:27:31 +0000 | [diff] [blame] | 3183 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | e01c987 | 2008-02-14 22:36:46 +0000 | [diff] [blame] | 3184 | // Visualization. | 
| Ted Kremenek | ee98546 | 2008-01-16 18:18:48 +0000 | [diff] [blame] | 3185 | //===----------------------------------------------------------------------===// | 
 | 3186 |  | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3187 | #ifndef NDEBUG | 
| Ted Kremenek | 4d4dd85 | 2008-02-13 17:41:41 +0000 | [diff] [blame] | 3188 | static GRExprEngine* GraphPrintCheckerState; | 
| Ted Kremenek | e97ca06 | 2008-03-07 20:57:30 +0000 | [diff] [blame] | 3189 | static SourceManager* GraphPrintSourceManager; | 
| Ted Kremenek | 3b4f670 | 2008-01-30 23:24:39 +0000 | [diff] [blame] | 3190 |  | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3191 | namespace llvm { | 
 | 3192 | template<> | 
| Ted Kremenek | 4d4dd85 | 2008-02-13 17:41:41 +0000 | [diff] [blame] | 3193 | struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3194 |   public DefaultDOTGraphTraits { | 
| Ted Kremenek | 016f52f | 2008-02-08 21:10:02 +0000 | [diff] [blame] | 3195 |      | 
| Ted Kremenek | a3fadfc | 2008-02-14 22:54:53 +0000 | [diff] [blame] | 3196 |   static std::string getNodeAttributes(const GRExprEngine::NodeTy* N, void*) { | 
 | 3197 |      | 
 | 3198 |     if (GraphPrintCheckerState->isImplicitNullDeref(N) || | 
| Ted Kremenek | 9dca062 | 2008-02-19 00:22:37 +0000 | [diff] [blame] | 3199 |         GraphPrintCheckerState->isExplicitNullDeref(N) || | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 3200 |         GraphPrintCheckerState->isUndefDeref(N) || | 
 | 3201 |         GraphPrintCheckerState->isUndefStore(N) || | 
 | 3202 |         GraphPrintCheckerState->isUndefControlFlow(N) || | 
| Ted Kremenek | 4d839b4 | 2008-03-07 19:04:53 +0000 | [diff] [blame] | 3203 |         GraphPrintCheckerState->isExplicitBadDivide(N) || | 
 | 3204 |         GraphPrintCheckerState->isImplicitBadDivide(N) || | 
| Ted Kremenek | 5e03fcb | 2008-02-29 23:14:48 +0000 | [diff] [blame] | 3205 |         GraphPrintCheckerState->isUndefResult(N) || | 
| Ted Kremenek | 2ded35a | 2008-02-29 23:53:11 +0000 | [diff] [blame] | 3206 |         GraphPrintCheckerState->isBadCall(N) || | 
 | 3207 |         GraphPrintCheckerState->isUndefArg(N)) | 
| Ted Kremenek | a3fadfc | 2008-02-14 22:54:53 +0000 | [diff] [blame] | 3208 |       return "color=\"red\",style=\"filled\""; | 
 | 3209 |      | 
| Ted Kremenek | 8cc13ea | 2008-02-28 20:32:03 +0000 | [diff] [blame] | 3210 |     if (GraphPrintCheckerState->isNoReturnCall(N)) | 
 | 3211 |       return "color=\"blue\",style=\"filled\""; | 
 | 3212 |      | 
| Ted Kremenek | a3fadfc | 2008-02-14 22:54:53 +0000 | [diff] [blame] | 3213 |     return ""; | 
 | 3214 |   } | 
| Ted Kremenek | ed4de31 | 2008-02-06 03:56:15 +0000 | [diff] [blame] | 3215 |      | 
| Ted Kremenek | 4d4dd85 | 2008-02-13 17:41:41 +0000 | [diff] [blame] | 3216 |   static std::string getNodeLabel(const GRExprEngine::NodeTy* N, void*) { | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3217 |     std::ostringstream Out; | 
| Ted Kremenek | 803c9ed | 2008-01-23 22:30:44 +0000 | [diff] [blame] | 3218 |  | 
 | 3219 |     // Program Location. | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3220 |     ProgramPoint Loc = N->getLocation(); | 
 | 3221 |      | 
 | 3222 |     switch (Loc.getKind()) { | 
 | 3223 |       case ProgramPoint::BlockEntranceKind: | 
 | 3224 |         Out << "Block Entrance: B"  | 
 | 3225 |             << cast<BlockEntrance>(Loc).getBlock()->getBlockID(); | 
 | 3226 |         break; | 
 | 3227 |        | 
 | 3228 |       case ProgramPoint::BlockExitKind: | 
 | 3229 |         assert (false); | 
 | 3230 |         break; | 
 | 3231 |          | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3232 |       default: { | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 3233 |         if (isa<PostStmt>(Loc)) { | 
 | 3234 |           const PostStmt& L = cast<PostStmt>(Loc);         | 
 | 3235 |           Stmt* S = L.getStmt(); | 
 | 3236 |           SourceLocation SLoc = S->getLocStart(); | 
 | 3237 |  | 
 | 3238 |           Out << S->getStmtClassName() << ' ' << (void*) S << ' ';         | 
 | 3239 |           llvm::raw_os_ostream OutS(Out); | 
 | 3240 |           S->printPretty(OutS); | 
 | 3241 |           OutS.flush(); | 
 | 3242 |            | 
 | 3243 |           if (SLoc.isFileID()) {         | 
 | 3244 |             Out << "\\lline=" | 
| Chris Lattner | 7da5aea | 2009-02-04 00:55:58 +0000 | [diff] [blame] | 3245 |               << GraphPrintSourceManager->getInstantiationLineNumber(SLoc) | 
 | 3246 |               << " col=" | 
 | 3247 |               << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc) | 
 | 3248 |               << "\\l"; | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 3249 |           } | 
 | 3250 |            | 
| Ted Kremenek | 7090d54 | 2009-05-07 18:27:16 +0000 | [diff] [blame] | 3251 |           if (isa<PostLoad>(Loc)) | 
 | 3252 |             Out << "\\lPostLoad\\l;"; | 
 | 3253 |           else if (isa<PostStore>(Loc)) | 
 | 3254 |             Out << "\\lPostStore\\l"; | 
 | 3255 |           else if (isa<PostLValue>(Loc)) | 
 | 3256 |             Out << "\\lPostLValue\\l"; | 
 | 3257 |           else if (isa<PostLocationChecksSucceed>(Loc)) | 
 | 3258 |             Out << "\\lPostLocationChecksSucceed\\l"; | 
 | 3259 |           else if (isa<PostNullCheckFailed>(Loc)) | 
 | 3260 |             Out << "\\lPostNullCheckFailed\\l"; | 
 | 3261 |            | 
| Ted Kremenek | 8c35475 | 2008-12-16 22:02:27 +0000 | [diff] [blame] | 3262 |           if (GraphPrintCheckerState->isImplicitNullDeref(N)) | 
 | 3263 |             Out << "\\|Implicit-Null Dereference.\\l"; | 
 | 3264 |           else if (GraphPrintCheckerState->isExplicitNullDeref(N)) | 
 | 3265 |             Out << "\\|Explicit-Null Dereference.\\l"; | 
 | 3266 |           else if (GraphPrintCheckerState->isUndefDeref(N)) | 
 | 3267 |             Out << "\\|Dereference of undefialied value.\\l"; | 
 | 3268 |           else if (GraphPrintCheckerState->isUndefStore(N)) | 
 | 3269 |             Out << "\\|Store to Undefined Loc."; | 
 | 3270 |           else if (GraphPrintCheckerState->isExplicitBadDivide(N)) | 
 | 3271 |             Out << "\\|Explicit divide-by zero or undefined value."; | 
 | 3272 |           else if (GraphPrintCheckerState->isImplicitBadDivide(N)) | 
 | 3273 |             Out << "\\|Implicit divide-by zero or undefined value."; | 
 | 3274 |           else if (GraphPrintCheckerState->isUndefResult(N)) | 
 | 3275 |             Out << "\\|Result of operation is undefined."; | 
 | 3276 |           else if (GraphPrintCheckerState->isNoReturnCall(N)) | 
 | 3277 |             Out << "\\|Call to function marked \"noreturn\"."; | 
 | 3278 |           else if (GraphPrintCheckerState->isBadCall(N)) | 
 | 3279 |             Out << "\\|Call to NULL/Undefined."; | 
 | 3280 |           else if (GraphPrintCheckerState->isUndefArg(N)) | 
 | 3281 |             Out << "\\|Argument in call is undefined"; | 
 | 3282 |            | 
 | 3283 |           break; | 
 | 3284 |         } | 
 | 3285 |  | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3286 |         const BlockEdge& E = cast<BlockEdge>(Loc); | 
 | 3287 |         Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B" | 
 | 3288 |             << E.getDst()->getBlockID()  << ')'; | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 3289 |          | 
 | 3290 |         if (Stmt* T = E.getSrc()->getTerminator()) { | 
| Ted Kremenek | e97ca06 | 2008-03-07 20:57:30 +0000 | [diff] [blame] | 3291 |            | 
 | 3292 |           SourceLocation SLoc = T->getLocStart(); | 
 | 3293 |           | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 3294 |           Out << "\\|Terminator: "; | 
| Ted Kremenek | e97ca06 | 2008-03-07 20:57:30 +0000 | [diff] [blame] | 3295 |            | 
| Ted Kremenek | a95d375 | 2008-09-13 05:16:45 +0000 | [diff] [blame] | 3296 |           llvm::raw_os_ostream OutS(Out); | 
 | 3297 |           E.getSrc()->printTerminator(OutS); | 
 | 3298 |           OutS.flush(); | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 3299 |            | 
| Ted Kremenek | 9b5551d | 2008-03-09 03:30:59 +0000 | [diff] [blame] | 3300 |           if (SLoc.isFileID()) { | 
 | 3301 |             Out << "\\lline=" | 
| Chris Lattner | 7da5aea | 2009-02-04 00:55:58 +0000 | [diff] [blame] | 3302 |               << GraphPrintSourceManager->getInstantiationLineNumber(SLoc) | 
 | 3303 |               << " col=" | 
 | 3304 |               << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc); | 
| Ted Kremenek | 9b5551d | 2008-03-09 03:30:59 +0000 | [diff] [blame] | 3305 |           } | 
| Ted Kremenek | e97ca06 | 2008-03-07 20:57:30 +0000 | [diff] [blame] | 3306 |              | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 3307 |           if (isa<SwitchStmt>(T)) { | 
 | 3308 |             Stmt* Label = E.getDst()->getLabel(); | 
 | 3309 |              | 
 | 3310 |             if (Label) {                         | 
 | 3311 |               if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) { | 
 | 3312 |                 Out << "\\lcase "; | 
| Ted Kremenek | a95d375 | 2008-09-13 05:16:45 +0000 | [diff] [blame] | 3313 |                 llvm::raw_os_ostream OutS(Out); | 
 | 3314 |                 C->getLHS()->printPretty(OutS); | 
 | 3315 |                 OutS.flush(); | 
 | 3316 |                | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 3317 |                 if (Stmt* RHS = C->getRHS()) { | 
 | 3318 |                   Out << " .. "; | 
| Ted Kremenek | a95d375 | 2008-09-13 05:16:45 +0000 | [diff] [blame] | 3319 |                   RHS->printPretty(OutS); | 
 | 3320 |                   OutS.flush(); | 
| Ted Kremenek | daeb9a7 | 2008-02-13 23:08:21 +0000 | [diff] [blame] | 3321 |                 } | 
 | 3322 |                  | 
 | 3323 |                 Out << ":"; | 
 | 3324 |               } | 
 | 3325 |               else { | 
 | 3326 |                 assert (isa<DefaultStmt>(Label)); | 
 | 3327 |                 Out << "\\ldefault:"; | 
 | 3328 |               } | 
 | 3329 |             } | 
 | 3330 |             else  | 
 | 3331 |               Out << "\\l(implicit) default:"; | 
 | 3332 |           } | 
 | 3333 |           else if (isa<IndirectGotoStmt>(T)) { | 
| Ted Kremenek | b38911f | 2008-01-30 23:03:39 +0000 | [diff] [blame] | 3334 |             // FIXME | 
 | 3335 |           } | 
 | 3336 |           else { | 
 | 3337 |             Out << "\\lCondition: "; | 
 | 3338 |             if (*E.getSrc()->succ_begin() == E.getDst()) | 
 | 3339 |               Out << "true"; | 
 | 3340 |             else | 
 | 3341 |               Out << "false";                         | 
 | 3342 |           } | 
 | 3343 |            | 
 | 3344 |           Out << "\\l"; | 
 | 3345 |         } | 
| Ted Kremenek | 3b4f670 | 2008-01-30 23:24:39 +0000 | [diff] [blame] | 3346 |          | 
| Ted Kremenek | 4a4e524 | 2008-02-28 09:25:22 +0000 | [diff] [blame] | 3347 |         if (GraphPrintCheckerState->isUndefControlFlow(N)) { | 
 | 3348 |           Out << "\\|Control-flow based on\\lUndefined value.\\l"; | 
| Ted Kremenek | 3b4f670 | 2008-01-30 23:24:39 +0000 | [diff] [blame] | 3349 |         } | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3350 |       } | 
 | 3351 |     } | 
 | 3352 |      | 
| Ted Kremenek | aed9b6a | 2008-02-28 10:21:43 +0000 | [diff] [blame] | 3353 |     Out << "\\|StateID: " << (void*) N->getState() << "\\|"; | 
| Ted Kremenek | 016f52f | 2008-02-08 21:10:02 +0000 | [diff] [blame] | 3354 |  | 
| Ted Kremenek | b65be70 | 2009-06-18 01:23:53 +0000 | [diff] [blame^] | 3355 |     const GRState *state = N->getState(); | 
 | 3356 |     state->printDOT(Out); | 
| Ted Kremenek | 803c9ed | 2008-01-23 22:30:44 +0000 | [diff] [blame] | 3357 |        | 
| Ted Kremenek | 803c9ed | 2008-01-23 22:30:44 +0000 | [diff] [blame] | 3358 |     Out << "\\l"; | 
| Ted Kremenek | aa66a32 | 2008-01-16 21:46:15 +0000 | [diff] [blame] | 3359 |     return Out.str(); | 
 | 3360 |   } | 
 | 3361 | }; | 
 | 3362 | } // end llvm namespace     | 
 | 3363 | #endif | 
 | 3364 |  | 
| Ted Kremenek | ffe0f43 | 2008-03-07 22:58:01 +0000 | [diff] [blame] | 3365 | #ifndef NDEBUG | 
| Ted Kremenek | 7ec07fd | 2008-03-12 17:18:20 +0000 | [diff] [blame] | 3366 | template <typename ITERATOR> | 
 | 3367 | GRExprEngine::NodeTy* GetGraphNode(ITERATOR I) { return *I; } | 
 | 3368 |  | 
 | 3369 | template <> | 
 | 3370 | GRExprEngine::NodeTy* | 
 | 3371 | GetGraphNode<llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator> | 
 | 3372 |   (llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator I) { | 
 | 3373 |   return I->first; | 
 | 3374 | } | 
| Ted Kremenek | ffe0f43 | 2008-03-07 22:58:01 +0000 | [diff] [blame] | 3375 | #endif | 
 | 3376 |  | 
 | 3377 | void GRExprEngine::ViewGraph(bool trim) { | 
| Ted Kremenek | 493d7a2 | 2008-03-11 18:25:33 +0000 | [diff] [blame] | 3378 | #ifndef NDEBUG   | 
| Ted Kremenek | ffe0f43 | 2008-03-07 22:58:01 +0000 | [diff] [blame] | 3379 |   if (trim) { | 
| Ted Kremenek | cb61292 | 2008-04-18 19:23:43 +0000 | [diff] [blame] | 3380 |     std::vector<NodeTy*> Src; | 
| Ted Kremenek | 940abcc | 2009-03-11 01:41:22 +0000 | [diff] [blame] | 3381 |  | 
 | 3382 |     // Flush any outstanding reports to make sure we cover all the nodes. | 
 | 3383 |     // This does not cause them to get displayed. | 
 | 3384 |     for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) | 
 | 3385 |       const_cast<BugType*>(*I)->FlushReports(BR); | 
 | 3386 |  | 
 | 3387 |     // Iterate through the reports and get their nodes. | 
 | 3388 |     for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) { | 
 | 3389 |       for (BugType::const_iterator I2=(*I)->begin(), E2=(*I)->end(); I2!=E2; ++I2) {         | 
 | 3390 |         const BugReportEquivClass& EQ = *I2; | 
 | 3391 |         const BugReport &R = **EQ.begin(); | 
 | 3392 |         NodeTy *N = const_cast<NodeTy*>(R.getEndNode()); | 
 | 3393 |         if (N) Src.push_back(N); | 
 | 3394 |       } | 
 | 3395 |     } | 
| Ted Kremenek | cb61292 | 2008-04-18 19:23:43 +0000 | [diff] [blame] | 3396 |      | 
| Ted Kremenek | 7ec07fd | 2008-03-12 17:18:20 +0000 | [diff] [blame] | 3397 |     ViewGraph(&Src[0], &Src[0]+Src.size()); | 
| Ted Kremenek | ffe0f43 | 2008-03-07 22:58:01 +0000 | [diff] [blame] | 3398 |   } | 
| Ted Kremenek | 493d7a2 | 2008-03-11 18:25:33 +0000 | [diff] [blame] | 3399 |   else { | 
 | 3400 |     GraphPrintCheckerState = this; | 
 | 3401 |     GraphPrintSourceManager = &getContext().getSourceManager(); | 
| Ted Kremenek | ae6814e | 2008-08-13 21:24:49 +0000 | [diff] [blame] | 3402 |  | 
| Ted Kremenek | ffe0f43 | 2008-03-07 22:58:01 +0000 | [diff] [blame] | 3403 |     llvm::ViewGraph(*G.roots_begin(), "GRExprEngine"); | 
| Ted Kremenek | 493d7a2 | 2008-03-11 18:25:33 +0000 | [diff] [blame] | 3404 |      | 
 | 3405 |     GraphPrintCheckerState = NULL; | 
 | 3406 |     GraphPrintSourceManager = NULL; | 
 | 3407 |   } | 
 | 3408 | #endif | 
 | 3409 | } | 
 | 3410 |  | 
 | 3411 | void GRExprEngine::ViewGraph(NodeTy** Beg, NodeTy** End) { | 
 | 3412 | #ifndef NDEBUG | 
 | 3413 |   GraphPrintCheckerState = this; | 
 | 3414 |   GraphPrintSourceManager = &getContext().getSourceManager(); | 
| Ted Kremenek | 1c72ef0 | 2008-08-16 00:49:49 +0000 | [diff] [blame] | 3415 |      | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 3416 |   std::auto_ptr<GRExprEngine::GraphTy> TrimmedG(G.Trim(Beg, End).first); | 
| Ted Kremenek | 493d7a2 | 2008-03-11 18:25:33 +0000 | [diff] [blame] | 3417 |  | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 3418 |   if (!TrimmedG.get()) | 
| Ted Kremenek | 493d7a2 | 2008-03-11 18:25:33 +0000 | [diff] [blame] | 3419 |     llvm::cerr << "warning: Trimmed ExplodedGraph is empty.\n"; | 
| Ted Kremenek | cf118d4 | 2009-02-04 23:49:09 +0000 | [diff] [blame] | 3420 |   else | 
| Ted Kremenek | 493d7a2 | 2008-03-11 18:25:33 +0000 | [diff] [blame] | 3421 |     llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedGRExprEngine");     | 
| Ted Kremenek | ffe0f43 | 2008-03-07 22:58:01 +0000 | [diff] [blame] | 3422 |    | 
| Ted Kremenek | 3b4f670 | 2008-01-30 23:24:39 +0000 | [diff] [blame] | 3423 |   GraphPrintCheckerState = NULL; | 
| Ted Kremenek | e97ca06 | 2008-03-07 20:57:30 +0000 | [diff] [blame] | 3424 |   GraphPrintSourceManager = NULL; | 
| Ted Kremenek | e01c987 | 2008-02-14 22:36:46 +0000 | [diff] [blame] | 3425 | #endif | 
| Ted Kremenek | ee98546 | 2008-01-16 18:18:48 +0000 | [diff] [blame] | 3426 | } |