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 17 namespace clang { 18 19 namespace ento { 20 21 // Recursively find any substatements containing macros 22 bool 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 37 bool 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 51 bool 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 67 bool 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 79 std::pair<const clang::VarDecl *, const clang::Expr *> 80 parseAssignment(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 101 Nullability 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