bool BlinkGCPluginConsumer::HasNonEmptyFinalizer(RecordInfo* info) { CXXDestructorDecl* dtor = info->record()->getDestructor(); if (dtor && dtor->isUserProvided()) { if (!dtor->hasBody() || !EmptyStmtVisitor::isEmpty(dtor->getBody())) return true; } for (RecordInfo::Bases::iterator it = info->GetBases().begin(); it != info->GetBases().end(); ++it) { if (HasNonEmptyFinalizer(it->second.info())) return true; } for (RecordInfo::Fields::iterator it = info->GetFields().begin(); it != info->GetFields().end(); ++it) { if (it->second.edge()->NeedsFinalization()) return true; } return false; }
void VirtualCallsFromCTOR::VisitDecl(Decl *decl) { CXXConstructorDecl *ctorDecl = dyn_cast<CXXConstructorDecl>(decl); CXXDestructorDecl *dtorDecl = dyn_cast<CXXDestructorDecl>(decl); if (ctorDecl == nullptr && dtorDecl == nullptr) return; Stmt *ctorOrDtorBody = ctorDecl ? ctorDecl->getBody() : dtorDecl->getBody(); if (ctorOrDtorBody == nullptr) return; CXXRecordDecl *classDecl = ctorDecl ? ctorDecl->getParent() : dtorDecl->getParent(); std::vector<Stmt*> processedStmts; SourceLocation loc = containsVirtualCall(classDecl, ctorOrDtorBody, processedStmts); if (loc.isValid()) { if (ctorDecl != nullptr) { emitWarning(decl->getLocStart(), "Calling pure virtual function in CTOR"); } else { emitWarning(decl->getLocStart(), "Calling pure virtual function in DTOR"); } emitWarning(loc, "Called here"); } }