;
44classAPIMisuse :
public BugType{
46APIMisuse(
const CheckerBase*checker,
const char*name)
57 returnID->getIdentifier()->getName();
73 boolIncludeSuperclasses =
true) {
74 staticllvm::StringMap<FoundationClass> Classes;
75 if(Classes.empty()) {
86 FoundationClassresult = Classes.lookup(ID->getIdentifier()->getName());
87 if(result ==
FC_None&& IncludeSuperclasses)
99classNilArgChecker :
public Checker<check::PreObjCMessage,
100check::PostStmt<ObjCDictionaryLiteral>,
101check::PostStmt<ObjCArrayLiteral>,
102EventDispatcher<ImplicitNullDerefEvent>> {
103 mutablestd::unique_ptr<APIMisuse> BT;
105 mutablellvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors;
106 mutable SelectorArrayWithObjectSel;
108 mutable SelectorInsertObjectAtIndexSel;
109 mutable SelectorReplaceObjectAtIndexWithObjectSel;
110 mutable SelectorSetObjectAtIndexedSubscriptSel;
111 mutable SelectorArrayByAddingObjectSel;
112 mutable SelectorDictionaryWithObjectForKeySel;
113 mutable SelectorSetObjectForKeySel;
114 mutable SelectorSetObjectForKeyedSubscriptSel;
115 mutable SelectorRemoveObjectForKeySel;
132voidNilArgChecker::warnIfNilExpr(
const Expr*
E,
135 autoLocation =
C.getSVal(
E).getAs<
Loc>();
139 auto[
NonNull,
Null] =
C.getState()->assume(*Location);
152 if(
ExplodedNode*N =
C.generateSink(Null,
C.getPredecessor())) {
153dispatchEvent({*Location,
false, N, &
C.getBugReporter(),
164 boolCanBeSubscript)
const{
167 if(!State->isNull(msg.
getArgSVal(Arg)).isConstrainedTrue())
177llvm::raw_svector_ostream os(sbuf);
182os <<
"Array element cannot be nil";
185os <<
"Value stored into '";
192llvm_unreachable(
"Missing foundation class for the subscript expr");
197os <<
"Value argument ";
200os <<
"Key argument ";
204os <<
"' cannot be nil";
208os <<
"' cannot be nil";
223BT.reset(
newAPIMisuse(
this,
"nil argument"));
225 autoR = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
226R->addRange(
Range);
228 C.emitReport(std::move(R));
231voidNilArgChecker::checkPreObjCMessage(
const ObjCMethodCall&msg,
239 static const unsignedInvalidArgIndex =
UINT_MAX;
240 unsignedArg = InvalidArgIndex;
241 boolCanBeSubscript =
false;
246 if(S.isUnarySelector())
249 if(StringSelectors.empty()) {
264StringSelectors[KnownSel] = 0;
266 autoI = StringSelectors.find(S);
267 if(I == StringSelectors.end())
273 if(S.isUnarySelector())
276 if(ArrayWithObjectSel.isNull()) {
280InsertObjectAtIndexSel =
282ReplaceObjectAtIndexWithObjectSel =
284SetObjectAtIndexedSubscriptSel =
289 if(S == ArrayWithObjectSel || S == AddObjectSel ||
290S == InsertObjectAtIndexSel || S == ArrayByAddingObjectSel) {
292}
else if(S == SetObjectAtIndexedSubscriptSel) {
294CanBeSubscript =
true;
295}
else if(S == ReplaceObjectAtIndexWithObjectSel) {
301 if(S.isUnarySelector())
304 if(DictionaryWithObjectForKeySel.isNull()) {
306DictionaryWithObjectForKeySel =
309SetObjectForKeyedSubscriptSel =
314 if(S == DictionaryWithObjectForKeySel || S == SetObjectForKeySel) {
316warnIfNilArg(
C, msg,
1, Class);
317}
else if(S == SetObjectForKeyedSubscriptSel) {
318CanBeSubscript =
true;
320}
else if(S == RemoveObjectForKeySel) {
326 if((Arg != InvalidArgIndex))
327warnIfNilArg(
C, msg, Arg, Class, CanBeSubscript);
333 for(
unsignedi = 0; i < NumOfElements; ++i) {
334warnIfNilExpr(AL->
getElement(i),
"Array element cannot be nil",
C);
341 for(
unsignedi = 0; i < NumOfElements; ++i) {
343warnIfNilExpr(Element.Key,
"Dictionary key cannot be nil",
C);
344warnIfNilExpr(Element.Value,
"Dictionary value cannot be nil",
C);
353classCFNumberChecker :
public Checker< check::PreStmt<CallExpr> > {
354 mutablestd::unique_ptr<APIMisuse> BT;
355 mutable IdentifierInfo*ICreate =
nullptr, *IGetValue =
nullptr;
357CFNumberChecker() =
default;
383 static const unsigned charFixedSize[] = { 8, 16, 32, 64, 32, 64 };
386 returnFixedSize[i-1];
410static const char* GetCFNumberTypeStr(uint64_t i) {
411 static const char* Names[] = {
412 "kCFNumberSInt8Type",
413 "kCFNumberSInt16Type",
414 "kCFNumberSInt32Type",
415 "kCFNumberSInt64Type",
416 "kCFNumberFloat32Type",
417 "kCFNumberFloat64Type",
418 "kCFNumberCharType",
419 "kCFNumberShortType",
421 "kCFNumberLongType",
422 "kCFNumberLongLongType",
423 "kCFNumberFloatType",
424 "kCFNumberDoubleType",
425 "kCFNumberCFIndexType",
426 "kCFNumberNSIntegerType",
427 "kCFNumberCGFloatType" 434voidCFNumberChecker::checkPreStmt(
const CallExpr*CE,
443ICreate = &Ctx.
Idents.
get(
"CFNumberCreate");
444IGetValue = &Ctx.
Idents.
get(
"CFNumberGetValue");
455std::optional<nonloc::ConcreteInt>
V=
456dyn_cast<nonloc::ConcreteInt>(TheTypeVal);
460 uint64_tNumberKind =
V->getValue()->getLimitedValue();
461std::optional<uint64_t> OptCFNumberSize =
GetCFNumberSize(Ctx, NumberKind);
464 if(!OptCFNumberSize)
467 uint64_tCFNumberSize = *OptCFNumberSize;
494 if(PrimitiveTypeSize == CFNumberSize)
502llvm::raw_svector_ostream os(sbuf);
506os << (PrimitiveTypeSize == 8 ?
"An ":
"A ")
507<< PrimitiveTypeSize <<
"-bit integer is used to initialize a " 508<<
"CFNumber object that represents " 509<< (CFNumberSize == 8 ?
"an ":
"a ")
510<< CFNumberSize <<
"-bit integer; ";
512os <<
"A CFNumber object that represents " 513<< (CFNumberSize == 8 ?
"an ":
"a ")
514<< CFNumberSize <<
"-bit integer is used to initialize " 515<< (PrimitiveTypeSize == 8 ?
"an ":
"a ")
516<< PrimitiveTypeSize <<
"-bit integer; ";
519 if(PrimitiveTypeSize < CFNumberSize)
520os << (CFNumberSize - PrimitiveTypeSize)
521<<
" bits of the CFNumber value will " 522<< (isCreate ?
"be garbage.":
"overwrite adjacent storage.");
524os << (PrimitiveTypeSize - CFNumberSize)
525<<
" bits of the integer value will be " 526<< (isCreate ?
"lost.":
"garbage.");
529BT.reset(
newAPIMisuse(
this,
"Bad use of CFNumber APIs"));
531 autoreport = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
533 C.emitReport(std::move(report));
542classCFRetainReleaseChecker :
public Checker<check::PreCall> {
543 mutableAPIMisuse BT{
this,
"null passed to CF memory management function"};
545{CDM::CLibrary, {
"CFRetain"}, 1},
546{CDM::CLibrary, {
"CFRelease"}, 1},
547{CDM::CLibrary, {
"CFMakeCollectable"}, 1},
548{CDM::CLibrary, {
"CFAutorelease"}, 1},
556voidCFRetainReleaseChecker::checkPreCall(
const CallEvent&
Call,
559 if(!ModelledCalls.contains(
Call))
571std::tie(stateNonNull, stateNull) = state->assume(*DefArgVal);
579raw_svector_ostream OS(Str);
580OS <<
"Null pointer argument in call to " 581<< cast<FunctionDecl>(
Call.getDecl())->getName();
583 autoreport = std::make_unique<PathSensitiveBugReport>(BT, OS.str(), N);
584report->addRange(
Call.getArgSourceRange(0));
586 C.emitReport(std::move(report));
591 C.addTransition(stateNonNull);
599classClassReleaseChecker :
public Checker<check::PreObjCMessage> {
604 mutablestd::unique_ptr<BugType> BT;
611voidClassReleaseChecker::checkPreObjCMessage(
const ObjCMethodCall&msg,
614BT.reset(
newAPIMisuse(
615 this,
"message incorrectly sent to class instead of class instance"));
630 if(!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
635llvm::raw_svector_ostream os(buf);
639os <<
"' message should be sent to instances " 640 "of class '"<<
Class->getName()
641<<
"' and not the class directly";
643 autoreport = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
645 C.emitReport(std::move(report));
655classVariadicMethodTypeChecker :
public Checker<check::PreObjCMessage> {
657 mutable SelectordictionaryWithObjectsAndKeysS;
659 mutable SelectororderedSetWithObjectsS;
661 mutable SelectorinitWithObjectsAndKeysS;
662 mutablestd::unique_ptr<BugType> BT;
674VariadicMethodTypeChecker::isVariadicMessage(
const ObjCMethodCall&msg)
const{
695 returnS == initWithObjectsS;
697 returnS == initWithObjectsAndKeysS;
706 returnS == arrayWithObjectsS;
708 returnS == orderedSetWithObjectsS;
710 returnS == setWithObjectsS;
712 returnS == dictionaryWithObjectsAndKeysS;
719voidVariadicMethodTypeChecker::checkPreObjCMessage(
const ObjCMethodCall&msg,
722BT.reset(
newAPIMisuse(
this,
723 "Arguments passed to variadic method aren't all " 724 "Objective-C pointer types"));
728dictionaryWithObjectsAndKeysS =
734initWithObjectsAndKeysS =
GetUnarySelector(
"initWithObjectsAndKeys", Ctx);
737 if(!isVariadicMessage(msg))
746 unsignedvariadicArgsEnd = msg.
getNumArgs() - 1;
748 if(variadicArgsEnd <= variadicArgsBegin)
752std::optional<ExplodedNode *> errorNode;
754 for(
unsignedI = variadicArgsBegin; I != variadicArgsEnd; ++I) {
764 if(isa<loc::ConcreteInt>(msg.
getArgSVal(I)))
768 if(
C.getASTContext().isObjCNSObjectType(ArgTy))
777errorNode =
C.generateNonFatalErrorNode();
783llvm::raw_svector_ostream os(sbuf);
787os <<
"Argument to '"<<
TypeName<<
"' method '";
789os <<
"Argument to method '";
792os <<
"' should be an Objective-C pointer type, not '";
793ArgTy.
print(os,
C.getLangOpts());
797std::make_unique<PathSensitiveBugReport>(*BT, os.str(), *errorNode);
799 C.emitReport(std::move(R));
814:
public Checker<check::PostStmt<ObjCForCollectionStmt>,
815check::PostObjCMessage,
817check::PointerEscape > {
824ObjCLoopChecker() =
default;
867std::optional<DefinedSVal> KnownCollection =
869 if(!KnownCollection)
873std::tie(StNonNil, StNil) = State->assume(*KnownCollection);
874 if(StNil && !StNonNil) {
900std::optional<Loc> ElementLoc;
901 if(
const DeclStmt*DS = dyn_cast<DeclStmt>(Element)) {
902 const VarDecl*ElemDecl = cast<VarDecl>(DS->getSingleDecl());
903assert(ElemDecl->
getInit() ==
nullptr);
904ElementLoc = State->getLValue(ElemDecl, LCtx);
906ElementLoc = State->getSVal(Element, LCtx).getAs<
Loc>();
913 SValVal = State->getSVal(*ElementLoc);
914 returnState->assume(cast<DefinedOrUnknownSVal>(Val),
true);
921 SymbolRefCollectionS,
boolAssumption) {
922 if(!State || !CollectionS)
925 const SymbolRef*CountS = State->get<ContainerCountMap>(CollectionS);
927 const bool*KnownNonEmpty = State->get<ContainerNonEmptyMap>(CollectionS);
929 returnState->set<ContainerNonEmptyMap>(CollectionS, Assumption);
930 return(Assumption == *KnownNonEmpty) ? State :
nullptr;
934 SValCountGreaterThanZeroVal =
937SvalBuilder.
makeIntVal(0, (*CountS)->getType()),
939std::optional<DefinedSVal> CountGreaterThanZero =
941 if(!CountGreaterThanZero) {
947 returnState->assume(*CountGreaterThanZero, Assumption);
968 if(std::optional<BlockEdge> BE =
P.getAs<
BlockEdge>()) {
969 returnBE->getSrc()->getLoopTarget() == FCS;
998 C.generateSink(
C.getState(),
C.getPredecessor());
999 else if(State !=
C.getState())
1000 C.addTransition(State);
1003boolObjCLoopChecker::isCollectionCountMethod(
const ObjCMethodCall&M,
1007 if(!CountSelectorII)
1008CountSelectorII = &
C.getASTContext().Idents.get(
"count");
1011 returnS.isUnarySelector() &&
1012(S.getIdentifierInfoForSlot(0) == CountSelectorII);
1015voidObjCLoopChecker::checkPostObjCMessage(
const ObjCMethodCall&M,
1037 if(!isCollectionCountMethod(M,
C))
1041 SymbolRefCountS =
C.getSVal(MsgExpr).getAsSymbol();
1045 C.getSymbolManager().addSymbolDependency(ContainerS, CountS);
1046State = State->set<ContainerCountMap>(ContainerS, CountS);
1048 if(
const bool*NonEmpty = State->get<ContainerNonEmptyMap>(ContainerS)) {
1049State = State->remove<ContainerNonEmptyMap>(ContainerS);
1053 C.addTransition(State);
1071StaticClass = Message->getOriginExpr()->getReceiverInterface();
1092 returnMessage->getReceiverSVal().getAsSymbol();
1108 if(Sym == ImmutableReceiver)
1113State = State->remove<ContainerCountMap>(Sym);
1114State = State->remove<ContainerNonEmptyMap>(Sym);
1119voidObjCLoopChecker::checkDeadSymbols(
SymbolReaper&SymReaper,
1124ContainerCountMapTy Tracked = State->get<ContainerCountMap>();
1125 for(
SymbolRefSym : llvm::make_first_range(Tracked)) {
1126 if(SymReaper.
isDead(Sym)) {
1127State = State->remove<ContainerCountMap>(Sym);
1128State = State->remove<ContainerNonEmptyMap>(Sym);
1132 C.addTransition(State);
1139classObjCNonNilReturnValueChecker
1140:
public Checker<check::PostObjCMessage,
1141check::PostStmt<ObjCArrayLiteral>,
1142check::PostStmt<ObjCDictionaryLiteral>,
1143check::PostStmt<ObjCBoxedExpr> > {
1146 mutable SelectorObjectAtIndexedSubscript;
1150ObjCNonNilReturnValueChecker() =
default;
1156 C.addTransition(assumeExprIsNonNull(
E,
C.getState(),
C));
1160assumeExprIsNonNull(
E,
C);
1163assumeExprIsNonNull(
E,
C);
1166assumeExprIsNonNull(
E,
C);
1174ObjCNonNilReturnValueChecker::assumeExprIsNonNull(
const Expr*NonNullExpr,
1177 SValVal =
C.getSVal(NonNullExpr);
1178 if(std::optional<DefinedOrUnknownSVal> DV =
1180 returnState->assume(*DV,
true);
1184voidObjCNonNilReturnValueChecker::checkPostObjCMessage(
const ObjCMethodCall&M,
1192ObjectAtIndexedSubscript =
GetUnarySelector(
"objectAtIndexedSubscript", Ctx);
1207 if(!
C.inTopFrame() && M.
getDecl() &&
1220 if(Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
1234 C.addTransition(State);
1245boolento::shouldRegisterNilArgChecker(
const CheckerManager&mgr) {
1253boolento::shouldRegisterCFNumberChecker(
const CheckerManager&mgr) {
1261boolento::shouldRegisterCFRetainReleaseChecker(
const CheckerManager&mgr) {
1269boolento::shouldRegisterClassReleaseChecker(
const CheckerManager&mgr) {
1273voidento::registerVariadicMethodTypeChecker(
CheckerManager&mgr) {
1277boolento::shouldRegisterVariadicMethodTypeChecker(
const CheckerManager&mgr) {
1285boolento::shouldRegisterObjCLoopChecker(
const CheckerManager&mgr) {
1289voidento::registerObjCNonNilReturnValueChecker(
CheckerManager&mgr) {
1293boolento::shouldRegisterObjCNonNilReturnValueChecker(
const CheckerManager&mgr) {
Defines the clang::ASTContext interface.
static bool alreadyExecutedAtLeastOneLoopIteration(const ExplodedNode *N, const ObjCForCollectionStmt *FCS)
If the fist block edge is a back edge, we are reentering the loop.
static ProgramStateRef checkCollectionNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection is non-nil.
static FoundationClass findKnownClass(const ObjCInterfaceDecl *ID, bool IncludeSuperclasses=true)
static bool isKnownNonNilCollectionType(QualType T)
static ProgramStateRef assumeCollectionNonEmpty(CheckerContext &C, ProgramStateRef State, SymbolRef CollectionS, bool Assumption)
Returns NULL state if the collection is known to contain elements (or is known not to contain element...
static SymbolRef getMethodReceiverIfKnownImmutable(const CallEvent *Call)
static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg)
static std::optional< uint64_t > GetCFNumberSize(ASTContext &Ctx, uint64_t i)
static ProgramStateRef checkElementNonNil(CheckerContext &C, ProgramStateRef State, const ObjCForCollectionStmt *FCS)
Assumes that the collection elements are non-nil.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Defines the Objective-C statement AST node classes.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
DeclContext * getDeclContext()
The return type of classify().
This represents one expression.
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.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp,...
Expr * getElement(unsigned Index)
getElement - Return the Element at the specified index.
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
ObjCBoxedExpr - used for generalized expression boxing.
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Represents Objective-C's collection statement.
Represents an ObjC class declaration.
ObjCMethodDecl - Represents an instance or class method declaration.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
ObjCInterfaceDecl * getClassInterface()
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.
A (possibly-)qualified type.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Smart pointer class that efficiently represents Objective-C method names.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
unsigned getNumArgs() const
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isBlockPointerType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isObjCObjectPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
Represents a variable declaration or definition.
const Expr * getInit() const
An immutable set of CallDescriptions.
Represents an abstract call to a function or method along a particular path.
virtual SourceRange getArgSourceRange(unsigned Index) const
Returns the source range for errors associated with this argument.
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)
Represents any expression that calls an Objective-C method.
const ObjCMethodDecl * getDecl() const override
Returns the declaration of the function or method that will be called.
bool isInstanceMessage() const
const Expr * getArgExpr(unsigned Index) const override
Returns the expression associated with a given argument.
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
unsigned getNumArgs() const override
Returns the number of arguments (explicit and implicit).
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
SourceRange getSourceRange() const override
Returns a source range for the entire call, suitable for outputting in diagnostics.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
bool isReceiverSelfOrSuper() const
Checks if the receiver refers to 'self' or 'super'.
Selector getSelector() const
A Range represents the closed range [from, to].
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
QualType getConditionType() const
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
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.
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
TypedValueRegion - An abstract class representing regions having a typed value.
virtual QualType getValueType() const =0
Represents symbolic expression that isn't a location.
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
const char *const AppleAPIMisuse
bool isCFObjectRef(QualType T)
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Descriptor *Desc)
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
The JSON file list parser is used to communicate input to InstallAPI.
static Selector getKeywordSelector(ASTContext &Ctx, const IdentifierInfos *...IIs)
@ NonNull
Values of this type can never be null.
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
const FunctionProtoType * T
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
An element in an Objective-C dictionary literal.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4