Path: blob/main/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
35266 views
//=== CXXSelfAssignmentChecker.cpp -----------------------------*- C++ -*--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines CXXSelfAssignmentChecker, which tests all custom defined9// copy and move assignment operators for the case of self assignment, thus10// where the parameter refers to the same location where the this pointer11// points to. The checker itself does not do any checks at all, but it12// causes the analyzer to check every copy and move assignment operator twice:13// once for when 'this' aliases with the parameter and once for when it may not.14// It is the task of the other enabled checkers to find the bugs in these two15// different cases.16//17//===----------------------------------------------------------------------===//1819#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"20#include "clang/StaticAnalyzer/Core/Checker.h"21#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"2223using namespace clang;24using namespace ento;2526namespace {2728class CXXSelfAssignmentChecker : public Checker<check::BeginFunction> {29public:30CXXSelfAssignmentChecker();31void checkBeginFunction(CheckerContext &C) const;32};33}3435CXXSelfAssignmentChecker::CXXSelfAssignmentChecker() {}3637void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const {38if (!C.inTopFrame())39return;40const auto *LCtx = C.getLocationContext();41const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());42if (!MD)43return;44if (!MD->isCopyAssignmentOperator() && !MD->isMoveAssignmentOperator())45return;46auto &State = C.getState();47auto &SVB = C.getSValBuilder();48auto ThisVal =49State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));50auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx));51auto ParamVal = State->getSVal(Param);5253ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx);54const NoteTag *SelfAssignTag =55C.getNoteTag([MD](PathSensitiveBugReport &BR) -> std::string {56SmallString<256> Msg;57llvm::raw_svector_ostream Out(Msg);58Out << "Assuming " << MD->getParamDecl(0)->getName() << " == *this";59return std::string(Out.str());60});61C.addTransition(SelfAssignState, SelfAssignTag);6263ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, LCtx);64const NoteTag *NonSelfAssignTag =65C.getNoteTag([MD](PathSensitiveBugReport &BR) -> std::string {66SmallString<256> Msg;67llvm::raw_svector_ostream Out(Msg);68Out << "Assuming " << MD->getParamDecl(0)->getName() << " != *this";69return std::string(Out.str());70});71C.addTransition(NonSelfAssignState, NonSelfAssignTag);72}7374void ento::registerCXXSelfAssignmentChecker(CheckerManager &Mgr) {75Mgr.registerChecker<CXXSelfAssignmentChecker>();76}7778bool ento::shouldRegisterCXXSelfAssignmentChecker(const CheckerManager &mgr) {79return true;80}818283