brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.4 KiB · 02fd737 Raw
74 lines · cpp
1//===-- ChromiumCheckModel.cpp ----------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h"10#include "clang/AST/Decl.h"11#include "clang/AST/DeclCXX.h"12#include "llvm/ADT/DenseSet.h"13 14namespace clang {15namespace dataflow {16 17/// Determines whether `D` is one of the methods used to implement Chromium's18/// `CHECK` macros. Populates `CheckDecls`, if empty.19static bool20isCheckLikeMethod(llvm::SmallDenseSet<const CXXMethodDecl *> &CheckDecls,21                  const CXXMethodDecl &D) {22  // All of the methods of interest are static, so avoid any lookup for23  // non-static methods (the common case).24  if (!D.isStatic())25    return false;26 27  if (CheckDecls.empty()) {28    // Attempt to initialize `CheckDecls` with the methods in class29    // `CheckError`.30    const CXXRecordDecl *ParentClass = D.getParent();31    if (ParentClass == nullptr || !ParentClass->getDeclName().isIdentifier() ||32        ParentClass->getName() != "CheckError")33      return false;34 35    // Check whether namespace is "logging".36    const auto *N =37        dyn_cast_or_null<NamespaceDecl>(ParentClass->getDeclContext());38    if (N == nullptr || !N->getDeclName().isIdentifier() ||39        N->getName() != "logging")40      return false;41 42    // Check whether "logging" is a top-level namespace.43    if (N->getParent() == nullptr || !N->getParent()->isTranslationUnit())44      return false;45 46    for (const CXXMethodDecl *M : ParentClass->methods())47      if (M->getDeclName().isIdentifier() && M->getName().ends_with("Check"))48        CheckDecls.insert(M);49  }50 51  return CheckDecls.contains(&D);52}53 54bool ChromiumCheckModel::transfer(const CFGElement &Element, Environment &Env) {55  auto CS = Element.getAs<CFGStmt>();56  if (!CS)57    return false;58  auto Stmt = CS->getStmt();59  if (const auto *Call = dyn_cast<CallExpr>(Stmt)) {60    if (const auto *M =61            dyn_cast_or_null<CXXMethodDecl>(Call->getDirectCallee())) {62      if (isCheckLikeMethod(CheckDecls, *M)) {63        // Mark this branch as unreachable.64        Env.assume(Env.arena().makeLiteral(false));65        return true;66      }67    }68  }69  return false;70}71 72} // namespace dataflow73} // namespace clang74