diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-08-15 00:51:56 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-08-15 00:51:56 +0000 |
commit | 0ad36baedc516005cb6ea97d96327517ebfe5138 (patch) | |
tree | c7150701fd2fef0d7ba8ae85d64fe1b9115f06de /lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp | |
parent | 2f834a5f5a4df86a70958f418e9773cd7a0aea42 (diff) |
[analyzer] Correctly devirtualize virtual method calls in destructors.
C++11 [class.cdtor]p4: When a virtual function is called directly or
indirectly from a constructor or from a destructor, including during
the construction or destruction of the class’s non-static data members,
and the object to which the call applies is the object under
construction or destruction, the function called is the final overrider
in the constructor's or destructor's class and not one overriding it in
a more-derived class.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161915 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index fea57337bb..036686e964 100644 --- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -25,7 +25,8 @@ using namespace ento; namespace { class DynamicTypePropagation: - public Checker< check::PostCall, + public Checker< check::PreCall, + check::PostCall, check::PostStmt<ImplicitCastExpr> > { const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, CheckerContext &C) const; @@ -34,11 +35,45 @@ class DynamicTypePropagation: const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE, CheckerContext &C) const; public: + void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPostCall(const CallEvent &Call, CheckerContext &C) const; void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const; }; } +void DynamicTypePropagation::checkPreCall(const CallEvent &Call, + CheckerContext &C) const { + if (const CXXDestructorCall *Dtor = dyn_cast<CXXDestructorCall>(&Call)) { + // C++11 [class.cdtor]p4: When a virtual function is called directly or + // indirectly from a constructor or from a destructor, including during + // the construction or destruction of the class’s non-static data members, + // and the object to which the call applies is the object under + // construction or destruction, the function called is the final overrider + // in the constructor's or destructor's class and not one overriding it in + // a more-derived class. + // FIXME: We don't support this behavior yet for constructors. + + const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion(); + if (!Target) + return; + + // FIXME: getRuntimeDefinition() can be expensive. It would be better to do + // this when we are entering the stack frame for the destructor. + const Decl *D = Dtor->getRuntimeDefinition().getDecl(); + if (!D) + return; + + const CXXRecordDecl *Class = cast<CXXDestructorDecl>(D)->getParent(); + + ASTContext &Ctx = C.getASTContext(); + QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class)); + + ProgramStateRef State = C.getState(); + State = State->setDynamicTypeInfo(Target, Ty, /*CanBeSubclass=*/false); + C.addTransition(State); + } +} + void DynamicTypePropagation::checkPostCall(const CallEvent &Call, CheckerContext &C) const { // We can obtain perfect type info for return values from some calls. |