File indexing completed on 2024-04-06 12:31:50
0001
0002
0003
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
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
0047
0048
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
0059
0060
0061
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
0084
0085
0086
0087
0088
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 "struct PyModuleDef",
0153 "::pybind11::class module_::module_def"};
0154
0155 for (auto &name : names)
0156 if (cname.substr(0, name.length()) == name)
0157 return true;
0158 return false;
0159 }
0160
0161 bool clangcms::support::isDataClass(const std::string &name) {
0162 CMS_SA_ALLOW static std::string iname("");
0163 if (iname.empty()) {
0164 clang::FileSystemOptions FSO;
0165 clang::FileManager FM(FSO);
0166 const char *lPath = std::getenv("LOCALRT");
0167 const char *rPath = std::getenv("CMSSW_RELEASE_BASE");
0168 if (lPath == nullptr || rPath == nullptr) {
0169 llvm::errs()
0170 << "\n\nThe scram runtime envorinment is not set.\nRun 'cmsenv' or 'eval `scram runtime -csh`'.\n\n\n";
0171 exit(1);
0172 }
0173 const std::string lname = std::string(lPath);
0174 const std::string rname = std::string(rPath);
0175 const std::string tname("/src/Utilities/StaticAnalyzers/scripts/bloom.bin");
0176 const std::string fname1 = lname + tname;
0177 const std::string fname2 = rname + tname;
0178 if (!(FM.getFile(fname1) || FM.getFile(fname2))) {
0179 llvm::errs() << "\n\nChecker cannot find bloom filter file" << fname1 << " or " << fname2 << "\n\n\n";
0180 exit(1);
0181 }
0182 if (FM.getFile(fname1))
0183 iname = fname1;
0184 else
0185 iname = fname2;
0186 }
0187
0188 CMS_SA_ALLOW static scaling_bloom_t *blmflt = new_scaling_bloom_from_file(CAPACITY, ERROR_RATE, iname.c_str());
0189
0190 if (scaling_bloom_check(blmflt, name.c_str(), name.length()) == 1)
0191 return true;
0192
0193 return false;
0194 }
0195
0196 bool clangcms::support::isInterestingLocation(const std::string &fname) {
0197 if (fname[0] == '<' && fname.find(".h") == std::string::npos)
0198 return false;
0199 if (fname.find("/test/") != std::string::npos)
0200 return false;
0201 return true;
0202 }
0203
0204 bool clangcms::support::isKnownThrUnsafeFunc(const std::string &fname) {
0205 static const std::vector<std::string> names = {"TGraph::Fit(const char *,",
0206 "TGraph2D::Fit(const char *,",
0207 "TH1::Fit(const char *,",
0208 "TMultiGraph::Fit(const char *,",
0209 "TTable::Fit(const char *,",
0210 "TTree::Fit(const char *,",
0211 "TTreePlayer::Fit(const char *,",
0212 "CLHEP::HepMatrix::determinant("};
0213 for (auto &name : names)
0214 if (fname.substr(0, name.length()) == name)
0215 return true;
0216 return false;
0217 }
0218
0219 void clangcms::support::writeLog(const std::string &ostring, const std::string &tfstring) {
0220 const char *pPath = std::getenv("LOCALRT");
0221 if (pPath == nullptr) {
0222 llvm::errs() << "\n\nThe scram runtime envorinment is not set.\nRun 'cmsenv' or 'eval `scram runtime -csh`'.\n\n\n";
0223 exit(1);
0224 }
0225
0226 std::string pname = std::string(pPath) + "/tmp/";
0227 const std::string tname = pname + tfstring;
0228
0229 std::fstream file;
0230 file.open(tname.c_str(), std::ios::out | std::ios::app);
0231 file << ostring << "\n";
0232 file.close();
0233
0234 return;
0235 }
0236
0237 void clangcms::support::fixAnonNS(std::string &name, const char *fname) {
0238 const std::string anon_ns = "(anonymous namespace)";
0239 if (name.substr(0, anon_ns.size()) == anon_ns) {
0240 const char *sname = "/src/";
0241 const char *filename = std::strstr(fname, sname);
0242 if (filename != nullptr)
0243 name = name.substr(0, anon_ns.size() - 1) + " in " + filename + ")" + name.substr(anon_ns.size());
0244 }
0245 return;
0246 }