diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 13:58:24 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 14:11:53 +0300 |
commit | 11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch) | |
tree | fabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp | |
parent | 9685917341315774aad5733b1793b1e533a88bbb (diff) | |
download | ydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz |
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp')
-rw-r--r-- | contrib/libs/clang16/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/contrib/libs/clang16/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/contrib/libs/clang16/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp new file mode 100644 index 0000000000..0fa3d60439 --- /dev/null +++ b/contrib/libs/clang16/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -0,0 +1,125 @@ +//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that +// checks for assigning undefined values. +// +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" + +using namespace clang; +using namespace ento; + +namespace { +class UndefinedAssignmentChecker + : public Checker<check::Bind> { + mutable std::unique_ptr<BugType> BT; + +public: + void checkBind(SVal location, SVal val, const Stmt *S, + CheckerContext &C) const; +}; +} + +void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, + const Stmt *StoreE, + CheckerContext &C) const { + if (!val.isUndef()) + return; + + // Do not report assignments of uninitialized values inside swap functions. + // This should allow to swap partially uninitialized structs + // (radar://14129997) + if (const FunctionDecl *EnclosingFunctionDecl = + dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl())) + if (C.getCalleeName(EnclosingFunctionDecl) == "swap") + return; + + ExplodedNode *N = C.generateErrorNode(); + + if (!N) + return; + + static const char *const DefaultMsg = + "Assigned value is garbage or undefined"; + if (!BT) + BT.reset(new BuiltinBug(this, DefaultMsg)); + + // Generate a report for this bug. + llvm::SmallString<128> Str; + llvm::raw_svector_ostream OS(Str); + + const Expr *ex = nullptr; + + while (StoreE) { + if (const UnaryOperator *U = dyn_cast<UnaryOperator>(StoreE)) { + OS << "The expression is an uninitialized value. " + "The computed value will also be garbage"; + + ex = U->getSubExpr(); + break; + } + + if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { + if (B->isCompoundAssignmentOp()) { + if (C.getSVal(B->getLHS()).isUndef()) { + OS << "The left expression of the compound assignment is an " + "uninitialized value. The computed value will also be garbage"; + ex = B->getLHS(); + break; + } + } + + ex = B->getRHS(); + break; + } + + if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) { + const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); + ex = VD->getInit(); + } + + if (const auto *CD = + dyn_cast<CXXConstructorDecl>(C.getStackFrame()->getDecl())) { + if (CD->isImplicit()) { + for (auto *I : CD->inits()) { + if (I->getInit()->IgnoreImpCasts() == StoreE) { + OS << "Value assigned to field '" << I->getMember()->getName() + << "' in implicit constructor is garbage or undefined"; + break; + } + } + } + } + + break; + } + + if (OS.str().empty()) + OS << DefaultMsg; + + auto R = std::make_unique<PathSensitiveBugReport>(*BT, OS.str(), N); + if (ex) { + R->addRange(ex->getSourceRange()); + bugreporter::trackExpressionValue(N, ex, *R); + } + C.emitReport(std::move(R)); +} + +void ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) { + mgr.registerChecker<UndefinedAssignmentChecker>(); +} + +bool ento::shouldRegisterUndefinedAssignmentChecker(const CheckerManager &mgr) { + return true; +} |