1//===---- CheckerHelpers.cpp - Helper functions for checkers ----*- 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-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file defines several static functions for use in checkers. 10// 11//===----------------------------------------------------------------------===// 12 13#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" 14#include "clang/AST/Decl.h" 15#include "clang/AST/Expr.h" 16 17namespace clang { 18 19namespace ento { 20 21// Recursively find any substatements containing macros 22bool containsMacro(const Stmt *S) { 23 if (S->getBeginLoc().isMacroID()) 24 return true; 25 26 if (S->getEndLoc().isMacroID()) 27 return true; 28 29 for (const Stmt *Child : S->children()) 30 if (Child && containsMacro(Child)) 31 return true; 32 33 return false; 34} 35 36// Recursively find any substatements containing enum constants 37bool containsEnum(const Stmt *S) { 38 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S); 39 40 if (DR && isa<EnumConstantDecl>(DR->getDecl())) 41 return true; 42 43 for (const Stmt *Child : S->children()) 44 if (Child && containsEnum(Child)) 45 return true; 46 47 return false; 48} 49 50// Recursively find any substatements containing static vars 51bool containsStaticLocal(const Stmt *S) { 52 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S); 53 54 if (DR) 55 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) 56 if (VD->isStaticLocal()) 57 return true; 58 59 for (const Stmt *Child : S->children()) 60 if (Child && containsStaticLocal(Child)) 61 return true; 62 63 return false; 64} 65 66// Recursively find any substatements containing __builtin_offsetof 67bool containsBuiltinOffsetOf(const Stmt *S) { 68 if (isa<OffsetOfExpr>(S)) 69 return true; 70 71 for (const Stmt *Child : S->children()) 72 if (Child && containsBuiltinOffsetOf(Child)) 73 return true; 74 75 return false; 76} 77 78// Extract lhs and rhs from assignment statement 79std::pair<const clang::VarDecl *, const clang::Expr *> 80parseAssignment(const Stmt *S) { 81 const VarDecl *VD = nullptr; 82 const Expr *RHS = nullptr; 83 84 if (auto Assign = dyn_cast_or_null<BinaryOperator>(S)) { 85 if (Assign->isAssignmentOp()) { 86 // Ordinary assignment 87 RHS = Assign->getRHS(); 88 if (auto DE = dyn_cast_or_null<DeclRefExpr>(Assign->getLHS())) 89 VD = dyn_cast_or_null<VarDecl>(DE->getDecl()); 90 } 91 } else if (auto PD = dyn_cast_or_null<DeclStmt>(S)) { 92 // Initialization 93 assert(PD->isSingleDecl() && "We process decls one by one"); 94 VD = cast<VarDecl>(PD->getSingleDecl()); 95 RHS = VD->getAnyInitializer(); 96 } 97 98 return std::make_pair(VD, RHS); 99} 100 101Nullability getNullabilityAnnotation(QualType Type) { 102 const auto *AttrType = Type->getAs<AttributedType>(); 103 if (!AttrType) 104 return Nullability::Unspecified; 105 if (AttrType->getAttrKind() == attr::TypeNullable) 106 return Nullability::Nullable; 107 else if (AttrType->getAttrKind() == attr::TypeNonNull) 108 return Nullability::Nonnull; 109 return Nullability::Unspecified; 110} 111 112 113} // end namespace ento 114} // end namespace clang 115