181ad6265SDimitry Andric //===-- ChromiumCheckModel.cpp ----------------------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "clang/Analysis/FlowSensitive/Models/ChromiumCheckModel.h" 1081ad6265SDimitry Andric #include "clang/AST/Decl.h" 1181ad6265SDimitry Andric #include "clang/AST/DeclCXX.h" 1281ad6265SDimitry Andric #include "llvm/ADT/DenseSet.h" 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric namespace clang { 1581ad6265SDimitry Andric namespace dataflow { 1681ad6265SDimitry Andric 1781ad6265SDimitry Andric /// Determines whether `D` is one of the methods used to implement Chromium's 1881ad6265SDimitry Andric /// `CHECK` macros. Populates `CheckDecls`, if empty. isCheckLikeMethod(llvm::SmallDenseSet<const CXXMethodDecl * > & CheckDecls,const CXXMethodDecl & D)1981ad6265SDimitry Andricbool isCheckLikeMethod(llvm::SmallDenseSet<const CXXMethodDecl *> &CheckDecls, 2081ad6265SDimitry Andric const CXXMethodDecl &D) { 2181ad6265SDimitry Andric // All of the methods of interest are static, so avoid any lookup for 2281ad6265SDimitry Andric // non-static methods (the common case). 2381ad6265SDimitry Andric if (!D.isStatic()) 2481ad6265SDimitry Andric return false; 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric if (CheckDecls.empty()) { 2781ad6265SDimitry Andric // Attempt to initialize `CheckDecls` with the methods in class 2881ad6265SDimitry Andric // `CheckError`. 2981ad6265SDimitry Andric const CXXRecordDecl *ParentClass = D.getParent(); 3081ad6265SDimitry Andric if (ParentClass == nullptr || !ParentClass->getDeclName().isIdentifier() || 3181ad6265SDimitry Andric ParentClass->getName() != "CheckError") 3281ad6265SDimitry Andric return false; 3381ad6265SDimitry Andric 3481ad6265SDimitry Andric // Check whether namespace is "logging". 3581ad6265SDimitry Andric const auto *N = 3681ad6265SDimitry Andric dyn_cast_or_null<NamespaceDecl>(ParentClass->getDeclContext()); 3781ad6265SDimitry Andric if (N == nullptr || !N->getDeclName().isIdentifier() || 3881ad6265SDimitry Andric N->getName() != "logging") 3981ad6265SDimitry Andric return false; 4081ad6265SDimitry Andric 4181ad6265SDimitry Andric // Check whether "logging" is a top-level namespace. 4281ad6265SDimitry Andric if (N->getParent() == nullptr || !N->getParent()->isTranslationUnit()) 4381ad6265SDimitry Andric return false; 4481ad6265SDimitry Andric 4581ad6265SDimitry Andric for (const CXXMethodDecl *M : ParentClass->methods()) 46*5f757f3fSDimitry Andric if (M->getDeclName().isIdentifier() && M->getName().ends_with("Check")) 4781ad6265SDimitry Andric CheckDecls.insert(M); 4881ad6265SDimitry Andric } 4981ad6265SDimitry Andric 5081ad6265SDimitry Andric return CheckDecls.contains(&D); 5181ad6265SDimitry Andric } 5281ad6265SDimitry Andric transfer(const CFGElement & Element,Environment & Env)5306c3fb27SDimitry Andricbool ChromiumCheckModel::transfer(const CFGElement &Element, Environment &Env) { 5406c3fb27SDimitry Andric auto CS = Element.getAs<CFGStmt>(); 55bdd1243dSDimitry Andric if (!CS) 56bdd1243dSDimitry Andric return false; 57bdd1243dSDimitry Andric auto Stmt = CS->getStmt(); 5881ad6265SDimitry Andric if (const auto *Call = dyn_cast<CallExpr>(Stmt)) { 5981ad6265SDimitry Andric if (const auto *M = dyn_cast<CXXMethodDecl>(Call->getDirectCallee())) { 6081ad6265SDimitry Andric if (isCheckLikeMethod(CheckDecls, *M)) { 6181ad6265SDimitry Andric // Mark this branch as unreachable. 62*5f757f3fSDimitry Andric Env.assume(Env.arena().makeLiteral(false)); 6381ad6265SDimitry Andric return true; 6481ad6265SDimitry Andric } 6581ad6265SDimitry Andric } 6681ad6265SDimitry Andric } 6781ad6265SDimitry Andric return false; 6881ad6265SDimitry Andric } 6981ad6265SDimitry Andric 7081ad6265SDimitry Andric } // namespace dataflow 7181ad6265SDimitry Andric } // namespace clang 72