25#include "llvm/ADT/SmallString.h"
26#include "llvm/Support/raw_ostream.h"
40class NSErrorMethodChecker
41 :
public Checker< check::ASTDecl<ObjCMethodDecl> > {
45 NSErrorMethodChecker() =
default;
55 if (!
D->isThisDeclarationADefinition())
57 if (!
D->getReturnType()->isVoidType())
63 bool hasNSError =
false;
64 for (
const auto *I :
D->parameters()) {
72 const char *err =
"Method accepting NSError** "
73 "should have a non-void return value to indicate whether or not an "
78 "Coding conventions (Apple)", err, L);
87class CFErrorFunctionChecker
88 :
public Checker< check::ASTDecl<FunctionDecl> > {
92 CFErrorFunctionChecker() : II(nullptr) {}
100 if (isa<CXXConstructorDecl>(
D))
108void CFErrorFunctionChecker::checkASTDecl(
const FunctionDecl *
D,
111 if (!
D->doesThisDeclarationHaveABody())
113 if (!
D->getReturnType()->isVoidType())
121 bool hasCFError =
false;
122 for (
auto *I :
D->parameters()) {
130 const char *err =
"Function accepting CFErrorRef* "
131 "should have a non-void return value to indicate whether or not an "
136 "Coding conventions (Apple)", err, L);
145class NSOrCFErrorDerefChecker
147 check::Event<ImplicitNullDerefEvent>> {
153 "Coding conventions (Apple)"};
155 "Coding conventions (Apple)"};
157 StringRef
getDebugTag()
const override {
return "NSOrCFErrorDerefChecker"; }
159 void checkLocation(
SVal loc,
bool isLoad,
const Stmt *S,
172 if (
const unsigned *attachedFlags = state->get<
T>(sym))
173 return *attachedFlags;
181 C.addTransition(state->set<
T>(sym,
true));
189 if (
const auto *StackSpace =
191 if (StackSpace->getStackFrame() == SFC)
192 return VR->getValueType();
198void NSOrCFErrorDerefChecker::checkLocation(
SVal loc,
bool isLoad,
203 if (loc.
isUndef() || !isa<Loc>(loc))
222 CFErrorII = &Ctx.
Idents.
get(
"CFErrorRef");
224 if (NSError.isEnabled() &&
IsNSError(parmT, NSErrorII)) {
225 setFlag<NSErrorOut>(state, state->getSVal(loc.
castAs<
Loc>()),
C);
229 if (CFError.isEnabled() &&
IsCFError(parmT, CFErrorII)) {
230 setFlag<CFErrorOut>(state, state->getSVal(loc.
castAs<
Loc>()),
C);
239 SVal loc =
event.Location;
243 bool isNSError = hasFlag<NSErrorOut>(loc, state);
244 bool isCFError =
false;
246 isCFError = hasFlag<CFErrorOut>(loc, state);
248 if (!(isNSError || isCFError))
253 llvm::raw_svector_ostream os(Buf);
255 os <<
"Potential null dereference. According to coding standards ";
257 ?
"in 'Creating and Returning NSError Objects' the parameter"
258 :
"documented in CoreFoundation/CFError.h the parameter");
260 os <<
" may be null";
262 const BugType &BT = isNSError ? NSError : CFError;
264 std::make_unique<PathSensitiveBugReport>(BT, os.str(), event.
SinkNode));
283 return II == ID->getIdentifier();
290 if (!PPT)
return false;
293 if (!TT)
return false;
304#define REGISTER_CHECKER(NAME, ADDITIONAL_PART) \
305 void ento::register##NAME##Checker(CheckerManager &Mgr) { \
306 Mgr.getChecker<NSOrCFErrorDerefChecker>()->NAME.enable(Mgr); \
307 Mgr.registerChecker<ADDITIONAL_PART>(); \
310 bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \
#define REGISTER_CHECKER(NAME, ADDITIONAL_PART)
static bool hasFlag(SVal val, ProgramStateRef state)
static bool IsCFError(QualType T, IdentifierInfo *II)
static void setFlag(ProgramStateRef state, SVal val, CheckerContext &C)
static QualType parameterTypeFromSVal(SVal val, CheckerContext &C)
static bool IsNSError(QualType T, IdentifierInfo *II)
static bool hasReservedReturnType(const FunctionDecl *D)
llvm::ImmutableMap< SymbolRef, unsigned > ErrorOutFlag
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
ASTContext & getASTContext() const LLVM_READONLY
Represents a function declaration or definition.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents an ObjC class declaration.
ObjCMethodDecl - Represents an instance or class method declaration.
Represents a pointer to an Objective C object.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
virtual StringRef getDebugTag() const =0
The description of this program point which will be dumped for debugging purposes.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
const T * getAs() const
Member-template getAs<specific type>'.
TypedefNameDecl * getDecl() const
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerFrontend *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
Checker families (where a single backend class implements multiple related frontends) should derive f...
Trivial convenience class for the common case when a certain checker frontend always uses the same bu...
Simple checker classes that implement one frontend (i.e.
MemRegion - The root abstract class for all memory regions.
const RegionTy * getAs() const
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
We dereferenced a location that may be null.