1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" |
15 | #include "clang/Basic/Builtins.h" |
16 | #include "clang/Lex/Lexer.h" |
17 | |
18 | using namespace clang; |
19 | using namespace ento; |
20 | |
21 | const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const { |
22 | const Expr *Callee = CE->getCallee(); |
23 | SVal L = Pred->getSVal(Callee); |
24 | return L.getAsFunctionDecl(); |
25 | } |
26 | |
27 | StringRef CheckerContext::getCalleeName(const FunctionDecl *FunDecl) const { |
28 | if (!FunDecl) |
29 | return StringRef(); |
30 | IdentifierInfo *funI = FunDecl->getIdentifier(); |
31 | if (!funI) |
32 | return StringRef(); |
33 | return funI->getName(); |
34 | } |
35 | |
36 | StringRef CheckerContext::getDeclDescription(const Decl *D) { |
37 | if (isa<ObjCMethodDecl>(D) || isa<CXXMethodDecl>(D)) |
38 | return "method"; |
39 | if (isa<BlockDecl>(D)) |
40 | return "anonymous block"; |
41 | return "function"; |
42 | } |
43 | |
44 | bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD, |
45 | StringRef Name) { |
46 | |
47 | |
48 | |
49 | unsigned BId = FD->getBuiltinID(); |
50 | if (BId != 0) { |
51 | if (Name.empty()) |
52 | return true; |
53 | StringRef BName = FD->getASTContext().BuiltinInfo.getName(BId); |
54 | if (BName.find(Name) != StringRef::npos) |
55 | return true; |
56 | } |
57 | |
58 | const IdentifierInfo *II = FD->getIdentifier(); |
59 | |
60 | |
61 | if (!II) |
62 | return false; |
63 | |
64 | |
65 | |
66 | if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit()) |
67 | return false; |
68 | |
69 | |
70 | |
71 | |
72 | if (!FD->isInlined() && !FD->isExternallyVisible()) |
73 | return false; |
74 | |
75 | if (Name.empty()) |
76 | return true; |
77 | |
78 | StringRef FName = II->getName(); |
79 | if (FName.equals(Name)) |
80 | return true; |
81 | |
82 | if (FName.startswith("__inline") && (FName.find(Name) != StringRef::npos)) |
83 | return true; |
84 | |
85 | if (FName.startswith("__") && FName.endswith("_chk") && |
86 | FName.find(Name) != StringRef::npos) |
87 | return true; |
88 | |
89 | return false; |
90 | } |
91 | |
92 | StringRef CheckerContext::getMacroNameOrSpelling(SourceLocation &Loc) { |
93 | if (Loc.isMacroID()) |
94 | return Lexer::getImmediateMacroName(Loc, getSourceManager(), |
95 | getLangOpts()); |
96 | SmallVector<char, 16> buf; |
97 | return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOpts()); |
98 | } |
99 | |
100 | |
101 | static bool evalComparison(SVal LHSVal, BinaryOperatorKind ComparisonOp, |
102 | SVal RHSVal, ProgramStateRef State) { |
103 | if (LHSVal.isUnknownOrUndef()) |
104 | return false; |
105 | ProgramStateManager &Mgr = State->getStateManager(); |
106 | if (!LHSVal.getAs<NonLoc>()) { |
107 | LHSVal = Mgr.getStoreManager().getBinding(State->getStore(), |
108 | LHSVal.castAs<Loc>()); |
109 | if (LHSVal.isUnknownOrUndef() || !LHSVal.getAs<NonLoc>()) |
110 | return false; |
111 | } |
112 | |
113 | SValBuilder &Bldr = Mgr.getSValBuilder(); |
114 | SVal Eval = Bldr.evalBinOp(State, ComparisonOp, LHSVal, RHSVal, |
115 | Bldr.getConditionType()); |
116 | if (Eval.isUnknownOrUndef()) |
117 | return false; |
118 | ProgramStateRef StTrue, StFalse; |
119 | std::tie(StTrue, StFalse) = State->assume(Eval.castAs<DefinedSVal>()); |
120 | return StTrue && !StFalse; |
121 | } |
122 | |
123 | bool CheckerContext::isGreaterOrEqual(const Expr *E, unsigned long long Val) { |
124 | DefinedSVal V = getSValBuilder().makeIntVal(Val, getASTContext().LongLongTy); |
125 | return evalComparison(getSVal(E), BO_GE, V, getState()); |
126 | } |
127 | |
128 | bool CheckerContext::isNegative(const Expr *E) { |
129 | DefinedSVal V = getSValBuilder().makeIntVal(0, false); |
130 | return evalComparison(getSVal(E), BO_LT, V, getState()); |
131 | } |
132 | |