ExprEngineCXX.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. //===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the C++ expression evaluation engine.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  14. #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
  17. #include "clang/AST/DeclCXX.h"
  18. using namespace clang;
  19. using namespace ento;
  20. namespace {
  21. class CallExprWLItem {
  22. public:
  23. CallExpr::const_arg_iterator I;
  24. ExplodedNode *N;
  25. CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
  26. : I(i), N(n) {}
  27. };
  28. }
  29. void ExprEngine::evalArguments(ConstExprIterator AI, ConstExprIterator AE,
  30. const FunctionProtoType *FnType,
  31. ExplodedNode *Pred, ExplodedNodeSet &Dst,
  32. bool FstArgAsLValue) {
  33. SmallVector<CallExprWLItem, 20> WorkList;
  34. WorkList.reserve(AE - AI);
  35. WorkList.push_back(CallExprWLItem(AI, Pred));
  36. while (!WorkList.empty()) {
  37. CallExprWLItem Item = WorkList.back();
  38. WorkList.pop_back();
  39. if (Item.I == AE) {
  40. Dst.insert(Item.N);
  41. continue;
  42. }
  43. // Evaluate the argument.
  44. ExplodedNodeSet Tmp;
  45. if (FstArgAsLValue) {
  46. FstArgAsLValue = false;
  47. }
  48. Visit(*Item.I, Item.N, Tmp);
  49. ++(Item.I);
  50. for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
  51. WorkList.push_back(CallExprWLItem(Item.I, *NI));
  52. }
  53. }
  54. void ExprEngine::evalCallee(const CallExpr *callExpr,
  55. const ExplodedNodeSet &src,
  56. ExplodedNodeSet &dest) {
  57. const Expr *callee = 0;
  58. switch (callExpr->getStmtClass()) {
  59. case Stmt::CXXMemberCallExprClass: {
  60. // Evaluate the implicit object argument that is the recipient of the
  61. // call.
  62. callee = cast<CXXMemberCallExpr>(callExpr)->getImplicitObjectArgument();
  63. // FIXME: handle member pointers.
  64. if (!callee)
  65. return;
  66. break;
  67. }
  68. default: {
  69. callee = callExpr->getCallee()->IgnoreParens();
  70. break;
  71. }
  72. }
  73. for (ExplodedNodeSet::iterator i = src.begin(), e = src.end(); i != e; ++i)
  74. Visit(callee, *i, dest);
  75. }
  76. const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXRecordDecl *D,
  77. const StackFrameContext *SFC) {
  78. const Type *T = D->getTypeForDecl();
  79. QualType PT = getContext().getPointerType(QualType(T, 0));
  80. return svalBuilder.getRegionManager().getCXXThisRegion(PT, SFC);
  81. }
  82. const CXXThisRegion *ExprEngine::getCXXThisRegion(const CXXMethodDecl *decl,
  83. const StackFrameContext *frameCtx) {
  84. return svalBuilder.getRegionManager().
  85. getCXXThisRegion(decl->getThisType(getContext()), frameCtx);
  86. }
  87. void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
  88. ExplodedNode *Pred,
  89. ExplodedNodeSet &Dst) {
  90. StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
  91. const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
  92. const ProgramState *state = Pred->getState();
  93. // Bind the temporary object to the value of the expression. Then bind
  94. // the expression to the location of the object.
  95. SVal V = state->getSVal(tempExpr);
  96. const MemRegion *R =
  97. svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
  98. Pred->getLocationContext());
  99. state = state->bindLoc(loc::MemRegionVal(R), V);
  100. Bldr.generateNode(ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
  101. }
  102. void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
  103. const MemRegion *Dest,
  104. ExplodedNode *Pred,
  105. ExplodedNodeSet &destNodes) {
  106. const CXXConstructorDecl *CD = E->getConstructor();
  107. assert(CD);
  108. #if 0
  109. if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
  110. // FIXME: invalidate the object.
  111. return;
  112. #endif
  113. // Evaluate other arguments.
  114. ExplodedNodeSet argsEvaluated;
  115. const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
  116. evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
  117. #if 0
  118. // Is the constructor elidable?
  119. if (E->isElidable()) {
  120. VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
  121. // FIXME: this is here to force propagation if VisitAggExpr doesn't
  122. if (destNodes.empty())
  123. destNodes.Add(Pred);
  124. return;
  125. }
  126. #endif
  127. // Perform the previsit of the constructor.
  128. ExplodedNodeSet destPreVisit;
  129. getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
  130. *this);
  131. // Evaluate the constructor. Currently we don't now allow checker-specific
  132. // implementations of specific constructors (as we do with ordinary
  133. // function calls. We can re-evaluate this in the future.
  134. #if 0
  135. // Inlining currently isn't fully implemented.
  136. if (AMgr.shouldInlineCall()) {
  137. if (!Dest)
  138. Dest =
  139. svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
  140. Pred->getLocationContext());
  141. // The callee stack frame context used to create the 'this'
  142. // parameter region.
  143. const StackFrameContext *SFC =
  144. AMgr.getStackFrame(CD, Pred->getLocationContext(),
  145. E, currentBuilderContext->getBlock(),
  146. currentStmtIdx);
  147. // Create the 'this' region.
  148. const CXXThisRegion *ThisR =
  149. getCXXThisRegion(E->getConstructor()->getParent(), SFC);
  150. CallEnter Loc(E, SFC, Pred->getLocationContext());
  151. StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext);
  152. for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
  153. NE = argsEvaluated.end(); NI != NE; ++NI) {
  154. const ProgramState *state = (*NI)->getState();
  155. // Setup 'this' region, so that the ctor is evaluated on the object pointed
  156. // by 'Dest'.
  157. state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
  158. Bldr.generateNode(Loc, *NI, state);
  159. }
  160. }
  161. #endif
  162. // Default semantics: invalidate all regions passed as arguments.
  163. ExplodedNodeSet destCall;
  164. {
  165. StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext);
  166. for (ExplodedNodeSet::iterator
  167. i = destPreVisit.begin(), e = destPreVisit.end();
  168. i != e; ++i)
  169. {
  170. ExplodedNode *Pred = *i;
  171. const LocationContext *LC = Pred->getLocationContext();
  172. const ProgramState *state = Pred->getState();
  173. state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
  174. Bldr.generateNode(E, Pred, state);
  175. }
  176. }
  177. // Do the post visit.
  178. getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
  179. }
  180. void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
  181. const MemRegion *Dest,
  182. const Stmt *S,
  183. ExplodedNode *Pred,
  184. ExplodedNodeSet &Dst) {
  185. StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
  186. if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
  187. return;
  188. // Create the context for 'this' region.
  189. const StackFrameContext *SFC =
  190. AnalysisDeclContexts.getContext(DD)->
  191. getStackFrame(Pred->getLocationContext(), S,
  192. currentBuilderContext->getBlock(), currentStmtIdx);
  193. const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
  194. CallEnter PP(S, SFC, Pred->getLocationContext());
  195. const ProgramState *state = Pred->getState();
  196. state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
  197. Bldr.generateNode(PP, Pred, state);
  198. }
  199. void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
  200. ExplodedNodeSet &Dst) {
  201. StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
  202. unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
  203. DefinedOrUnknownSVal symVal =
  204. svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount);
  205. const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
  206. QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
  207. const ElementRegion *EleReg =
  208. getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
  209. if (CNE->isArray()) {
  210. // FIXME: allocating an array requires simulating the constructors.
  211. // For now, just return a symbolicated region.
  212. const ProgramState *state = Pred->getState();
  213. state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
  214. Bldr.generateNode(CNE, Pred, state);
  215. return;
  216. }
  217. // Evaluate constructor arguments.
  218. const FunctionProtoType *FnType = NULL;
  219. const CXXConstructorDecl *CD = CNE->getConstructor();
  220. if (CD)
  221. FnType = CD->getType()->getAs<FunctionProtoType>();
  222. ExplodedNodeSet argsEvaluated;
  223. Bldr.takeNodes(Pred);
  224. evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
  225. FnType, Pred, argsEvaluated);
  226. Bldr.addNodes(argsEvaluated);
  227. // Initialize the object region and bind the 'new' expression.
  228. for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
  229. E = argsEvaluated.end(); I != E; ++I) {
  230. const ProgramState *state = (*I)->getState();
  231. // Accumulate list of regions that are invalidated.
  232. // FIXME: Eventually we should unify the logic for constructor
  233. // processing in one place.
  234. SmallVector<const MemRegion*, 10> regionsToInvalidate;
  235. for (CXXNewExpr::const_arg_iterator
  236. ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
  237. ai != ae; ++ai)
  238. {
  239. SVal val = state->getSVal(*ai);
  240. if (const MemRegion *region = val.getAsRegion())
  241. regionsToInvalidate.push_back(region);
  242. }
  243. if (ObjTy->isRecordType()) {
  244. regionsToInvalidate.push_back(EleReg);
  245. // Invalidate the regions.
  246. state = state->invalidateRegions(regionsToInvalidate,
  247. CNE, blockCount, 0,
  248. /* invalidateGlobals = */ true);
  249. } else {
  250. // Invalidate the regions.
  251. state = state->invalidateRegions(regionsToInvalidate,
  252. CNE, blockCount, 0,
  253. /* invalidateGlobals = */ true);
  254. if (CNE->hasInitializer()) {
  255. SVal V = state->getSVal(*CNE->constructor_arg_begin());
  256. state = state->bindLoc(loc::MemRegionVal(EleReg), V);
  257. } else {
  258. // Explicitly set to undefined, because currently we retrieve symbolic
  259. // value from symbolic region.
  260. state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
  261. }
  262. }
  263. state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
  264. Bldr.generateNode(CNE, *I, state);
  265. }
  266. }
  267. void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
  268. ExplodedNode *Pred, ExplodedNodeSet &Dst) {
  269. // Should do more checking.
  270. ExplodedNodeSet Argevaluated;
  271. Visit(CDE->getArgument(), Pred, Argevaluated);
  272. StmtNodeBuilder Bldr(Argevaluated, Dst, *currentBuilderContext);
  273. for (ExplodedNodeSet::iterator I = Argevaluated.begin(),
  274. E = Argevaluated.end(); I != E; ++I) {
  275. const ProgramState *state = (*I)->getState();
  276. Bldr.generateNode(CDE, *I, state);
  277. }
  278. }
  279. void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
  280. ExplodedNodeSet &Dst) {
  281. StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
  282. // Get the this object region from StoreManager.
  283. const MemRegion *R =
  284. svalBuilder.getRegionManager().getCXXThisRegion(
  285. getContext().getCanonicalType(TE->getType()),
  286. Pred->getLocationContext());
  287. const ProgramState *state = Pred->getState();
  288. SVal V = state->getSVal(loc::MemRegionVal(R));
  289. Bldr.generateNode(TE, Pred, state->BindExpr(TE, V));
  290. }