Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:50

0001 //== ConstCastChecker.cpp - Checks for const_cast<> --------------*- C++ -*--==//
0002 //
0003 // by Thomas Hauth [ Thomas.Hauth@cern.ch ]
0004 //
0005 //===----------------------------------------------------------------------===//
0006 
0007 #include <clang/AST/Attr.h>
0008 #include <clang/AST/ExprCXX.h>
0009 #include <clang/AST/ParentMap.h>
0010 
0011 #include <memory>
0012 
0013 #include "ConstCastChecker.h"
0014 #include "CmsSupport.h"
0015 
0016 using namespace clang;
0017 using namespace clang::ento;
0018 using namespace llvm;
0019 
0020 namespace clangcms {
0021 
0022   void ConstCastChecker::checkPreStmt(const clang::CXXConstCastExpr *CE, clang::ento::CheckerContext &C) const {
0023     auto P = C.getCurrentAnalysisDeclContext()->getParentMap().getParent(CE);
0024     while (P && !(isa<AttributedStmt>(P) || isa<DeclStmt>(P)) &&
0025            C.getCurrentAnalysisDeclContext()->getParentMap().hasParent(P)) {
0026       P = C.getCurrentAnalysisDeclContext()->getParentMap().getParent(P);
0027     }
0028     if (P && isa<AttributedStmt>(P)) {
0029       const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(P);
0030       if (AS && (hasSpecificAttr<CMSSaAllowAttr>(AS->getAttrs()) || hasSpecificAttr<CMSThreadSafeAttr>(AS->getAttrs())))
0031         return;
0032     }
0033     if (P && isa<DeclStmt>(P)) {
0034       const DeclStmt *DS = dyn_cast_or_null<DeclStmt>(P);
0035       if (DS) {
0036         for (auto D : DS->decls()) {
0037           if (hasSpecificAttr<CMSSaAllowAttr>(D->getAttrs()) || hasSpecificAttr<CMSThreadSafeAttr>(D->getAttrs())) {
0038             return;
0039           }
0040         }
0041       }
0042     }
0043 
0044     const Expr *SE = CE->getSubExprAsWritten();
0045     const CXXRecordDecl *CRD = nullptr;
0046     std::string cname;
0047     if (SE->getType()->isPointerType())
0048       CRD = SE->getType()->getPointeeCXXRecordDecl();
0049     else
0050       CRD = SE->getType()->getAsCXXRecordDecl();
0051     if (CRD)
0052       cname = CRD->getQualifiedNameAsString();
0053     if (clang::ento::ExplodedNode *errorNode = C.generateErrorNode()) {
0054       if (!BT)
0055         BT = std::make_unique<clang::ento::BugType>(this, "const_cast used on pointer to class", "ConstThreadSafety");
0056       std::string buf;
0057       llvm::raw_string_ostream os(buf);
0058       os << "const_cast was used, this may result in thread-unsafe code.";
0059       std::unique_ptr<clang::ento::PathSensitiveBugReport> PSBR =
0060           std::make_unique<clang::ento::PathSensitiveBugReport>(*BT, llvm::StringRef(os.str()), errorNode);
0061       PSBR->addRange(CE->getSourceRange());
0062       if (!m_exception.reportConstCast(*PSBR, C))
0063         return;
0064       C.emitReport(std::move(PSBR));
0065       if (cname.empty())
0066         return;
0067       std::string tname = "constcast-checker.txt.unsorted";
0068       std::string tolog = "flagged class '" + cname + "' const_cast used ";
0069       support::writeLog(tolog, tname);
0070     }
0071   }
0072 
0073 }  // namespace clangcms