File indexing completed on 2024-12-19 04:04:57
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 (strncmp(file, "src/", 4) == 0)
0042 return true;
0043 if ((DirLen == 0) || (strncmp(file, LocalDir, DirLen) != 0) || (strncmp(&file[DirLen], "/src/", 5) != 0))
0044 return false;
0045 return true;
0046 }
0047
0048
0049
0050
0051 std::string clangcms::support::getQualifiedName(const clang::NamedDecl &d) {
0052 std::string ret;
0053 LangOptions LangOpts;
0054 LangOpts.CPlusPlus = true;
0055 PrintingPolicy Policy(LangOpts);
0056 Policy.FullyQualifiedName = true;
0057 Policy.PrintCanonicalTypes = true;
0058 const DeclContext *ctx = d.getDeclContext();
0059 if (ctx->isFunctionOrMethod() && isa<NamedDecl>(ctx)) {
0060
0061
0062
0063
0064 ret = getQualifiedName(*cast<NamedDecl>(ctx)) + "::" + d.getNameAsString();
0065 } else {
0066 ret = d.getQualifiedNameAsString();
0067 }
0068
0069 if (const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(&d)) {
0070 if (fd->isFunctionTemplateSpecialization()) {
0071 ret += "<";
0072 const TemplateArgumentList *TemplateArgs = fd->getTemplateSpecializationArgs();
0073 if (TemplateArgs) {
0074 unsigned num_args = TemplateArgs->size();
0075 for (unsigned i = 0; i < num_args; ++i) {
0076 if (i)
0077 ret += ",";
0078 TemplateArgument TemplateArg = TemplateArgs->get(i);
0079 if (TemplateArg.getKind() == TemplateArgument::ArgKind::Type)
0080 ret += TemplateArg.getAsType().getAsString();
0081 }
0082 }
0083 ret += ">";
0084 }
0085
0086
0087
0088
0089
0090
0091 ret += "(";
0092 const clang::FunctionType *ft = fd->getType()->castAs<clang::FunctionType>();
0093 if (const FunctionProtoType *fpt = dyn_cast_or_null<FunctionProtoType>(ft)) {
0094 unsigned num_params = fd->getNumParams();
0095 for (unsigned i = 0; i < num_params; ++i) {
0096 if (i)
0097 ret += ", ";
0098 ret += fd->getParamDecl(i)->getType().getAsString(Policy);
0099 }
0100
0101 if (fpt->isVariadic()) {
0102 if (num_params > 0)
0103 ret += ", ";
0104 ret += "...";
0105 }
0106 }
0107 ret += ")";
0108 if (ft->isConst())
0109 ret += " const";
0110 }
0111
0112 return ret;
0113 }
0114
0115 bool clangcms::support::isSafeClassName(const std::string &cname) {
0116 static const std::vector<std::string> names = {"atomic<",
0117 "std::atomic<",
0118 "struct std::atomic<",
0119 "std::__atomic_",
0120 "struct std::atomic_flag",
0121 "std::atomic_flag",
0122 "__atomic_flag",
0123 "atomic_flag",
0124 "std::mutex",
0125 "std::recursive_mutex",
0126 "boost::thread_specific_ptr",
0127 "class std::atomic",
0128 "class std::__atomic_",
0129 "class std::mutex",
0130 "class std::recursive_mutex",
0131 "class boost::thread_specific_ptr",
0132 "tbb::",
0133 "class tbb::",
0134 "concurrent_unordered_map",
0135 "class concurrent_unordered_map",
0136 "edm::AtomicPtrCache",
0137 "class edm::AtomicPtrCache",
0138 "edm::InputTag",
0139 "class edm::InputTag",
0140 "std::once_flag",
0141 "struct std::once_flag",
0142 "boost::<anonymous namespace>::extents",
0143 "cout",
0144 "cerr",
0145 "std::cout",
0146 "std::cerr",
0147 "edm::RunningAverage",
0148 "class edm::RunningAverage",
0149 "TVirtualMutex",
0150 "class TVirtualMutex",
0151 "boost::(anonymous namespace)::extents",
0152 "(anonymous namespace)::_1",
0153 "(anonymous namespace)::_2",
0154 "struct PyModuleDef",
0155 "::pybind11::class module_::module_def"};
0156
0157 for (auto &name : names)
0158 if (cname.substr(0, name.length()) == name)
0159 return true;
0160 return false;
0161 }
0162
0163 bool clangcms::support::isDataClass(const std::string &name) {
0164 CMS_SA_ALLOW static std::string iname("");
0165 if (iname.empty()) {
0166 clang::FileSystemOptions FSO;
0167 clang::FileManager FM(FSO);
0168 const char *lPath = std::getenv("LOCALRT");
0169 const char *rPath = std::getenv("CMSSW_RELEASE_BASE");
0170 if (lPath == nullptr || rPath == nullptr) {
0171 llvm::errs()
0172 << "\n\nThe scram runtime envorinment is not set.\nRun 'cmsenv' or 'eval `scram runtime -csh`'.\n\n\n";
0173 exit(1);
0174 }
0175 const std::string lname = std::string(lPath);
0176 const std::string rname = std::string(rPath);
0177 const std::string tname("/src/Utilities/StaticAnalyzers/scripts/bloom.bin");
0178 const std::string fname1 = lname + tname;
0179 const std::string fname2 = rname + tname;
0180 if (!(FM.getFile(fname1) || FM.getFile(fname2))) {
0181 llvm::errs() << "\n\nChecker cannot find bloom filter file" << fname1 << " or " << fname2 << "\n\n\n";
0182 exit(1);
0183 }
0184 if (FM.getFile(fname1))
0185 iname = fname1;
0186 else
0187 iname = fname2;
0188 }
0189
0190 CMS_SA_ALLOW static scaling_bloom_t *blmflt = new_scaling_bloom_from_file(CAPACITY, ERROR_RATE, iname.c_str());
0191
0192 if (scaling_bloom_check(blmflt, name.c_str(), name.length()) == 1)
0193 return true;
0194
0195 return false;
0196 }
0197
0198 bool clangcms::support::isInterestingLocation(const std::string &fname) {
0199 if (fname[0] == '<' && fname.find(".h") == std::string::npos)
0200 return false;
0201 if (fname.find("/test/") != std::string::npos)
0202 return false;
0203 return true;
0204 }
0205
0206 bool clangcms::support::isKnownThrUnsafeFunc(const std::string &fname) {
0207 static const std::vector<std::string> names = {"TGraph::Fit(const char *,",
0208 "TGraph2D::Fit(const char *,",
0209 "TH1::Fit(const char *,",
0210 "TMultiGraph::Fit(const char *,",
0211 "TTable::Fit(const char *,",
0212 "TTree::Fit(const char *,",
0213 "TTreePlayer::Fit(const char *,",
0214 "CLHEP::HepMatrix::determinant("};
0215 for (auto &name : names)
0216 if (fname.substr(0, name.length()) == name)
0217 return true;
0218 return false;
0219 }
0220
0221 void clangcms::support::writeLog(const std::string &ostring, const std::string &tfstring) {
0222 const char *pPath = std::getenv("LOCALRT");
0223 if (pPath == nullptr) {
0224 llvm::errs() << "\n\nThe scram runtime envorinment is not set.\nRun 'cmsenv' or 'eval `scram runtime -csh`'.\n\n\n";
0225 exit(1);
0226 }
0227
0228 std::string pname = std::string(pPath) + "/tmp/";
0229 const std::string tname = pname + tfstring;
0230
0231 std::fstream file;
0232 file.open(tname.c_str(), std::ios::out | std::ios::app);
0233 file << ostring << "\n";
0234 file.close();
0235
0236 return;
0237 }
0238
0239 void clangcms::support::fixAnonNS(std::string &name, const char *fname) {
0240 const std::string anon_ns = "(anonymous namespace)";
0241 if (name.substr(0, anon_ns.size()) == anon_ns) {
0242 const char *sname = "/src/";
0243 const char *filename = std::strstr(fname, sname);
0244 if (filename != nullptr)
0245 name = name.substr(0, anon_ns.size() - 1) + " in " + filename + ")" + name.substr(anon_ns.size());
0246 }
0247 return;
0248 }
0249
0250 bool clangcms::support::isStdAtomic(const clang::FieldDecl *fieldDecl) {
0251 if (!fieldDecl)
0252 return false;
0253
0254
0255 clang::QualType fieldType = fieldDecl->getType();
0256
0257
0258 fieldType = fieldType.getCanonicalType();
0259
0260
0261 if (const clang::RecordType *recordType = fieldType->getAs<clang::RecordType>()) {
0262 const clang::CXXRecordDecl *recordDecl = clang::dyn_cast<clang::CXXRecordDecl>(recordType->getDecl());
0263 if (!recordDecl)
0264 return false;
0265
0266
0267 if (const clang::ClassTemplateSpecializationDecl *specDecl =
0268 clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(recordDecl)) {
0269 const clang::TemplateDecl *templateDecl = specDecl->getSpecializedTemplate();
0270 if (!templateDecl)
0271 return false;
0272
0273
0274 const std::string templateName = templateDecl->getNameAsString();
0275 if (templateName == "atomic") {
0276
0277 const clang::NamespaceDecl *namespaceDecl =
0278 clang::dyn_cast<clang::NamespaceDecl>(templateDecl->getDeclContext());
0279 if (namespaceDecl && namespaceDecl->getNameAsString() == "std") {
0280 return true;
0281 }
0282 }
0283 }
0284 }
0285
0286 return false;
0287 }