Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-10-13 23:03:32

0001 //===--- CmsSupport.cpp - Provides support functions ------------*- C++ -*-===//
0002 //
0003 // by Shahzad Malik MUZAFFAR [ Shahzad.Malik.MUZAFFAR@cern.ch ]
0004 //
0005 //===----------------------------------------------------------------------===//
0006 #include "CmsSupport.h"
0007 #include <clang/Basic/FileManager.h>
0008 #include <clang/StaticAnalyzer/Core/Checker.h>
0009 #include <clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h>
0010 #include <clang/StaticAnalyzer/Core/BugReporter/BugType.h>
0011 #include <llvm/ADT/SmallString.h>
0012 #include <clang/AST/DeclTemplate.h>
0013 #include <llvm/Support/raw_ostream.h>
0014 #include <llvm/Support/Regex.h>
0015 #include <cstdlib>
0016 #include <cstring>
0017 #include <iostream>
0018 #include <fstream>
0019 #include <iterator>
0020 #include <string>
0021 
0022 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0023 
0024 // PGartung needed for bloom filter loading
0025 extern "C" {
0026 #include "dablooms.h"
0027 #define CAPACITY 5000
0028 #define ERROR_RATE .0002
0029 }
0030 
0031 using namespace clang;
0032 using namespace llvm;
0033 bool clangcms::support::isCmsLocalFile(const char *file) {
0034   static const char *LocalDir = std::getenv("LOCALRT");
0035   CMS_SA_ALLOW static int DirLen = -1;
0036   if (DirLen == -1) {
0037     DirLen = 0;
0038     if (LocalDir != nullptr)
0039       DirLen = strlen(LocalDir);
0040   }
0041   if ((DirLen == 0) || (strncmp(file, LocalDir, DirLen) != 0) || (strncmp(&file[DirLen], "/src/", 5) != 0))
0042     return false;
0043   return true;
0044 }
0045 
0046 // This is a wrapper around NamedDecl::getQualifiedNameAsString.
0047 // It produces more qualified output to distinguish several cases
0048 // which would otherwise be ambiguous.
0049 std::string clangcms::support::getQualifiedName(const clang::NamedDecl &d) {
0050   std::string ret;
0051   LangOptions LangOpts;
0052   LangOpts.CPlusPlus = true;
0053   PrintingPolicy Policy(LangOpts);
0054   Policy.FullyQualifiedName = true;
0055   Policy.PrintCanonicalTypes = true;
0056   const DeclContext *ctx = d.getDeclContext();
0057   if (ctx->isFunctionOrMethod() && isa<NamedDecl>(ctx)) {
0058     // This is a local variable.
0059     // d.getQualifiedNameAsString() will return the unqualifed name for this
0060     // but we want an actual qualified name so we can distinguish variables
0061     // with the same name but that are in different functions.
0062     ret = getQualifiedName(*cast<NamedDecl>(ctx)) + "::" + d.getNameAsString();
0063   } else {
0064     ret = d.getQualifiedNameAsString();
0065   }
0066 
0067   if (const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(&d)) {
0068     if (fd->isFunctionTemplateSpecialization()) {
0069       ret += "<";
0070       const TemplateArgumentList *TemplateArgs = fd->getTemplateSpecializationArgs();
0071       if (TemplateArgs) {
0072         unsigned num_args = TemplateArgs->size();
0073         for (unsigned i = 0; i < num_args; ++i) {
0074           if (i)
0075             ret += ",";
0076           TemplateArgument TemplateArg = TemplateArgs->get(i);
0077           if (TemplateArg.getKind() == TemplateArgument::ArgKind::Type)
0078             ret += TemplateArg.getAsType().getAsString();
0079         }
0080       }
0081       ret += ">";
0082     }
0083     // This is a function. getQualifiedNameAsString will return a string
0084     // like "ANamespace::AFunction". To this we append the list of parameters
0085     // so that we can distinguish correctly between
0086     // void ANamespace::AFunction(int);
0087     // and
0088     // void ANamespace::AFunction(float);
0089     ret += "(";
0090     const clang::FunctionType *ft = fd->getType()->castAs<clang::FunctionType>();
0091     if (const FunctionProtoType *fpt = dyn_cast_or_null<FunctionProtoType>(ft)) {
0092       unsigned num_params = fd->getNumParams();
0093       for (unsigned i = 0; i < num_params; ++i) {
0094         if (i)
0095           ret += ", ";
0096         ret += fd->getParamDecl(i)->getType().getAsString(Policy);
0097       }
0098 
0099       if (fpt->isVariadic()) {
0100         if (num_params > 0)
0101           ret += ", ";
0102         ret += "...";
0103       }
0104     }
0105     ret += ")";
0106     if (ft->isConst())
0107       ret += " const";
0108   }
0109 
0110   return ret;
0111 }
0112 
0113 bool clangcms::support::isSafeClassName(const std::string &cname) {
0114   static const std::vector<std::string> names = {"atomic<",
0115                                                  "std::atomic<",
0116                                                  "struct std::atomic<",
0117                                                  "std::__atomic_",
0118                                                  "struct std::atomic_flag",
0119                                                  "std::atomic_flag",
0120                                                  "__atomic_flag",
0121                                                  "atomic_flag",
0122                                                  "std::mutex",
0123                                                  "std::recursive_mutex",
0124                                                  "boost::thread_specific_ptr",
0125                                                  "class std::atomic",
0126                                                  "class std::__atomic_",
0127                                                  "class std::mutex",
0128                                                  "class std::recursive_mutex",
0129                                                  "class boost::thread_specific_ptr",
0130                                                  "tbb::",
0131                                                  "class tbb::",
0132                                                  "concurrent_unordered_map",
0133                                                  "class concurrent_unordered_map",
0134                                                  "edm::AtomicPtrCache",
0135                                                  "class edm::AtomicPtrCache",
0136                                                  "edm::InputTag",
0137                                                  "class edm::InputTag",
0138                                                  "std::once_flag",
0139                                                  "struct std::once_flag",
0140                                                  "boost::<anonymous namespace>::extents",
0141                                                  "cout",
0142                                                  "cerr",
0143                                                  "std::cout",
0144                                                  "std::cerr",
0145                                                  "edm::RunningAverage",
0146                                                  "class edm::RunningAverage",
0147                                                  "TVirtualMutex",
0148                                                  "class TVirtualMutex",
0149                                                  "boost::(anonymous namespace)::extents",
0150                                                  "(anonymous namespace)::_1",
0151                                                  "(anonymous namespace)::_2"};
0152 
0153   for (auto &name : names)
0154     if (cname.substr(0, name.length()) == name)
0155       return true;
0156   return false;
0157 }
0158 
0159 bool clangcms::support::isDataClass(const std::string &name) {
0160   CMS_SA_ALLOW static std::string iname("");
0161   if (iname.empty()) {
0162     clang::FileSystemOptions FSO;
0163     clang::FileManager FM(FSO);
0164     const char *lPath = std::getenv("LOCALRT");
0165     const char *rPath = std::getenv("CMSSW_RELEASE_BASE");
0166     if (lPath == nullptr || rPath == nullptr) {
0167       llvm::errs()
0168           << "\n\nThe scram runtime envorinment is not set.\nRun 'cmsenv' or 'eval `scram runtime -csh`'.\n\n\n";
0169       exit(1);
0170     }
0171     const std::string lname = std::string(lPath);
0172     const std::string rname = std::string(rPath);
0173     const std::string tname("/src/Utilities/StaticAnalyzers/scripts/bloom.bin");
0174     const std::string fname1 = lname + tname;
0175     const std::string fname2 = rname + tname;
0176     if (!(FM.getFile(fname1) || FM.getFile(fname2))) {
0177       llvm::errs() << "\n\nChecker cannot find bloom filter file" << fname1 << " or " << fname2 << "\n\n\n";
0178       exit(1);
0179     }
0180     if (FM.getFile(fname1))
0181       iname = fname1;
0182     else
0183       iname = fname2;
0184   }
0185 
0186   CMS_SA_ALLOW static scaling_bloom_t *blmflt = new_scaling_bloom_from_file(CAPACITY, ERROR_RATE, iname.c_str());
0187 
0188   if (scaling_bloom_check(blmflt, name.c_str(), name.length()) == 1)
0189     return true;
0190 
0191   return false;
0192 }
0193 
0194 bool clangcms::support::isInterestingLocation(const std::string &fname) {
0195   if (fname[0] == '<' && fname.find(".h") == std::string::npos)
0196     return false;
0197   if (fname.find("/test/") != std::string::npos)
0198     return false;
0199   return true;
0200 }
0201 
0202 bool clangcms::support::isKnownThrUnsafeFunc(const std::string &fname) {
0203   static const std::vector<std::string> names = {"TGraph::Fit(const char *,",
0204                                                  "TGraph2D::Fit(const char *,",
0205                                                  "TH1::Fit(const char *,",
0206                                                  "TMultiGraph::Fit(const char *,",
0207                                                  "TTable::Fit(const char *,",
0208                                                  "TTree::Fit(const char *,",
0209                                                  "TTreePlayer::Fit(const char *,",
0210                                                  "CLHEP::HepMatrix::determinant("};
0211   for (auto &name : names)
0212     if (fname.substr(0, name.length()) == name)
0213       return true;
0214   return false;
0215 }
0216 
0217 void clangcms::support::writeLog(const std::string &ostring, const std::string &tfstring) {
0218   const char *pPath = std::getenv("LOCALRT");
0219   if (pPath == nullptr) {
0220     llvm::errs() << "\n\nThe scram runtime envorinment is not set.\nRun 'cmsenv' or 'eval `scram runtime -csh`'.\n\n\n";
0221     exit(1);
0222   }
0223 
0224   std::string pname = std::string(pPath) + "/tmp/";
0225   const std::string tname = pname + tfstring;
0226 
0227   std::fstream file;
0228   file.open(tname.c_str(), std::ios::out | std::ios::app);
0229   file << ostring << "\n";
0230   file.close();
0231 
0232   return;
0233 }
0234 
0235 void clangcms::support::fixAnonNS(std::string &name, const char *fname) {
0236   const std::string anon_ns = "(anonymous namespace)";
0237   if (name.substr(0, anon_ns.size()) == anon_ns) {
0238     const char *sname = "/src/";
0239     const char *filename = std::strstr(fname, sname);
0240     if (filename != nullptr)
0241       name = name.substr(0, anon_ns.size() - 1) + " in " + filename + ")" + name.substr(anon_ns.size());
0242   }
0243   return;
0244 }