diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-08-15 22:09:50 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-08-15 22:09:50 +0000 |
commit | 18c66fdc3c4008d335885695fe36fb5353c5f672 (patch) | |
tree | 019e9f4a85f00db1b37272874093391e17e1d6ac /lib/StaticAnalyzer/Checkers/CStringChecker.cpp | |
parent | 6db629e09a76676f872d86285e68a29eb8a6f131 (diff) |
Rename GRState to ProgramState, and cleanup some code formatting along the way.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137665 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 224 |
1 files changed, 126 insertions, 98 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index b1389cff0b..23a189e6a7 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -17,7 +17,7 @@ #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; @@ -40,14 +40,15 @@ public: bool evalCall(const CallExpr *CE, CheckerContext &C) const; void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; - void checkLiveSymbols(const GRState *state, SymbolReaper &SR) const; + void checkLiveSymbols(const ProgramState *state, SymbolReaper &SR) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; - bool wantsRegionChangeUpdate(const GRState *state) const; + bool wantsRegionChangeUpdate(const ProgramState *state) const; - const GRState *checkRegionChanges(const GRState *state, - const StoreManager::InvalidatedSymbols *, - const MemRegion * const *Begin, - const MemRegion * const *End) const; + const ProgramState * + checkRegionChanges(const ProgramState *state, + const StoreManager::InvalidatedSymbols *, + const MemRegion * const *Begin, + const MemRegion * const *End) const; typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *) const; @@ -57,8 +58,10 @@ public: void evalMemmove(CheckerContext &C, const CallExpr *CE) const; void evalBcopy(CheckerContext &C, const CallExpr *CE) const; void evalCopyCommon(CheckerContext &C, const CallExpr *CE, - const GRState *state, - const Expr *Size, const Expr *Source, const Expr *Dest, + const ProgramState *state, + const Expr *Size, + const Expr *Source, + const Expr *Dest, bool Restricted = false, bool IsMempcpy = false) const; @@ -66,14 +69,18 @@ public: void evalstrLength(CheckerContext &C, const CallExpr *CE) const; void evalstrnLength(CheckerContext &C, const CallExpr *CE) const; - void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, + void evalstrLengthCommon(CheckerContext &C, + const CallExpr *CE, bool IsStrnlen = false) const; void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; - void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, - bool isBounded, bool isAppending) const; + void evalStrcpyCommon(CheckerContext &C, + const CallExpr *CE, + bool returnEnd, + bool isBounded, + bool isAppending) const; void evalStrcat(CheckerContext &C, const CallExpr *CE) const; void evalStrncat(CheckerContext &C, const CallExpr *CE) const; @@ -82,64 +89,85 @@ public: void evalStrncmp(CheckerContext &C, const CallExpr *CE) const; void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const; void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const; - void evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, - bool isBounded = false, bool ignoreCase = false) const; + void evalStrcmpCommon(CheckerContext &C, + const CallExpr *CE, + bool isBounded = false, + bool ignoreCase = false) const; // Utility methods - std::pair<const GRState*, const GRState*> + std::pair<const ProgramState*, const ProgramState*> static assumeZero(CheckerContext &C, - const GRState *state, SVal V, QualType Ty); + const ProgramState *state, SVal V, QualType Ty); - static const GRState *setCStringLength(const GRState *state, - const MemRegion *MR, SVal strLength); + static const ProgramState *setCStringLength(const ProgramState *state, + const MemRegion *MR, + SVal strLength); static SVal getCStringLengthForRegion(CheckerContext &C, - const GRState *&state, - const Expr *Ex, const MemRegion *MR, + const ProgramState *&state, + const Expr *Ex, + const MemRegion *MR, bool hypothetical); - SVal getCStringLength(CheckerContext &C, const GRState *&state, - const Expr *Ex, SVal Buf, + SVal getCStringLength(CheckerContext &C, + const ProgramState *&state, + const Expr *Ex, + SVal Buf, bool hypothetical = false) const; const StringLiteral *getCStringLiteral(CheckerContext &C, - const GRState *&state, + const ProgramState *&state, const Expr *expr, SVal val) const; - static const GRState *InvalidateBuffer(CheckerContext &C, - const GRState *state, - const Expr *Ex, SVal V); + static const ProgramState *InvalidateBuffer(CheckerContext &C, + const ProgramState *state, + const Expr *Ex, SVal V); static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx, const MemRegion *MR); // Re-usable checks - const GRState *checkNonNull(CheckerContext &C, const GRState *state, - const Expr *S, SVal l) const; - const GRState *CheckLocation(CheckerContext &C, const GRState *state, - const Expr *S, SVal l, - const char *message = NULL) const; - const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, - const Expr *Size, - const Expr *FirstBuf, - const Expr *SecondBuf, - const char *firstMessage = NULL, - const char *secondMessage = NULL, - bool WarnAboutSize = false) const; - const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, - const Expr *Size, const Expr *Buf, - const char *message = NULL, - bool WarnAboutSize = false) const { + const ProgramState *checkNonNull(CheckerContext &C, + const ProgramState *state, + const Expr *S, + SVal l) const; + const ProgramState *CheckLocation(CheckerContext &C, + const ProgramState *state, + const Expr *S, + SVal l, + const char *message = NULL) const; + const ProgramState *CheckBufferAccess(CheckerContext &C, + const ProgramState *state, + const Expr *Size, + const Expr *FirstBuf, + const Expr *SecondBuf, + const char *firstMessage = NULL, + const char *secondMessage = NULL, + bool WarnAboutSize = false) const; + + const ProgramState *CheckBufferAccess(CheckerContext &C, + const ProgramState *state, + const Expr *Size, + const Expr *Buf, + const char *message = NULL, + bool WarnAboutSize = false) const { // This is a convenience override. return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL, WarnAboutSize); } - const GRState *CheckOverlap(CheckerContext &C, const GRState *state, - const Expr *Size, const Expr *First, - const Expr *Second) const; - void emitOverlapBug(CheckerContext &C, const GRState *state, - const Stmt *First, const Stmt *Second) const; - const GRState *checkAdditionOverflow(CheckerContext &C, const GRState *state, - NonLoc left, NonLoc right) const; + const ProgramState *CheckOverlap(CheckerContext &C, + const ProgramState *state, + const Expr *Size, + const Expr *First, + const Expr *Second) const; + void emitOverlapBug(CheckerContext &C, + const ProgramState *state, + const Stmt *First, + const Stmt *Second) const; + + const ProgramState *checkAdditionOverflow(CheckerContext &C, + const ProgramState *state, + NonLoc left, + NonLoc right) const; }; class CStringLength { @@ -151,8 +179,8 @@ public: namespace clang { namespace ento { template <> - struct GRStateTrait<CStringLength> - : public GRStatePartialTrait<CStringLength::EntryMap> { + struct ProgramStateTrait<CStringLength> + : public ProgramStatePartialTrait<CStringLength::EntryMap> { static void *GDMIndex() { return CStringChecker::getTag(); } }; } @@ -162,26 +190,26 @@ namespace ento { // Individual checks and utility methods. //===----------------------------------------------------------------------===// -std::pair<const GRState*, const GRState*> -CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V, +std::pair<const ProgramState*, const ProgramState*> +CStringChecker::assumeZero(CheckerContext &C, const ProgramState *state, SVal V, QualType Ty) { DefinedSVal *val = dyn_cast<DefinedSVal>(&V); if (!val) - return std::pair<const GRState*, const GRState *>(state, state); + return std::pair<const ProgramState*, const ProgramState *>(state, state); SValBuilder &svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); return state->assume(svalBuilder.evalEQ(state, *val, zero)); } -const GRState *CStringChecker::checkNonNull(CheckerContext &C, - const GRState *state, +const ProgramState *CStringChecker::checkNonNull(CheckerContext &C, + const ProgramState *state, const Expr *S, SVal l) const { // If a previous check has failed, propagate the failure. if (!state) return NULL; - const GRState *stateNull, *stateNonNull; + const ProgramState *stateNull, *stateNonNull; llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); if (stateNull && !stateNonNull) { @@ -214,8 +242,8 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C, } // FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? -const GRState *CStringChecker::CheckLocation(CheckerContext &C, - const GRState *state, +const ProgramState *CStringChecker::CheckLocation(CheckerContext &C, + const ProgramState *state, const Expr *S, SVal l, const char *warningMsg) const { // If a previous check has failed, propagate the failure. @@ -244,8 +272,8 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C, // Get the index of the accessed element. DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); - const GRState *StInBound = state->assumeInBound(Idx, Size, true); - const GRState *StOutBound = state->assumeInBound(Idx, Size, false); + const ProgramState *StInBound = state->assumeInBound(Idx, Size, true); + const ProgramState *StOutBound = state->assumeInBound(Idx, Size, false); if (StOutBound && !StInBound) { ExplodedNode *N = C.generateSink(StOutBound); if (!N) @@ -287,8 +315,8 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C, return StInBound; } -const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, - const GRState *state, +const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C, + const ProgramState *state, const Expr *Size, const Expr *FirstBuf, const Expr *SecondBuf, @@ -359,8 +387,8 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, return state; } -const GRState *CStringChecker::CheckOverlap(CheckerContext &C, - const GRState *state, +const ProgramState *CStringChecker::CheckOverlap(CheckerContext &C, + const ProgramState *state, const Expr *Size, const Expr *First, const Expr *Second) const { @@ -372,7 +400,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C, if (!state) return NULL; - const GRState *stateTrue, *stateFalse; + const ProgramState *stateTrue, *stateFalse; // Get the buffer values and make sure they're known locations. SVal firstVal = state->getSVal(First); @@ -470,7 +498,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C, return stateFalse; } -void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state, +void CStringChecker::emitOverlapBug(CheckerContext &C, const ProgramState *state, const Stmt *First, const Stmt *Second) const { ExplodedNode *N = C.generateSink(state); if (!N) @@ -489,8 +517,8 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state, C.EmitReport(report); } -const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C, - const GRState *state, +const ProgramState *CStringChecker::checkAdditionOverflow(CheckerContext &C, + const ProgramState *state, NonLoc left, NonLoc right) const { // If a previous check has failed, propagate the failure. @@ -521,7 +549,7 @@ const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C, SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left, *maxMinusRightNL, cmpTy); - const GRState *stateOverflow, *stateOkay; + const ProgramState *stateOverflow, *stateOkay; llvm::tie(stateOverflow, stateOkay) = state->assume(cast<DefinedOrUnknownSVal>(willOverflow)); @@ -557,7 +585,7 @@ const GRState *CStringChecker::checkAdditionOverflow(CheckerContext &C, return state; } -const GRState *CStringChecker::setCStringLength(const GRState *state, +const ProgramState *CStringChecker::setCStringLength(const ProgramState *state, const MemRegion *MR, SVal strLength) { assert(!strLength.isUndef() && "Attempt to set an undefined string length"); @@ -598,7 +626,7 @@ const GRState *CStringChecker::setCStringLength(const GRState *state, } SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, - const GRState *&state, + const ProgramState *&state, const Expr *Ex, const MemRegion *MR, bool hypothetical) { @@ -622,7 +650,7 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, return strLength; } -SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, +SVal CStringChecker::getCStringLength(CheckerContext &C, const ProgramState *&state, const Expr *Ex, SVal Buf, bool hypothetical) const { const MemRegion *MR = Buf.getAsRegion(); @@ -717,7 +745,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, } const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, - const GRState *&state, const Expr *expr, SVal val) const { + const ProgramState *&state, const Expr *expr, SVal val) const { // Get the memory region pointed to by the val. const MemRegion *bufRegion = val.getAsRegion(); @@ -736,8 +764,8 @@ const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, return strRegion->getStringLiteral(); } -const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C, - const GRState *state, +const ProgramState *CStringChecker::InvalidateBuffer(CheckerContext &C, + const ProgramState *state, const Expr *E, SVal V) { Loc *L = dyn_cast<Loc>(&V); if (!L) @@ -810,7 +838,7 @@ bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx, void CStringChecker::evalCopyCommon(CheckerContext &C, const CallExpr *CE, - const GRState *state, + const ProgramState *state, const Expr *Size, const Expr *Dest, const Expr *Source, bool Restricted, bool IsMempcpy) const { @@ -820,7 +848,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, SVal sizeVal = state->getSVal(Size); QualType sizeTy = Size->getType(); - const GRState *stateZeroSize, *stateNonZeroSize; + const ProgramState *stateZeroSize, *stateNonZeroSize; llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, sizeVal, sizeTy); @@ -912,7 +940,7 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { // void *memcpy(void *restrict dst, const void *restrict src, size_t n); // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); } @@ -921,7 +949,7 @@ void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); // The return value is a pointer to the byte following the last written byte. const Expr *Dest = CE->getArg(0); - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true); } @@ -930,7 +958,7 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { // void *memmove(void *dst, const void *src, size_t n); // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); } @@ -949,14 +977,14 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { const Expr *Right = CE->getArg(1); const Expr *Size = CE->getArg(2); - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); SValBuilder &svalBuilder = C.getSValBuilder(); // See if the size argument is zero. SVal sizeVal = state->getSVal(Size); QualType sizeTy = Size->getType(); - const GRState *stateZeroSize, *stateNonZeroSize; + const ProgramState *stateZeroSize, *stateNonZeroSize; llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, sizeVal, sizeTy); @@ -979,7 +1007,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { // See if they are the same. DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); - const GRState *StSameBuf, *StNotSameBuf; + const ProgramState *StSameBuf, *StNotSameBuf; llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); // If the two arguments might be the same buffer, we know the result is 0, @@ -1024,13 +1052,13 @@ void CStringChecker::evalstrnLength(CheckerContext &C, void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, bool IsStrnlen) const { CurrentFunctionDescription = "string length function"; - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); if (IsStrnlen) { const Expr *maxlenExpr = CE->getArg(1); SVal maxlenVal = state->getSVal(maxlenExpr); - const GRState *stateZeroSize, *stateNonZeroSize; + const ProgramState *stateZeroSize, *stateNonZeroSize; llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, maxlenVal, maxlenExpr->getType()); @@ -1082,7 +1110,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); if (strLengthNL && maxlenValNL) { - const GRState *stateStringTooLong, *stateStringNotTooLong; + const ProgramState *stateStringTooLong, *stateStringNotTooLong; // Check if the strLength is greater than the maxlen. llvm::tie(stateStringTooLong, stateStringNotTooLong) = @@ -1189,7 +1217,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, bool isBounded, bool isAppending) const { CurrentFunctionDescription = "string copy function"; - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); // Check that the destination is non-null. const Expr *Dst = CE->getArg(0); @@ -1239,7 +1267,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, // If we know both values, we might be able to figure out how much // we're copying. if (strLengthNL && lenValNL) { - const GRState *stateSourceTooLong, *stateSourceNotTooLong; + const ProgramState *stateSourceTooLong, *stateSourceNotTooLong; // Check if the max number to copy is less than the length of the src. // If the bound is equal to the source length, strncpy won't null- @@ -1512,7 +1540,7 @@ void CStringChecker::evalStrncasecmp(CheckerContext &C, void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, bool isBounded, bool ignoreCase) const { CurrentFunctionDescription = "string comparison function"; - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); // Check that the first string is non-null const Expr *s1 = CE->getArg(0); @@ -1547,7 +1575,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, // See if they are the same. SValBuilder &svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); - const GRState *StSameBuf, *StNotSameBuf; + const ProgramState *StSameBuf, *StNotSameBuf; llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); // If the two arguments might be the same buffer, we know the result is 0, @@ -1638,7 +1666,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { // Get the callee. All the functions we care about are C functions // with simple identifiers. - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); const Expr *Callee = CE->getCallee(); const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); @@ -1687,7 +1715,7 @@ bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { // Record string length for char a[] = "abc"; - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); I != E; ++I) { @@ -1721,13 +1749,13 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { C.addTransition(state); } -bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const { +bool CStringChecker::wantsRegionChangeUpdate(const ProgramState *state) const { CStringLength::EntryMap Entries = state->get<CStringLength>(); return !Entries.isEmpty(); } -const GRState * -CStringChecker::checkRegionChanges(const GRState *state, +const ProgramState * +CStringChecker::checkRegionChanges(const ProgramState *state, const StoreManager::InvalidatedSymbols *, const MemRegion * const *Begin, const MemRegion * const *End) const { @@ -1777,7 +1805,7 @@ CStringChecker::checkRegionChanges(const GRState *state, return state->set<CStringLength>(Entries); } -void CStringChecker::checkLiveSymbols(const GRState *state, +void CStringChecker::checkLiveSymbols(const ProgramState *state, SymbolReaper &SR) const { // Mark all symbols in our string length map as valid. CStringLength::EntryMap Entries = state->get<CStringLength>(); @@ -1797,7 +1825,7 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR, if (!SR.hasDeadSymbols()) return; - const GRState *state = C.getState(); + const ProgramState *state = C.getState(); CStringLength::EntryMap Entries = state->get<CStringLength>(); if (Entries.isEmpty()) return; |