From e3a453001a7a48354314393506ca04847056a3cf Mon Sep 17 00:00:00 2001 From: Patrick Gartung Date: Thu, 5 Nov 2015 11:29:28 -0600 Subject: [PATCH 1/4] use the output of ldd to limit which libraries the symbols can come from --- Utilities/StaticAnalyzers/scripts/symbols.py | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Utilities/StaticAnalyzers/scripts/symbols.py b/Utilities/StaticAnalyzers/scripts/symbols.py index d2a4a93a2a9bc..56f182dcd5141 100755 --- a/Utilities/StaticAnalyzers/scripts/symbols.py +++ b/Utilities/StaticAnalyzers/scripts/symbols.py @@ -12,10 +12,12 @@ symbols_re_skip = re.compile("(@@)") nm_line_re = re.compile(r"\s+".join([addr_re, code_re, symbol_re]) + "\s*$", re.I) +ldd_line_re = re.compile(r"\s+(.*) => (.*) \(0x") requires = collections.defaultdict(set) provides = collections.defaultdict(set) dependencies = collections.defaultdict(set) +libraries = collections.defaultdict(set) def get_symbols(fname): lines = subprocess.check_output(["nm", "-g", fname]) @@ -28,6 +30,15 @@ def get_symbols(fname): else: provides[symbol].add(fname) +def get_libraries(fname): + lines = subprocess.check_output(["ldd",fname]) + for l in lines.splitlines(): + m = ldd_line_re.match(l) + if not m: continue + library = m.group(2) + libraries[fname].add(library) + + paths=os.environ['LD_LIBRARY_PATH'].split(':') for p in paths: @@ -37,20 +48,19 @@ def get_symbols(fname): filetype = subprocess.check_output(["file", fpth]) if filetype.find("dynamically linked") >= 0 : get_symbols(fpth) + get_libraries(fpth) -def pick(symbols): +def pick(symbols,libraries): # If several files provide a symbol, choose the one with the shortest name. best = None for s in symbols: - if best is None or len(s) < len(best): + if best is None or s in libraries : best = s -# if len(symbols) > 1: -# best = "*" + best return best for fname, symbols in requires.items(): - dependencies[fname] = set(pick(provides[s]) for s in symbols if s in provides) -# print fname + ': ' + ' '.join(sorted(dependencies[fname])) + dependencies[fname] = set(pick(provides[s],libraries[fname]) for s in symbols if s in provides) + print fname + ' : primary dependencies : ' + ', '.join(sorted(dependencies[fname]))+'\n' unmet = set() demangled = set() for s in symbols: @@ -58,7 +68,7 @@ def pick(symbols): for u in sorted(unmet): dm = subprocess.check_output(["c++filt",u]) demangled.add(dm.rstrip('\r\n')) -# if demangled : print fname + ': undefined : ' + ' '.join(sorted(demangled)) + if demangled : print fname + ': undefined : ' + ', '.join(sorted(demangled)) import networkx as nx G=nx.DiGraph() @@ -74,4 +84,4 @@ def pick(symbols): if key != node : deps.add(key) for v in vals : deps.add(v) - print node + ': ' + ','.join(sorted(deps)) + print node + ': primary and secondary dependencies' + ', '.join(sorted(deps)) From 525cbadc65b5ac414c749ede38a899a6dfa87553 Mon Sep 17 00:00:00 2001 From: Patrick Gartung Date: Thu, 5 Nov 2015 16:05:49 -0600 Subject: [PATCH 2/4] produce graphviz graphs if pydot is available --- Utilities/StaticAnalyzers/scripts/symbols.py | 27 ++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Utilities/StaticAnalyzers/scripts/symbols.py b/Utilities/StaticAnalyzers/scripts/symbols.py index 56f182dcd5141..a538e28ad1733 100755 --- a/Utilities/StaticAnalyzers/scripts/symbols.py +++ b/Utilities/StaticAnalyzers/scripts/symbols.py @@ -50,16 +50,12 @@ def get_libraries(fname): get_symbols(fpth) get_libraries(fpth) -def pick(symbols,libraries): - # If several files provide a symbol, choose the one with the shortest name. - best = None - for s in symbols: - if best is None or s in libraries : - best = s - return best - for fname, symbols in requires.items(): - dependencies[fname] = set(pick(provides[s],libraries[fname]) for s in symbols if s in provides) + dependencies[fname] = set() + for s in symbols: + for p in provides[s]: + for f in libraries[fname]: + if f==p : dependencies[fname].add(f) print fname + ' : primary dependencies : ' + ', '.join(sorted(dependencies[fname]))+'\n' unmet = set() demangled = set() @@ -84,4 +80,15 @@ def pick(symbols,libraries): if key != node : deps.add(key) for v in vals : deps.add(v) - print node + ': primary and secondary dependencies' + ', '.join(sorted(deps)) + print node + ': primary and secondary dependencies :' + ', '.join(sorted(deps)) + +import pydot + +H=nx.DiGraph() +for key,values in dependencies.items(): + H.add_node(os.path.basename(key)) + for val in values: H.add_edge(os.path.basename(key),os.path.basename(val)) +for node in nx.nodes_iter(H): + T = nx.dfs_tree(H,node) + name = node + ".dot" + nx.write_dot(T,name) From 195fd180f34e14b98520fec103f0e1a46e70f115 Mon Sep 17 00:00:00 2001 From: Patrick Gartung Date: Mon, 9 Nov 2015 10:35:54 -0600 Subject: [PATCH 3/4] put back old symbols to library matching --- Utilities/StaticAnalyzers/scripts/symbols.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Utilities/StaticAnalyzers/scripts/symbols.py b/Utilities/StaticAnalyzers/scripts/symbols.py index a538e28ad1733..bbfd5493cc735 100755 --- a/Utilities/StaticAnalyzers/scripts/symbols.py +++ b/Utilities/StaticAnalyzers/scripts/symbols.py @@ -36,7 +36,7 @@ def get_libraries(fname): m = ldd_line_re.match(l) if not m: continue library = m.group(2) - libraries[fname].add(library) + libraries[fname].add(library.rstrip('\r\n')) paths=os.environ['LD_LIBRARY_PATH'].split(':') @@ -50,12 +50,15 @@ def get_libraries(fname): get_symbols(fpth) get_libraries(fpth) -for fname, symbols in requires.items(): - dependencies[fname] = set() +def pick(symbols,libraries): + best = None for s in symbols: - for p in provides[s]: - for f in libraries[fname]: - if f==p : dependencies[fname].add(f) + if best is None or s in libraries : + best = s + return best + +for fname, symbols in requires.items(): + dependencies[fname] = set(pick(provides[s],libraries[fname]) for s in symbols if s in provides) print fname + ' : primary dependencies : ' + ', '.join(sorted(dependencies[fname]))+'\n' unmet = set() demangled = set() From 5dbb28aea9c79c8bf837ac0830af196306998972 Mon Sep 17 00:00:00 2001 From: Patrick Gartung Date: Mon, 9 Nov 2015 21:15:15 -0600 Subject: [PATCH 4/4] move fixAnonNS to CmsSupport.cpp --- .../StaticAnalyzers/src/ClassChecker.cpp | 95 +++++++------------ Utilities/StaticAnalyzers/src/ClassDumper.cpp | 55 +++++------ Utilities/StaticAnalyzers/src/CmsSupport.cpp | 10 ++ Utilities/StaticAnalyzers/src/CmsSupport.h | 1 + 4 files changed, 69 insertions(+), 92 deletions(-) diff --git a/Utilities/StaticAnalyzers/src/ClassChecker.cpp b/Utilities/StaticAnalyzers/src/ClassChecker.cpp index d2a8a011e9ceb..aec185bb427f4 100644 --- a/Utilities/StaticAnalyzers/src/ClassChecker.cpp +++ b/Utilities/StaticAnalyzers/src/ClassChecker.cpp @@ -49,8 +49,6 @@ void writeLog(std::string ostring) { return; } - - class WalkAST : public clang::StmtVisitor { const CheckerBase *Checker; clang::ento::BugReporter &BR; @@ -82,35 +80,21 @@ class WalkAST : public clang::StmtVisitor { /// generating bug reports. This is null while visiting the body of a /// constructor or destructor. const clang::CXXMemberCallExpr *visitingCallExpr; - + const char *sfile; public: - WalkAST(const CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac, const CXXMethodDecl * fd) + WalkAST(const CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac, const CXXMethodDecl * fd, const char* file) : Checker(checker), BR(br), AC(ac), AD(fd), - visitingCallExpr(0) {} - - void fixAnonNS(std::string & name) { - const std::string anon_ns = "(anonymous namespace)"; - if (name.substr(0, anon_ns.size()) == anon_ns ) { - const char* fname = BR.getSourceManager().getPresumedLoc(AD->getLocation()).getFilename(); - const char* sname = "/src/"; - const char* filename = std::strstr(fname, sname); - if (filename != NULL) name = name.substr(0, anon_ns.size() - 1)+" in "+filename+")"+name.substr(anon_ns.size()); - } - return; - } - + visitingCallExpr(0),sfile(file) {} bool hasWork() const { return !WList.empty(); } /// This method adds a CallExpr to the worklist void Enqueue(WorkListUnit WLUnit) { Kind &K = VisitedFunctions[WLUnit]; - if (K = Visiting) { - return; - } + if ((K = Visiting)) return; K = Visiting; WList.push_back(WLUnit); } @@ -253,7 +237,6 @@ void WalkAST::CheckCXXOperatorCallExpr(const clang::CXXOperatorCallExpr *OCE,con void WalkAST::CheckExplicitCastExpr(const clang::ExplicitCastExpr * CE,const clang::MemberExpr *ME){ - if (! ( clang::CStyleCastExpr::classof(CE) || clang::CXXConstCastExpr::classof(CE) )) return; const clang::Expr *E = CE->getSubExpr(); clang::ASTContext &Ctx = AC->getASTContext(); @@ -296,9 +279,9 @@ void WalkAST::CheckReturnStmt(const clang::ReturnStmt * RS, const clang::MemberE std::string buf; llvm::raw_string_ostream os(buf); std::string mname = support::getQualifiedName(*MD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string pname = support::getQualifiedName(*(MD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); os << mname << " is a const member function that returns a const std::vector<*> or const std::vector<*>& "<getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str()+"."; writeLog(tolog); BugType * BT = new BugType(Checker,"const_cast used in const function ","Data Class Const Correctness"); @@ -330,12 +313,11 @@ void WalkAST::VisitCXXConstCastExpr(clang::CXXConstCastExpr *CCE) { } void WalkAST::VisitDeclRefExpr( clang::DeclRefExpr * DRE) { - if (clang::VarDecl * D = llvm::dyn_cast_or_null(DRE->getDecl()) ) { + if (clang::VarDecl * D = llvm::dyn_cast_or_null(DRE->getDecl()) ) { clang::SourceLocation SL = DRE->getLocStart(); if (BR.getSourceManager().isInSystemHeader(SL) || BR.getSourceManager().isInExternCSystemHeader(SL)) return; if ( support::isSafeClassName( D->getCanonicalDecl()->getQualifiedNameAsString() ) ) return; ReportDeclRef( DRE ); - } } @@ -360,9 +342,9 @@ void WalkAST::ReportDeclRef( const clang::DeclRefExpr * DRE) { PS->printPretty(os,0,Policy); os << "'.\n"; std::string pname = support::getQualifiedName(*(AD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str(); writeLog(tolog); BugType * BT = new BugType(Checker,"ClassChecker : non-const static local variable accessed","Data Class Const Correctness"); @@ -379,9 +361,9 @@ void WalkAST::ReportDeclRef( const clang::DeclRefExpr * DRE) { PS->printPretty(os,0,Policy); os << "'.\n"; std::string pname = support::getQualifiedName(*(AD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str(); writeLog(tolog); BugType * BT = new BugType(Checker,"Non-const static member variable accessed","Data Class Const Correctness"); @@ -403,9 +385,9 @@ void WalkAST::ReportDeclRef( const clang::DeclRefExpr * DRE) { PS->printPretty(os,0,Policy); os << "'.\n"; std::string pname = support::getQualifiedName(*(AD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str(); writeLog(tolog); BugType * BT = new BugType(Checker,"Non-const global static variable accessed","Data Class Const Correctness"); @@ -423,7 +405,6 @@ void WalkAST::VisitMemberExpr( clang::MemberExpr *ME) { clang::SourceLocation SL = ME->getExprLoc(); if (BR.getSourceManager().isInSystemHeader(SL) || BR.getSourceManager().isInExternCSystemHeader(SL)) return; - const ValueDecl * D = ME->getMemberDecl(); if ( D->hasAttr() || D->hasAttr()) return; if (!(ME->isImplicitAccess())) return; @@ -502,9 +483,9 @@ void WalkAST::ReportMember(const clang::MemberExpr *ME) { ME->printPretty(os,0,Policy); os << "' is directly or indirectly modified in const function\n"; std::string pname = support::getQualifiedName(*(AD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: " + os.str(); writeLog(tolog); BR.EmitBasicReport(AD,Checker,"Member data modified in const function","Data Class Const Correctness",os.str(),CELoc); @@ -521,7 +502,6 @@ void WalkAST::ReportCall(const clang::CXXMemberCallExpr *CE) { clang::LangOptions LangOpts; LangOpts.CPlusPlus = true; clang::PrintingPolicy Policy(LangOpts); - os << "call expr '"; CE->printPretty(os,0,Policy); os << "' with implicit object argument '"; @@ -530,9 +510,9 @@ void WalkAST::ReportCall(const clang::CXXMemberCallExpr *CE) { os<<"' is a non-const member function '"<getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+ pname +"' const function '" + mname + "' Warning: "+os.str(); if ( support::isSafeClassName(support::getQualifiedName(*MD)) ) return; writeLog(tolog); @@ -556,9 +536,9 @@ void WalkAST::ReportCast(const clang::ExplicitCastExpr *CE) { os << "Const qualifier of member data object"; os <<" was removed via cast expression '"; std::string pname = support::getQualifiedName(*(AD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str(); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(),AC); @@ -588,9 +568,9 @@ void WalkAST::ReportCallArg(const clang::CXXMemberCallExpr *CE,const int i) { os << "\n"; std::string pname = support::getQualifiedName(*(AD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str(); @@ -619,9 +599,9 @@ void WalkAST::ReportCallReturn(const clang::ReturnStmt * RS) { clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(RS, BR.getSourceManager(),AC); std::string pname = support::getQualifiedName(*(AD->getParent())); - fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*AD); - fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str(); writeLog(tolog); clang::ASTContext &Ctx = AC->getASTContext(); @@ -650,35 +630,32 @@ void ClassChecker::checkASTDecl(const clang::CXXRecordDecl *RD, clang::ento::Ana clang::ento::BugReporter &BR) const { const clang::SourceManager &SM = BR.getSourceManager(); - const char *sfile=SM.getPresumedLoc(RD->getLocation()).getFilename(); + const char *sfile=SM.getPresumedLoc(RD->getLocation()).getFilename(); if (!support::isCmsLocalFile(sfile)) return; - std::string buf; llvm::raw_string_ostream os(buf); std::string name = RD->getQualifiedNameAsString(); if ( ! support::isDataClass(name) ) return; - for ( auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I) { const FieldDecl * D = (*I) ; - if ( D->hasAttr() || D->hasAttr()) return; - if ( D->isMutable() ) + if ( D->hasAttr() || D->hasAttr()) return; + if ( D->isMutable() ) { clang::QualType t = D->getType(); clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(D, BR.getSourceManager()); if ( support::isSafeClassName( t.getCanonicalType().getAsString() ) ) return; - if ( ! support::isDataClass( support::getQualifiedName(*RD) ) ) return; - WalkAST walker(this,BR, mgr.getAnalysisDeclContext(RD), (*(RD->ctor_begin()))->getMostRecentDecl() ) ; + if ( ! support::isDataClass( support::getQualifiedName(*RD) ) ) return; std::string buf; llvm::raw_string_ostream os(buf); os << "Mutable member '" <hasAttr() || MD->hasAttr()) continue; if ( MD->hasBody() ) { clang::Stmt *Body = MD->getBody(); - WalkAST walker(this,BR, mgr.getAnalysisDeclContext(MD),MD); + WalkAST walker(this,BR, mgr.getAnalysisDeclContext(MD),MD,sfile); walker.Visit(Body); clang::QualType RQT = MD->getCallResultType(); clang::ASTContext &Ctx = BR.getContext(); @@ -707,9 +684,9 @@ void ClassChecker::checkASTDecl(const clang::CXXRecordDecl *RD, clang::ento::Ana llvm::raw_string_ostream os(buf); os << MD->getQualifiedNameAsString() << " is a const member function that returns a pointer or reference to a non-const object \n"; std::string pname = support::getQualifiedName(*(MD->getParent())); - walker.fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*MD); - walker.fixAnonNS(mname); + support::fixAnonNS(mname,sfile); std::string tolog = "data class '"+pname+"' const function '" + mname + "' Warning: "+os.str(); writeLog(tolog); BR.EmitBasicReport(MD,this, "Const function returns pointer or reference to non-const object.","Data Class Const Correctness",os.str(),ELoc); @@ -728,9 +705,9 @@ void ClassChecker::checkASTDecl(const clang::CXXRecordDecl *RD, clang::ento::Ana std::string buf; llvm::raw_string_ostream os(buf); std::string pname = support::getQualifiedName(*(MD->getParent())); - walker.fixAnonNS(pname); + support::fixAnonNS(pname,sfile); std::string mname = support::getQualifiedName(*MD); - walker.fixAnonNS(mname); + support::fixAnonNS(mname,sfile); os << mname << " is a const member function that returns an object of type const std::vector<*> or const std::vector<*>& "<getLocation()).getFilename(); if (!RD->hasDefinition()) return; std::string rname = RD->getQualifiedNameAsString(); - fixAnonNS(rname,sfile); + support::fixAnonNS(rname,sfile); clang::LangOptions LangOpts; LangOpts.CPlusPlus = true; clang::PrintingPolicy Policy(LangOpts); @@ -45,18 +36,18 @@ void ClassDumper::checkASTDecl(const clang::CXXRecordDecl *RD,clang::ento::Analy if (tt->isRecordType()) { auto TAD = tt->getAsCXXRecordDecl(); if (TAD) taname = TAD->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string sdname = SD->getQualifiedNameAsString(); - fixAnonNS(sdname,sfile); + support::fixAnonNS(sdname,sfile); std::string cfname = "templated data class '"+sdname+"' template type class '"+taname+"'"; support::writeLog(crname+" "+cfname,tname); } - if (tt->isPointerType() || tt->isReferenceType() ) { + if ( tt->isPointerType() || tt->isReferenceType() ) { auto TAD = tt->getPointeeCXXRecordDecl(); if (TAD) taname = TAD->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string sdname = SD->getQualifiedNameAsString(); - fixAnonNS(sdname,sfile); + support::fixAnonNS(sdname,sfile); std::string cfname = "templated data class '"+sdname+"' template type class '"+taname+"'"; std::string cbname = "templated data class 'bare_ptr' template type class '"+taname+"'"; support::writeLog(crname+" "+cfname,tname); @@ -83,7 +74,7 @@ void ClassDumper::checkASTDecl(const clang::CXXRecordDecl *RD,clang::ento::Analy if (!qual.getTypePtr()->isRecordType()) continue; if (const CXXRecordDecl * TRD = qual.getTypePtr()->getAsCXXRecordDecl()) { std::string fname = TRD->getQualifiedNameAsString(); - fixAnonNS(fname, sfile); + support::fixAnonNS(fname, sfile); const ClassTemplateSpecializationDecl *SD = dyn_cast_or_null(TRD); if (SD) { std::string buf; @@ -99,18 +90,18 @@ void ClassDumper::checkASTDecl(const clang::CXXRecordDecl *RD,clang::ento::Analy if ( tt->isRecordType() ) { const clang::CXXRecordDecl * TAD = tt->getAsCXXRecordDecl(); if (TAD) taname = TAD->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string sdname = SD->getQualifiedNameAsString(); - fixAnonNS(sdname,sfile); + support::fixAnonNS(sdname,sfile); std::string cfname = "templated member data class '"+sdname+"' template type class '"+taname+"'"; support::writeLog(crname+" "+cfname,tname); } if ( tt->isPointerType() || tt->isReferenceType() ) { const clang::CXXRecordDecl * TAD = tt->getPointeeCXXRecordDecl(); if (TAD) taname = TAD->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string sdname = SD->getQualifiedNameAsString(); - fixAnonNS(sdname,sfile); + support::fixAnonNS(sdname,sfile); std::string cfname = "templated member data class '"+sdname+"' template type class '"+taname+"'"; std::string cbname = "templated member data class 'bare_ptr' template type class '"+taname+"'"; support::writeLog(crname+" "+cfname,tname); @@ -141,7 +132,7 @@ void ClassDumper::checkASTDecl(const clang::CXXRecordDecl *RD,clang::ento::Analy auto BRD = J->getType()->getAsCXXRecordDecl(); if (!BRD) continue; std::string bname = BRD->getQualifiedNameAsString(); - fixAnonNS(bname,sfile); + support::fixAnonNS(bname,sfile); std::string cbname = "base class '"+bname+"'"; support::writeLog(crname+" "+cbname,tname); } @@ -154,10 +145,10 @@ void ClassDumperCT::checkASTDecl(const clang::ClassTemplateDecl *TD,clang::ento: const char *sfile=BR.getSourceManager().getPresumedLoc(TD->getLocation()).getFilename(); if (!support::isCmsLocalFile(sfile)) return; - std::string crname("class '"); std::string pname = "classes.txt.dumperct.unsorted"; std::string tname = TD->getTemplatedDecl()->getQualifiedNameAsString(); + if ( tname == "edm::Wrapper" || tname == "edm::RunCache" || tname == "edm::LuminosityBlockCache" || tname == "edm::GlobalCache" ) { for ( auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) { @@ -166,9 +157,9 @@ void ClassDumperCT::checkASTDecl(const clang::ClassTemplateDecl *TD,clang::ento: if (D) { ClassDumper dumper; dumper.checkASTDecl( D, mgr, BR,pname ); std::string taname = D->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string tdname = TD->getQualifiedNameAsString(); - fixAnonNS(tdname,sfile); + support::fixAnonNS(tdname,sfile); std::string cfname = "templated class '"+tdname+"' template type class '"+taname+"'"; support::writeLog(cfname,pname); } @@ -176,9 +167,9 @@ void ClassDumperCT::checkASTDecl(const clang::ClassTemplateDecl *TD,clang::ento: if (E) { ClassDumper dumper; dumper.checkASTDecl( E, mgr, BR,pname ); std::string taname = E->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string tdname = TD->getQualifiedNameAsString(); - fixAnonNS(tdname,sfile); + support::fixAnonNS(tdname,sfile); std::string cfname = "templated class '"+tdname+"' template type class '"+taname+"'"; support::writeLog(cfname,pname); std::string cbname = "templated class 'bare_ptr' template type class '"+taname+"'"; @@ -187,7 +178,6 @@ void ClassDumperCT::checkASTDecl(const clang::ClassTemplateDecl *TD,clang::ento: } } } - } //end class void ClassDumperFT::checkASTDecl(const clang::FunctionTemplateDecl *TD,clang::ento::AnalysisManager& mgr, @@ -195,7 +185,6 @@ void ClassDumperFT::checkASTDecl(const clang::FunctionTemplateDecl *TD,clang::en const char *sfile=BR.getSourceManager().getPresumedLoc(TD->getLocation()).getFilename(); if (!support::isCmsLocalFile(sfile)) return; - std::string crname("class '"); std::string pname = "classes.txt.dumperft.unsorted"; if (TD->getTemplatedDecl()->getQualifiedNameAsString().find("typelookup::className") != std::string::npos ) { @@ -207,9 +196,9 @@ void ClassDumperFT::checkASTDecl(const clang::FunctionTemplateDecl *TD,clang::en if (D) { ClassDumper dumper; dumper.checkASTDecl( D, mgr, BR,pname ); std::string taname = D->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string sdname = SD->getQualifiedNameAsString(); - fixAnonNS(sdname,sfile); + support::fixAnonNS(sdname,sfile); std::string cfname = "templated function '"+sdname+"' template type class '"+taname+"'"; support::writeLog(cfname,pname); } @@ -217,9 +206,9 @@ void ClassDumperFT::checkASTDecl(const clang::FunctionTemplateDecl *TD,clang::en if (E) { ClassDumper dumper; dumper.checkASTDecl( E, mgr, BR,pname ); std::string taname = E->getQualifiedNameAsString(); - fixAnonNS(taname,sfile); + support::fixAnonNS(taname,sfile); std::string sdname = SD->getQualifiedNameAsString(); - fixAnonNS(sdname,sfile); + support::fixAnonNS(sdname,sfile); std::string cfname = "templated function '"+sdname+"' template type class '"+taname+"'"; support::writeLog(cfname,pname); std::string cbname = "templated function 'bare_ptr' template type class '"+taname+"'"; @@ -228,7 +217,7 @@ void ClassDumperFT::checkASTDecl(const clang::FunctionTemplateDecl *TD,clang::en } } - } + } } //end class void ClassDumperInherit::checkASTDecl(const clang::CXXRecordDecl *RD, clang::ento::AnalysisManager& mgr, diff --git a/Utilities/StaticAnalyzers/src/CmsSupport.cpp b/Utilities/StaticAnalyzers/src/CmsSupport.cpp index 883de3039a724..371ec3e8a7d6e 100644 --- a/Utilities/StaticAnalyzers/src/CmsSupport.cpp +++ b/Utilities/StaticAnalyzers/src/CmsSupport.cpp @@ -220,3 +220,13 @@ void support::writeLog(const std::string &ostring,const std::string &tfstring) { return; } +void support::fixAnonNS(std::string & name, const char * fname ){ + const std::string anon_ns = "(anonymous namespace)"; + if (name.substr(0, anon_ns.size()) == anon_ns ) { + const char* sname = "/src/"; + const char* filename = std::strstr(fname, sname); + if (filename != NULL) name = name.substr(0, anon_ns.size() - 1)+" in "+filename+")"+name.substr(anon_ns.size()); + } + return; +} + diff --git a/Utilities/StaticAnalyzers/src/CmsSupport.h b/Utilities/StaticAnalyzers/src/CmsSupport.h index c322495ce2db1..57010e6e4d984 100644 --- a/Utilities/StaticAnalyzers/src/CmsSupport.h +++ b/Utilities/StaticAnalyzers/src/CmsSupport.h @@ -50,6 +50,7 @@ bool isDataClass(const std::string &d); bool isInterestingLocation(const std::string &d); bool isKnownThrUnsafeFunc(const std::string &name ); void writeLog(const std::string &ostring,const std::string &tfstring); +void fixAnonNS(std::string & name, const char * fname ); } }