1 //== CheckerHelpers.h - 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 CheckerVisitor. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H 14 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H 15 16 #include "clang/AST/OperationKinds.h" 17 #include "clang/AST/Stmt.h" 18 #include "clang/Basic/OperatorKinds.h" 19 #include <optional> 20 #include <tuple> 21 22 namespace clang { 23 24 class Expr; 25 class VarDecl; 26 class QualType; 27 class Preprocessor; 28 29 namespace ento { 30 31 bool containsMacro(const Stmt *S); 32 bool containsEnum(const Stmt *S); 33 bool containsStaticLocal(const Stmt *S); 34 bool containsBuiltinOffsetOf(const Stmt *S); containsStmt(const Stmt * S)35template <class T> bool containsStmt(const Stmt *S) { 36 if (isa<T>(S)) 37 return true; 38 39 for (const Stmt *Child : S->children()) 40 if (Child && containsStmt<T>(Child)) 41 return true; 42 43 return false; 44 } 45 46 std::pair<const clang::VarDecl *, const clang::Expr *> 47 parseAssignment(const Stmt *S); 48 49 // Do not reorder! The getMostNullable method relies on the order. 50 // Optimization: Most pointers expected to be unspecified. When a symbol has an 51 // unspecified or nonnull type non of the rules would indicate any problem for 52 // that symbol. For this reason only nullable and contradicted nullability are 53 // stored for a symbol. When a symbol is already contradicted, it can not be 54 // casted back to nullable. 55 enum class Nullability : char { 56 Contradicted, // Tracked nullability is contradicted by an explicit cast. Do 57 // not report any nullability related issue for this symbol. 58 // This nullability is propagated aggressively to avoid false 59 // positive results. See the comment on getMostNullable method. 60 Nullable, 61 Unspecified, 62 Nonnull 63 }; 64 65 /// Get nullability annotation for a given type. 66 Nullability getNullabilityAnnotation(QualType Type); 67 68 /// Try to parse the value of a defined preprocessor macro. We can only parse 69 /// simple expressions that consist of an optional minus sign token and then a 70 /// token for an integer. If we cannot parse the value then std::nullopt is 71 /// returned. 72 std::optional<int> tryExpandAsInteger(StringRef Macro, const Preprocessor &PP); 73 74 class OperatorKind { 75 union { 76 BinaryOperatorKind Bin; 77 UnaryOperatorKind Un; 78 } Op; 79 bool IsBinary; 80 81 public: OperatorKind(BinaryOperatorKind Bin)82 explicit OperatorKind(BinaryOperatorKind Bin) : Op{Bin}, IsBinary{true} {} OperatorKind(UnaryOperatorKind Un)83 explicit OperatorKind(UnaryOperatorKind Un) : IsBinary{false} { Op.Un = Un; } IsBinaryOp()84 bool IsBinaryOp() const { return IsBinary; } 85 GetBinaryOpUnsafe()86 BinaryOperatorKind GetBinaryOpUnsafe() const { 87 assert(IsBinary && "cannot get binary operator - we have a unary operator"); 88 return Op.Bin; 89 } 90 GetBinaryOp()91 std::optional<BinaryOperatorKind> GetBinaryOp() const { 92 if (IsBinary) 93 return Op.Bin; 94 return {}; 95 } 96 GetUnaryOpUnsafe()97 UnaryOperatorKind GetUnaryOpUnsafe() const { 98 assert(!IsBinary && 99 "cannot get unary operator - we have a binary operator"); 100 return Op.Un; 101 } 102 GetUnaryOp()103 std::optional<UnaryOperatorKind> GetUnaryOp() const { 104 if (!IsBinary) 105 return Op.Un; 106 return {}; 107 } 108 }; 109 110 OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, 111 bool IsBinary); 112 113 } // namespace ento 114 115 } // namespace clang 116 117 #endif 118