void MutableMemberChecker::checkASTDecl(const clang::FieldDecl *D, clang::ento::AnalysisManager &Mgr, clang::ento::BugReporter &BR) const { if ( D->hasAttr<CMSThreadGuardAttr>() || D->hasAttr<CMSThreadSafeAttr>()) return; if ( D->isMutable() && D->getDeclContext()->isRecord() ) { clang::QualType t = D->getType(); clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(D, BR.getSourceManager()); if ( ! m_exception.reportMutableMember( t, DLoc, BR ) ) return; if ( support::isSafeClassName( t.getCanonicalType().getAsString() ) ) return; if ( ! support::isDataClass( D->getParent()->getQualifiedNameAsString() ) ) return; std::string buf; llvm::raw_string_ostream os(buf); os << "Mutable member'" <<t.getAsString()<<" "<<*D << "' in class '"<<D->getParent()->getQualifiedNameAsString()<<"', might be thread-unsafe when accessing via a const handle."; BR.EmitBasicReport(D, this, "mutable member", "ThreadSafety", os.str(), DLoc); return; } }
bool CmsException::reportGeneral( clang::ento::PathDiagnosticLocation const& path, clang::ento::BugReporter & BR ) const { const char *sfile=BR.getSourceManager().getPresumedLoc(path.asLocation()).getFilename(); if ((!sfile) || (!support::isCmsLocalFile(sfile))) return false; return true; }
void GlobalStaticChecker::checkASTDecl(const clang::VarDecl *D, clang::ento::AnalysisManager &Mgr, clang::ento::BugReporter &BR) const { if ( D->hasAttr<CMSThreadGuardAttr>() || D->hasAttr<CMSThreadSafeAttr>()) return; clang::QualType t = D->getType(); if ( D->hasGlobalStorage() && !D->isStaticDataMember() && !D->isStaticLocal() && !support::isConst( t ) ) { clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(D, BR.getSourceManager()); if ( ! m_exception.reportGlobalStaticForType( t, DLoc, BR ) ) return; if ( support::isSafeClassName( D->getCanonicalDecl()->getQualifiedNameAsString() ) ) return; std::string buf; llvm::raw_string_ostream os(buf); os << "Non-const variable '" << t.getAsString()<<" "<<*D << "' is static and might be thread-unsafe"; BR.EmitBasicReport(D, "Possibly Thread-Unsafe: non-const static variable", "ThreadSafety", os.str(), DLoc); return; } }
void edmChecker::checkASTDecl(const clang::CXXRecordDecl *RD, clang::ento::AnalysisManager& mgr, clang::ento::BugReporter &BR) const { const clang::SourceManager &SM = BR.getSourceManager(); clang::ento::PathDiagnosticLocation DLoc =clang::ento::PathDiagnosticLocation::createBegin( RD, SM ); if ( !m_exception.reportClass( DLoc, BR ) ) return; // Check the class methods (member methods). for (clang::CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) { if ( !llvm::isa<clang::CXXMethodDecl>((*I)) ) continue; clang::CXXMethodDecl * MD = llvm::cast<clang::CXXMethodDecl>((*I)); if ( MD->getNameAsString() == "beginRun" || MD->getNameAsString() == "endRun" || MD->getNameAsString() == "beginLuminosityBlock" || MD->getNameAsString() == "endLuminosityBlock" ) { // llvm::errs()<<MD->getQualifiedNameAsString()<<"\n"; for (auto J=RD->bases_begin(), F=RD->bases_end();J != F; ++J) { std::string name = J->getType()->castAs<RecordType>()->getDecl()->getQualifiedNameAsString(); // llvm::errs()<<RD->getQualifiedNameAsString()<<"\n"; // llvm::errs() << "inherits from " <<name<<"\n"; if (name=="edm::EDProducer" || name=="edm::EDFilter") { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << RD->getQualifiedNameAsString() << " inherits from edm::EDProducer or edm::EDFilter"; os << "\n"; llvm::errs()<<os.str(); CXXMethodDecl::param_iterator I = MD->param_begin(); ParmVarDecl * PVD = *(I); QualType PQT = PVD->getType(); if ( PQT->isReferenceType() ) { QualType RQT = PQT->getPointeeType(); if (RQT.isConstQualified()) continue; } clang::ento::PathDiagnosticLocation ELoc =clang::ento::PathDiagnosticLocation::createBegin( MD, SM ); clang::SourceLocation SL = MD->getLocStart(); BR.EmitBasicReport(MD, "Class Checker : inherits from edm::EDProducer or edm::EDFilter","optional",os.str(),ELoc,SL); } } } } } //end of class
void CatchAll::checkASTCodeBody(const clang::Decl* D, clang::ento::AnalysisManager& AM, clang::ento::BugReporter& BR) const { const clang::Stmt* s=D->getBody(); if (!s) return; s=process(s); if (!s) return; clang::ento::LocationOrAnalysisDeclContext x(AM.getAnalysisDeclContext(D)); clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(s, BR.getSourceManager(),x); BR.EmitBasicReport(D, this, "'catch(...)' in sources","CMS code rules","using 'catch(...)' is forbidden", DLoc,s->getSourceRange ()); }
void getParamDumper::checkASTDecl(const clang::CXXRecordDecl *RD, clang::ento::AnalysisManager& mgr, clang::ento::BugReporter &BR) const { const clang::SourceManager &SM = BR.getSourceManager(); const char *sfile=SM.getPresumedLoc(RD->getLocation()).getFilename(); if (!support::isCmsLocalFile(sfile)) return; std::string tname = "getparam-dumper.txt.unsorted"; std::string ps = "const class edm::ParameterSet "; std::string ups = "const class edm::UntrackedParameterSet "; for (clang::CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), E = RD->ctor_end(); I != E; ++I) { clang::CXXConstructorDecl * CD = llvm::dyn_cast<clang::CXXConstructorDecl>((*I)->getMostRecentDecl()); for ( unsigned I=0, E=CD->getNumParams(); I != E; ++I) { std::string pname = CD->getParamDecl(I)->getQualifiedNameAsString(); std::string qname = CD->getParamDecl(I)->getType().getCanonicalType().getAsString(); if (qname.substr(0,ps.length()) == ps || qname.substr(0,ups.length()) == ups) { std::string buf; llvm::raw_string_ostream os(buf); os << "constructor decl '"<<CD->getQualifiedNameAsString()<< "' with parameter '"<< qname << " " << pname <<"'\n"; support::writeLog(os.str(),tname); for ( CXXConstructorDecl::init_iterator J = CD->init_begin(), E=CD->init_end(); J != E; ++J ) { if (FieldDecl * fd = (*J)->getAnyMember()) { std::string fname = fd->getQualifiedNameAsString(); std::string fqname = fd->getType().getCanonicalType().getAsString(); os << "constructor decl '"<<CD->getQualifiedNameAsString()<< "' initializer for member decl '" << fname << "' of type '" <<fqname<<"'\n"; Expr * e = (*J)->getInit(); if ( e ) { gpWalkAST walker(this,BR, mgr.getAnalysisDeclContext(CD),fd); walker.Visit(e); } } } support::writeLog(os.str(),tname); } } } for (clang::CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) { clang::CXXMethodDecl * MD = llvm::cast<clang::CXXMethodDecl>((*I)->getMostRecentDecl()); for ( unsigned I=0, E=MD->getNumParams(); I != E; ++I) { std::string pname = MD->getParamDecl(I)->getQualifiedNameAsString(); std::string qname = MD->getParamDecl(I)->getType().getCanonicalType().getAsString(); if (qname.substr(0,ps.length()) == ps || qname.substr(0,ups.length()) == ups) { std::string buf; llvm::raw_string_ostream os(buf); clang::Stmt *Body = MD->getBody(); if ( Body ) { os << "function decl '"<<MD->getQualifiedNameAsString()<< "' with parameter '"<< qname << " " << pname <<"'\n"; gpWalkAST walker(this,BR, mgr.getAnalysisDeclContext(MD),MD); walker.Visit(Body); } support::writeLog(os.str(),tname); } } } return; }