26 #include "llvm/ADT/SmallString.h" 27 #include "llvm/Support/raw_ostream.h" 29 using namespace clang;
40 class NSErrorMethodChecker
41 :
public Checker< check::ASTDecl<ObjCMethodDecl> > {
45 NSErrorMethodChecker() : II(nullptr) {}
63 bool hasNSError =
false;
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);
87 class CFErrorFunctionChecker
88 :
public Checker< check::ASTDecl<FunctionDecl> > {
92 CFErrorFunctionChecker() : II(nullptr) {}
99 void CFErrorFunctionChecker::checkASTDecl(
const FunctionDecl *D,
110 bool hasCFError =
false;
119 const char *err =
"Function accepting CFErrorRef* " 120 "should have a non-void return value to indicate whether or not an " 124 BR.
EmitBasicReport(D,
this,
"Bad return type when passing CFErrorRef*",
125 "Coding conventions (Apple)", err, L);
135 class NSErrorDerefBug :
public BugType {
138 :
BugType(Checker,
"NSError** null dereference",
139 "Coding conventions (Apple)") {}
142 class CFErrorDerefBug :
public BugType {
145 :
BugType(Checker,
"CFErrorRef* null dereference",
146 "Coding conventions (Apple)") {}
152 class NSOrCFErrorDerefChecker
153 :
public Checker< check::Location,
154 check::Event<ImplicitNullDerefEvent> > {
156 mutable std::unique_ptr<NSErrorDerefBug> NSBT;
157 mutable std::unique_ptr<CFErrorDerefBug> CFBT;
159 bool ShouldCheckNSError, ShouldCheckCFError;
160 NSOrCFErrorDerefChecker() : NSErrorII(nullptr), CFErrorII(nullptr),
161 ShouldCheckNSError(0), ShouldCheckCFError(0) { }
163 void checkLocation(
SVal loc,
bool isLoad,
const Stmt *S,
173 template <
typename T>
176 if (
const unsigned *attachedFlags = state->get<T>(sym))
177 return *attachedFlags;
181 template <
typename T>
194 stackReg = dyn_cast<StackArgumentsSpaceRegion>(VR->getMemorySpace()))
195 if (stackReg->getStackFrame() == SFC)
196 return VR->getValueType();
202 void NSOrCFErrorDerefChecker::checkLocation(
SVal loc,
bool isLoad,
226 CFErrorII = &Ctx.
Idents.
get(
"CFErrorRef");
228 if (ShouldCheckNSError &&
IsNSError(parmT, NSErrorII)) {
233 if (ShouldCheckCFError &&
IsCFError(parmT, CFErrorII)) {
243 SVal loc =
event.Location;
247 bool isNSError = hasFlag<NSErrorOut>(loc,
state);
248 bool isCFError =
false;
250 isCFError = hasFlag<CFErrorOut>(loc,
state);
252 if (!(isNSError || isCFError))
257 llvm::raw_svector_ostream os(Buf);
259 os <<
"Potential null dereference. According to coding standards ";
261 ?
"in 'Creating and Returning NSError Objects' the parameter" 262 :
"documented in CoreFoundation/CFError.h the parameter");
264 os <<
" may be null";
269 NSBT.reset(
new NSErrorDerefBug(
this));
274 CFBT.reset(
new CFErrorDerefBug(
this));
277 BR.
emitReport(llvm::make_unique<BugReport>(*bug, os.str(),
event.SinkNode));
303 if (!PPT)
return false;
306 if (!TT)
return false;
313 NSOrCFErrorDerefChecker *checker =
315 checker->ShouldCheckNSError =
true;
320 NSOrCFErrorDerefChecker *checker =
322 checker->ShouldCheckCFError =
true;
Represents a function declaration or definition.
bool isThisDeclarationADefinition() const
Returns whether this specific method is a definition.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
Stmt - This represents one statement.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
static bool IsCFError(QualType T, IdentifierInfo *II)
QualType getReturnType() const
const T * getAs() const
Member-template getAs<specific type>'.
ObjCMethodDecl - Represents an instance or class method declaration.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
ArrayRef< ParmVarDecl * > parameters() const
void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
llvm::ImmutableMap< SymbolRef, unsigned > ErrorOutFlag
Represents an ObjC class declaration.
QualType getReturnType() const
We dereferenced a location that may be null.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
const RegionTy * getAs() const
static void setFlag(ProgramStateRef state, SVal val, CheckerContext &C)
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
CHECKER * registerChecker(AT... Args)
Used to register checkers.
BugReporter is a utility class for generating PathDiagnostics for analysis.
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy...
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ASTContext & getASTContext() const LLVM_READONLY
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
static bool hasFlag(SVal val, ProgramStateRef state)
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
Represents a pointer to an Objective C object.
const StackFrameContext * getStackFrame() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
const ProgramStateRef & getState() const
TypedefNameDecl * getDecl() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
SourceManager & getSourceManager()
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
static bool IsNSError(QualType T, IdentifierInfo *II)
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
static QualType parameterTypeFromSVal(SVal val, CheckerContext &C)
ArrayRef< ParmVarDecl * > parameters() const