;
45:
public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,
52 boolModelSmartPtrDereference =
false;
62 const char*Sep)
const override;
81std::pair<SVal, ProgramStateRef>
86 usingSmartPtrMethodHandlerFn =
89{{CDM::CXXMethod, {
"reset"}}, &SmartPtrModeling::handleReset},
90{{CDM::CXXMethod, {
"release"}}, &SmartPtrModeling::handleRelease},
91{{CDM::CXXMethod, {
"swap"}, 1}, &SmartPtrModeling::handleSwapMethod},
92{{CDM::CXXMethod, {
"get"}}, &SmartPtrModeling::handleGet}};
93 const CallDescriptionStdSwapCall{CDM::SimpleFunc, {
"std",
"swap"}, 2};
95{CDM::SimpleFunc, {
"std",
"make_unique"}},
96{CDM::SimpleFunc, {
"std",
"make_unique_for_overwrite"}}};
105 if(!RD || !RD->getDeclContext()->isStdNamespace())
107 if(RD->getDeclName().isIdentifier())
108 returnllvm::is_contained(Names, RD->getName());
112constexprllvm::StringLiteral
STD_PTR_NAMES[] = {
"shared_ptr",
"unique_ptr",
128 const auto*MethodDecl = dyn_cast_or_null<CXXMethodDecl>(
Call.getDecl());
129 if(!MethodDecl || !MethodDecl->getParent())
139StringRef Name = RD->
getName();
140 returnName ==
"shared_ptr"|| Name ==
"unique_ptr"|| Name ==
"weak_ptr";
150 const auto*InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
151 returnInnerPointVal &&
159staticTrackedRegionMapTy
161TrackedRegionMapTy::Factory &RegionMapFactory,
165 for(
const auto&
E: RegionMap) {
166 if(
E.first->isSubRegionOf(Region))
167RegionMap = RegionMapFactory.remove(RegionMap,
E.first);
174 const SVal*RegionInnerPointerVal) {
175 if(RegionInnerPointerVal) {
176State = State->set<TrackedRegionMap>(Region, *RegionInnerPointerVal);
178State = State->remove<TrackedRegionMap>(Region);
187 const auto*TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
191 autoTemplateArgs = TSD->getTemplateArgs().asArray();
192 if(TemplateArgs.empty())
194 autoInnerValueType = TemplateArgs[0].getAsType();
195 return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());
203 const auto*FD = dyn_cast_or_null<FunctionDecl>(
Call.getDecl());
204 if(!FD || !FD->getPrimaryTemplate())
206 const auto&TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();
207 if(TemplateArgs.size() == 0)
209 autoValueType = TemplateArgs[0].getAsType();
210 return C.getASTContext().getPointerType(ValueType.getCanonicalType());
216 const auto*MethodDecl = dyn_cast_or_null<CXXMethodDecl>(
Call.getDecl());
217 if(!MethodDecl || !MethodDecl->getParent())
233boolSmartPtrModeling::isBoolConversionMethod(
const CallEvent&
Call)
const{
238 const auto*CD = dyn_cast_or_null<CXXConversionDecl>(
Call.getDecl());
239 returnCD && CD->getConversionType()->isBooleanType();
250 return Call.getDecl() &&
Call.getDecl()->getDeclContext()->isStdNamespace();
256 const auto*FC = dyn_cast<SimpleFunctionCall>(&
Call);
263 if(OOK != clang::OO_LessLess)
284 if(handleComparisionOp(
Call,
C))
288 returnhandleOstreamOperator(
Call,
C);
290 if(StdSwapCall.matches(
Call)) {
292assert(
Call.getNumArgs() == 2 &&
"std::swap should have two arguments");
293 const Expr*FirstArg =
Call.getArgExpr(0);
296 returnhandleSwap(State,
Call.getArgSVal(0),
Call.getArgSVal(1),
C);
299 if(MakeUniqueVariants.contains(
Call)) {
300 if(!ModelSmartPtrDereference)
303 conststd::optional<SVal> ThisRegionOpt =
304 Call.getReturnValueUnderConstruction();
308 const autoPtrVal =
C.getSValBuilder().getConjuredHeapSymbolVal(
309 Call.getOriginExpr(),
C.getLocationContext(),
312 const MemRegion*ThisRegion = ThisRegionOpt->getAsRegion();
313State = State->set<TrackedRegionMap>(ThisRegion, PtrVal);
314State = State->assume(PtrVal,
true);
332 auto&Engine = State->getStateManager().getOwningEngine();
333State = Engine.updateObjectsUnderConstruction(
334*ThisRegionOpt,
nullptr, State,
C.getLocationContext(),
335 Call.getConstructionContext(), {});
339 C.addTransition(State);
346 if(isBoolConversionMethod(
Call)) {
348cast<CXXInstanceCall>(&
Call)->getCXXThisVal().getAsRegion();
350 if(ModelSmartPtrDereference) {
355handleBoolConversion(
Call,
C);
365 C.addTransition(State->BindExpr(
366 Call.getOriginExpr(),
C.getLocationContext(),
367 C.getSValBuilder().makeZeroVal(
Call.getResultType())));
373 if(!ModelSmartPtrDereference)
376 if(
const auto*CC = dyn_cast<CXXConstructorCall>(&
Call)) {
377 if(CC->getDecl()->isCopyConstructor())
380 const MemRegion*ThisRegion = CC->getCXXThisVal().getAsRegion();
384 QualTypeThisType = cast<CXXMethodDecl>(
Call.getDecl())->getThisType();
386 if(CC->getDecl()->isMoveConstructor())
387 returnhandleMoveCtr(
Call,
C, ThisRegion);
389 if(
Call.getNumArgs() == 0) {
390 autoNullVal =
C.getSValBuilder().makeNullWithType(ThisType);
391State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
395llvm::raw_ostream &OS) {
396if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
397!BR.isInteresting(ThisRegion))
399OS <<
"Default constructed smart pointer";
400checkAndPrettyPrintRegion(OS, ThisRegion);
404 const auto*TrackingExpr =
Call.getArgExpr(0);
405assert(TrackingExpr->getType()->isPointerType() &&
406 "Adding a non pointer value to TrackedRegionMap");
407 autoArgVal =
Call.getArgSVal(0);
408State = State->set<TrackedRegionMap>(ThisRegion, ArgVal);
410 C.addTransition(State,
C.getNoteTag([ThisRegion, TrackingExpr,
412llvm::raw_ostream &OS) {
413if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
414!BR.isInteresting(ThisRegion))
416bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
417OS <<
"Smart pointer";
418checkAndPrettyPrintRegion(OS, ThisRegion);
419if (ArgVal.isZeroConstant())
420OS <<
" is constructed using a null value";
422OS <<
" is constructed";
428 if(handleAssignOp(
Call,
C))
431 constSmartPtrMethodHandlerFn *Handler = SmartPtrMethodHandlers.lookup(
Call);
434(this->**Handler)(
Call,
C);
436 return C.isDifferent();
439std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
442 const auto*Ptr = State->get<TrackedRegionMap>(ThisRegion);
444 return{*Ptr, State};
445 autoVal =
C.getSValBuilder().conjureSymbolVal(
E,
C.getLocationContext(),
446 Type,
C.blockCount());
447State = State->set<TrackedRegionMap>(ThisRegion, Val);
451boolSmartPtrModeling::handleComparisionOp(
const CallEvent&
Call,
453 const auto*FC = dyn_cast<SimpleFunctionCall>(&
Call);
460 if(!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less ||
461OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
462OOK == OO_Spaceship))
472 SValS) -> std::pair<SVal, ProgramStateRef> {
473 if(S.isZeroConstant()) {
478 "this pointer of std::unique_ptr should be obtainable as MemRegion");
480 returnretrieveOrConjureInnerPtrVal(State, Reg,
E,
Type,
C);
485 const auto*FirstExpr =
Call.getArgExpr(0);
486 const auto*SecondExpr =
Call.getArgExpr(1);
488 const auto*ResultExpr =
Call.getOriginExpr();
489 const auto*LCtx =
C.getLocationContext();
490 auto&Bldr =
C.getSValBuilder();
493 SValFirstPtrVal, SecondPtrVal;
494std::tie(FirstPtrVal, State) = makeSValFor(State, FirstExpr,
First);
495std::tie(SecondPtrVal, State) = makeSValFor(State, SecondExpr, Second);
498 autoRetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal,
499 Call.getResultType());
501 if(OOK != OO_Spaceship) {
503std::tie(TrueState, FalseState) =
507TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(
true)));
510FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(
false)));
512 C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal));
517boolSmartPtrModeling::handleOstreamOperator(
const CallEvent&
Call,
528 const autoStreamVal =
Call.getArgSVal(0);
529 const MemRegion*StreamThisRegion = StreamVal.getAsRegion();
530 if(!StreamThisRegion)
533State->invalidateRegions({StreamThisRegion},
Call.getOriginExpr(),
534 C.blockCount(),
C.getLocationContext(),
false);
536State->BindExpr(
Call.getOriginExpr(),
C.getLocationContext(), StreamVal);
537 C.addTransition(State);
541voidSmartPtrModeling::checkDeadSymbols(
SymbolReaper&SymReaper,
545TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
546 for(
auto E: TrackedRegions) {
551State = State->remove<TrackedRegionMap>(Region);
553 C.addTransition(State);
556voidSmartPtrModeling::printState(raw_ostream &Out,
ProgramStateRefState,
557 const char*NL,
const char*Sep)
const{
558TrackedRegionMapTy RS = State->get<TrackedRegionMap>();
561Out << Sep <<
"Smart ptr regions :"<< NL;
563I.first->dumpToStream(Out);
567Out <<
": Non Null";
578TrackedRegionMapTy RegionMap = State->get<TrackedRegionMap>();
579TrackedRegionMapTy::Factory &RegionMapFactory =
580State->get_context<TrackedRegionMap>();
581 for(
const auto*Region : Regions)
584 returnState->set<TrackedRegionMap>(RegionMap);
590TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
591 for(
SValVal : llvm::make_second_range(TrackedRegions)) {
601 const auto*IC = dyn_cast<CXXInstanceCall>(&
Call);
605 const MemRegion*ThisRegion = IC->getCXXThisVal().getAsRegion();
609assert(
Call.getArgExpr(0)->getType()->isPointerType() &&
610 "Adding a non pointer value to TrackedRegionMap");
611State = State->set<TrackedRegionMap>(ThisRegion,
Call.getArgSVal(0));
612 const auto*TrackingExpr =
Call.getArgExpr(0);
615llvm::raw_ostream &OS) {
616if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
617!BR.isInteresting(ThisRegion))
619bugreporter::trackExpressionValue(BR.getErrorNode(), TrackingExpr, BR);
620OS <<
"Smart pointer";
621checkAndPrettyPrintRegion(OS, ThisRegion);
622OS <<
" reset using a null value";
628voidSmartPtrModeling::handleRelease(
const CallEvent&
Call,
631 const auto*IC = dyn_cast<CXXInstanceCall>(&
Call);
635 const MemRegion*ThisRegion = IC->getCXXThisVal().getAsRegion();
639 const auto*InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
642State = State->BindExpr(
Call.getOriginExpr(),
C.getLocationContext(),
646 QualTypeThisType = cast<CXXMethodDecl>(
Call.getDecl())->getThisType();
647 autoValueToUpdate =
C.getSValBuilder().makeNullWithType(ThisType);
648State = State->set<TrackedRegionMap>(ThisRegion, ValueToUpdate);
651llvm::raw_ostream &OS) {
652if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
653!BR.isInteresting(ThisRegion))
656OS <<
"Smart pointer";
657checkAndPrettyPrintRegion(OS, ThisRegion);
658OS <<
" is released and set to null";
664voidSmartPtrModeling::handleSwapMethod(
const CallEvent&
Call,
667 const auto*IC = dyn_cast<CXXInstanceCall>(&
Call);
671 autoState =
C.getState();
672handleSwap(State, IC->getCXXThisVal(),
Call.getArgSVal(0),
C);
678 if(!FirstThisRegion)
681 if(!SecondThisRegion)
684 const auto*FirstInnerPtrVal = State->get<TrackedRegionMap>(FirstThisRegion);
685 const auto*SecondInnerPtrVal =
686State->get<TrackedRegionMap>(SecondThisRegion);
691 C.addTransition(State,
C.getNoteTag([FirstThisRegion, SecondThisRegion](
693llvm::raw_ostream &OS) {
694if (&BR.getBugType() != smartptr::getNullDereferenceBugType())
696if (BR.isInteresting(FirstThisRegion) &&
697!BR.isInteresting(SecondThisRegion)) {
698BR.markInteresting(SecondThisRegion);
699BR.markNotInteresting(FirstThisRegion);
703BR.markInteresting(FirstThisRegion);
704BR.markNotInteresting(SecondThisRegion);
715 const auto*IC = dyn_cast<CXXInstanceCall>(&
Call);
719 const MemRegion*ThisRegion = IC->getCXXThisVal().getAsRegion();
723 SValInnerPointerVal;
724std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(
725State, ThisRegion,
Call.getOriginExpr(),
Call.getResultType(),
C);
726State = State->BindExpr(
Call.getOriginExpr(),
C.getLocationContext(),
729 C.addTransition(State);
732boolSmartPtrModeling::handleAssignOp(
const CallEvent&
Call,
735 const auto*OC = dyn_cast<CXXMemberOperatorCall>(&
Call);
741 const MemRegion*ThisRegion = OC->getCXXThisVal().getAsRegion();
745 QualTypeThisType = cast<CXXMethodDecl>(
Call.getDecl())->getThisType();
747 const MemRegion*OtherSmartPtrRegion = OC->getArgSVal(0).getAsRegion();
749 if(!OtherSmartPtrRegion) {
750 boolAssignedNull =
Call.getArgSVal(0).isZeroConstant();
753 autoNullVal =
C.getSValBuilder().makeNullWithType(ThisType);
754State = State->set<TrackedRegionMap>(ThisRegion, NullVal);
756llvm::raw_ostream &OS) {
757if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
758!BR.isInteresting(ThisRegion))
760OS <<
"Smart pointer";
761checkAndPrettyPrintRegion(OS, ThisRegion);
762OS <<
" is assigned to null";
767 returnupdateMovedSmartPointers(
C, ThisRegion, OtherSmartPtrRegion,
Call);
772 const auto*OtherSmartPtrRegion =
Call.getArgSVal(0).getAsRegion();
773 if(!OtherSmartPtrRegion)
776 returnupdateMovedSmartPointers(
C, ThisRegion, OtherSmartPtrRegion,
Call);
779boolSmartPtrModeling::updateMovedSmartPointers(
783 QualTypeThisType = cast<CXXMethodDecl>(
Call.getDecl())->getThisType();
784 const auto*OtherInnerPtr = State->get<TrackedRegionMap>(OtherSmartPtrRegion);
786State = State->set<TrackedRegionMap>(ThisRegion, *OtherInnerPtr);
788 autoNullVal =
C.getSValBuilder().makeNullWithType(ThisType);
789State = State->set<TrackedRegionMap>(OtherSmartPtrRegion, NullVal);
790 boolIsArgValNull = OtherInnerPtr->isZeroConstant();
794 C.getNoteTag([ThisRegion, OtherSmartPtrRegion, IsArgValNull](
799OS <<
"Smart pointer";
801OS <<
" is null after being moved to";
805OS <<
"A null pointer value is moved to";
815 autoNullVal =
C.getSValBuilder().makeNullWithType(ThisType);
816State = State->remove<TrackedRegionMap>(ThisRegion);
817State = State->set<TrackedRegionMap>(OtherSmartPtrRegion, NullVal);
818 C.addTransition(State,
C.getNoteTag([OtherSmartPtrRegion,
820llvm::raw_ostream &OS) {
824OS <<
"Smart pointer";
826OS <<
" is null after; previous value moved to";
834voidSmartPtrModeling::handleBoolConversion(
const CallEvent&
Call,
840cast<CXXInstanceCall>(&
Call)->getCXXThisVal().getAsRegion();
842 QualTypeThisType = cast<CXXMethodDecl>(
Call.getDecl())->getThisType();
844 SValInnerPointerVal;
845 if(
const auto*InnerValPtr = State->get<TrackedRegionMap>(ThisRegion)) {
846InnerPointerVal = *InnerValPtr;
851 if(InnerPointerType.isNull())
855InnerPointerVal =
C.getSValBuilder().conjureSymbolVal(
856 CallExpr, LC, InnerPointerType,
C.blockCount());
857State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal);
860 if(State->isNull(InnerPointerVal).isConstrainedTrue()) {
861State = State->BindExpr(
CallExpr,
C.getLocationContext(),
862 C.getSValBuilder().makeTruthVal(
false));
864 C.addTransition(State);
866}
else if(State->isNonNull(InnerPointerVal).isConstrainedTrue()) {
867State = State->BindExpr(
CallExpr,
C.getLocationContext(),
868 C.getSValBuilder().makeTruthVal(
true));
870 C.addTransition(State);
874State->BindExpr(
CallExpr,
C.getLocationContext(),
875 C.getSValBuilder().makeZeroVal(
Call.getResultType())));
879std::tie(NotNullState, NullState) =
882 autoNullVal =
C.getSValBuilder().makeNullWithType(ThisType);
884NullState = NullState->set<TrackedRegionMap>(ThisRegion, NullVal);
886NullState = NullState->BindExpr(
CallExpr,
C.getLocationContext(),
887 C.getSValBuilder().makeTruthVal(
false));
888 C.addTransition(NullState,
C.getNoteTag(
890llvm::raw_ostream &OS) {
891OS <<
"Assuming smart pointer";
892checkAndPrettyPrintRegion(OS, ThisRegion);
897NotNullState->BindExpr(
CallExpr,
C.getLocationContext(),
898 C.getSValBuilder().makeTruthVal(
true));
903OS <<
"Assuming smart pointer";
904checkAndPrettyPrintRegion(OS, ThisRegion);
905OS <<
" is non-null";
914 Checker->ModelSmartPtrDereference =
916 Checker,
"ModelSmartPtrDereference");
919boolento::shouldRegisterSmartPtrModeling(
const CheckerManager&mgr) {
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
static bool isStdFunctionCall(const CallEvent &Call)
static bool isStdBasicOstream(const Expr *E)
static void checkAndPrettyPrintRegion(llvm::raw_ostream &OS, const MemRegion *Region)
static QualType getInnerPointerType(CheckerContext C, const CXXRecordDecl *RD)
static ProgramStateRef updateSwappedRegion(ProgramStateRef State, const MemRegion *Region, const SVal *RegionInnerPointerVal)
static bool isStdOstreamOperatorCall(const CallEvent &Call)
static TrackedRegionMapTy removeTrackedSubregions(TrackedRegionMapTy RegionMap, TrackedRegionMapTy::Factory &RegionMapFactory, const MemRegion *Region)
static bool isPotentiallyComparisionOpCall(const CallEvent &Call)
static QualType getPointerTypeFromTemplateArg(const CallEvent &Call, CheckerContext &C)
static bool hasStdClassWithName(const CXXRecordDecl *RD, ArrayRef< llvm::StringLiteral > Names)
static bool isStdSmartPtr(const CXXRecordDecl *RD)
constexpr llvm::StringLiteral BASIC_OSTREAM_NAMES[]
constexpr llvm::StringLiteral STD_PTR_NAMES[]
C Language Family Type Representation.
bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, bool SearchInParents=false) const
Interprets an option's string value as a boolean.
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isStdNamespace() const
bool isInStdNamespace() const
DeclContext * getDeclContext()
bool isIdentifier() const
Predicate functions for querying what type of name this is.
This represents one expression.
Represents a function declaration or definition.
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
A (possibly-)qualified type.
Represents a struct/union/class.
StringLiteral - This represents a string literal expression, e.g.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const BugType & getBugType() const
An immutable map from CallDescriptions to arbitrary data.
An immutable set of CallDescriptions.
A CallDescription is a pattern that can be used to match calls based on the qualified name and the ar...
Represents an abstract call to a function or method along a particular path.
virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const
See CheckerManager::runCheckersForPrintState.
const AnalyzerOptions & getAnalyzerOptions() const
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
const LangOptions & getLangOpts() const
MemRegion - The root abstract class for all memory regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
BinaryOperatorKind GetBinaryOpUnsafe() const
void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)
Marks a symbol as interesting.
bool isInteresting(SymbolRef sym) const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
const MemRegion * getAsRegion() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
llvm::iterator_range< symbol_iterator > symbols() const
A class responsible for cleaning up unused symbols.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
bool isLiveRegion(const MemRegion *region)
bool isMovedFrom(ProgramStateRef State, const MemRegion *Region)
Returns true if the object is known to have been recently std::moved.
const BugType * getNullDereferenceBugType()
bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion)
Returns whether the smart pointer is null or not.
bool isStdSmartPtr(const CXXRecordDecl *RD)
bool isStdSmartPtrCall(const CallEvent &Call)
Returns true if the event call is on smart pointer.
OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, bool IsBinary)
llvm::DenseSet< SymbolRef > InvalidatedSymbols
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
Diagnostic wrappers for TextAPI types for error reporting.
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