File indexing completed on 2024-04-06 12:31:50
0001
0002
0003
0004
0005
0006
0007
0008 #include <clang/AST/ExprCXX.h>
0009 #include <clang/AST/Attr.h>
0010 #include <clang/AST/ParentMap.h>
0011 #include <clang/AST/Stmt.h>
0012
0013 #include <memory>
0014
0015 #include "ConstCastAwayChecker.h"
0016 #include "CmsSupport.h"
0017
0018 using namespace clang;
0019 using namespace clang::ento;
0020 using namespace llvm;
0021
0022 namespace clangcms {
0023
0024 void ConstCastAwayChecker::checkPreStmt(const clang::ExplicitCastExpr *CE, clang::ento::CheckerContext &C) const {
0025 if (!(clang::CStyleCastExpr::classof(CE) || clang::CXXConstCastExpr::classof(CE)))
0026 return;
0027 auto P = C.getCurrentAnalysisDeclContext()->getParentMap().getParent(CE);
0028 while (P && !(isa<AttributedStmt>(P) || isa<DeclStmt>(P)) &&
0029 C.getCurrentAnalysisDeclContext()->getParentMap().hasParent(P)) {
0030 P = C.getCurrentAnalysisDeclContext()->getParentMap().getParent(P);
0031 }
0032 if (P && isa<AttributedStmt>(P)) {
0033 const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(P);
0034 if (AS && (hasSpecificAttr<CMSSaAllowAttr>(AS->getAttrs()) || hasSpecificAttr<CMSThreadSafeAttr>(AS->getAttrs())))
0035 return;
0036 }
0037 if (P && isa<DeclStmt>(P)) {
0038 const DeclStmt *DS = dyn_cast_or_null<DeclStmt>(P);
0039 if (DS) {
0040 for (auto D : DS->decls()) {
0041 if (hasSpecificAttr<CMSSaAllowAttr>(D->getAttrs()) || hasSpecificAttr<CMSThreadSafeAttr>(D->getAttrs())) {
0042 return;
0043 }
0044 }
0045 }
0046 }
0047
0048 const Expr *SE = CE->getSubExpr();
0049 const CXXRecordDecl *CRD = nullptr;
0050 std::string cname;
0051 if (SE->getType()->isPointerType())
0052 CRD = SE->getType()->getPointeeCXXRecordDecl();
0053 else
0054 CRD = SE->getType()->getAsCXXRecordDecl();
0055
0056 if (CRD)
0057 cname = CRD->getQualifiedNameAsString();
0058
0059 clang::ASTContext &Ctx = C.getASTContext();
0060 clang::QualType OrigTy = Ctx.getCanonicalType(SE->getType());
0061 clang::QualType ToTy = Ctx.getCanonicalType(CE->getType());
0062
0063 if (support::isConst(OrigTy) && !support::isConst(ToTy)) {
0064 if (clang::ento::ExplodedNode *errorNode = C.generateErrorNode()) {
0065 if (!BT)
0066 BT = std::make_unique<clang::ento::BugType>(this, "const cast away", "ConstThreadSafety");
0067 std::string buf;
0068 llvm::raw_string_ostream os(buf);
0069 os << "const qualifier was removed via a cast, this may result in thread-unsafe code.";
0070 std::unique_ptr<clang::ento::PathSensitiveBugReport> PSBR =
0071 std::make_unique<clang::ento::PathSensitiveBugReport>(*BT, llvm::StringRef(os.str()), errorNode);
0072 PSBR->addRange(CE->getSourceRange());
0073 if (!m_exception.reportConstCastAway(*PSBR, C))
0074 return;
0075 C.emitReport(std::move(PSBR));
0076 if (cname.empty())
0077 return;
0078 std::string tname = "constcastaway-checker.txt.unsorted";
0079 std::string tolog = "flagged class '" + cname + "' const qualifier cast away";
0080 support::writeLog(tolog, tname);
0081 }
0082 }
0083 }
0084
0085 }