diff options
author | dim <dim@FreeBSD.org> | 2015-06-21 14:00:56 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-06-21 14:00:56 +0000 |
commit | 9dd834653b811ad20382e98a87dff824980c9916 (patch) | |
tree | a764184c2fc9486979b074250b013a0937ee64e5 /lib/StaticAnalyzer | |
parent | bb9760db9b86e93a638ed430d0a14785f7ff9064 (diff) | |
download | FreeBSD-src-9dd834653b811ad20382e98a87dff824980c9916.zip FreeBSD-src-9dd834653b811ad20382e98a87dff824980c9916.tar.gz |
Vendor import of clang trunk r240225:
https://llvm.org/svn/llvm-project/cfe/trunk@240225
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp | 25 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 74 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/ModelInjector.cpp | 2 |
7 files changed, 101 insertions, 10 deletions
diff --git a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp index d1938a0..4f0b7e5 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp @@ -29,7 +29,8 @@ using namespace ento; namespace { class ObjCContainersChecker : public Checker< check::PreStmt<CallExpr>, - check::PostStmt<CallExpr> > { + check::PostStmt<CallExpr>, + check::PointerEscape> { mutable std::unique_ptr<BugType> BT; inline void initBugType() const { if (!BT) @@ -52,6 +53,10 @@ public: void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + ProgramStateRef checkPointerEscape(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind) const; }; } // end anonymous namespace @@ -146,6 +151,24 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE, } } +ProgramStateRef +ObjCContainersChecker::checkPointerEscape(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind) const { + for (InvalidatedSymbols::const_iterator I = Escaped.begin(), + E = Escaped.end(); + I != E; ++I) { + SymbolRef Sym = *I; + // When a symbol for a mutable array escapes, we can't reason precisely + // about its size any more -- so remove it from the map. + // Note that we aren't notified here when a CFMutableArrayRef escapes as a + // CFArrayRef. This is because CFArrayRef is typedef'd as a pointer to a + // const-qualified type. + State = State->remove<ArraySizeMap>(Sym); + } + return State; +} /// Register checker. void ento::registerObjCContainersChecker(CheckerManager &mgr) { mgr.registerChecker<ObjCContainersChecker>(); diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 58c27d4..49eef23 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -906,6 +906,8 @@ static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) { case IncRef: case IncRefMsg: case MakeCollectable: + case UnretainedOutParameter: + case RetainedOutParameter: case MayEscape: case StopTracking: case StopTrackingHard: @@ -1335,7 +1337,18 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ, if (pd->hasAttr<NSConsumedAttr>()) Template->addArg(AF, parm_idx, DecRefMsg); else if (pd->hasAttr<CFConsumedAttr>()) - Template->addArg(AF, parm_idx, DecRef); + Template->addArg(AF, parm_idx, DecRef); + else if (pd->hasAttr<CFReturnsRetainedAttr>()) { + QualType PointeeTy = pd->getType()->getPointeeType(); + if (!PointeeTy.isNull()) + if (coreFoundation::isCFObjectRef(PointeeTy)) + Template->addArg(AF, parm_idx, RetainedOutParameter); + } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) { + QualType PointeeTy = pd->getType()->getPointeeType(); + if (!PointeeTy.isNull()) + if (coreFoundation::isCFObjectRef(PointeeTy)) + Template->addArg(AF, parm_idx, UnretainedOutParameter); + } } QualType RetTy = FD->getReturnType(); @@ -1366,7 +1379,17 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ, Template->addArg(AF, parm_idx, DecRefMsg); else if (pd->hasAttr<CFConsumedAttr>()) { Template->addArg(AF, parm_idx, DecRef); - } + } else if (pd->hasAttr<CFReturnsRetainedAttr>()) { + QualType PointeeTy = pd->getType()->getPointeeType(); + if (!PointeeTy.isNull()) + if (coreFoundation::isCFObjectRef(PointeeTy)) + Template->addArg(AF, parm_idx, RetainedOutParameter); + } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) { + QualType PointeeTy = pd->getType()->getPointeeType(); + if (!PointeeTy.isNull()) + if (coreFoundation::isCFObjectRef(PointeeTy)) + Template->addArg(AF, parm_idx, UnretainedOutParameter); + } } QualType RetTy = MD->getReturnType(); @@ -2746,7 +2769,6 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE, if (hasErr) { // FIXME: If we get an error during a bridge cast, should we report it? - // Should we assert that there is no error? return; } @@ -2951,6 +2973,40 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ, C.addTransition(state); } +static ProgramStateRef updateOutParameter(ProgramStateRef State, + SVal ArgVal, + ArgEffect Effect) { + auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion()); + if (!ArgRegion) + return State; + + QualType PointeeTy = ArgRegion->getValueType(); + if (!coreFoundation::isCFObjectRef(PointeeTy)) + return State; + + SVal PointeeVal = State->getSVal(ArgRegion); + SymbolRef Pointee = PointeeVal.getAsLocSymbol(); + if (!Pointee) + return State; + + switch (Effect) { + case UnretainedOutParameter: + State = setRefBinding(State, Pointee, + RefVal::makeNotOwned(RetEffect::CF, PointeeTy)); + break; + case RetainedOutParameter: + // Do nothing. Retained out parameters will either point to a +1 reference + // or NULL, but the way you check for failure differs depending on the API. + // Consequently, we don't have a good way to track them yet. + break; + + default: + llvm_unreachable("only for out parameters"); + } + + return State; +} + void RetainCountChecker::checkSummary(const RetainSummary &Summ, const CallEvent &CallOrMsg, CheckerContext &C) const { @@ -2964,9 +3020,12 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ, for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) { SVal V = CallOrMsg.getArgSVal(idx); - if (SymbolRef Sym = V.getAsLocSymbol()) { + ArgEffect Effect = Summ.getArg(idx); + if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) { + state = updateOutParameter(state, V, Effect); + } else if (SymbolRef Sym = V.getAsLocSymbol()) { if (const RefVal *T = getRefBinding(state, Sym)) { - state = updateSymbol(state, Sym, *T, Summ.getArg(idx), hasErr, C); + state = updateSymbol(state, Sym, *T, Effect, hasErr, C); if (hasErr) { ErrorRange = CallOrMsg.getArgSourceRange(idx); ErrorSym = Sym; @@ -3115,6 +3174,11 @@ RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym, case DecRefMsgAndStopTrackingHard: llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted"); + case UnretainedOutParameter: + case RetainedOutParameter: + llvm_unreachable("Applies to pointer-to-pointer parameters, which should " + "not have ref state."); + case Dealloc: // Any use of -dealloc in GC is *bad*. if (C.isObjCGCEnabled()) { diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index b906cc9..fa7884f 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1529,7 +1529,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, return nullptr; } else { - // If the the complete 'std' suppression is not enabled, suppress reports + // If the complete 'std' suppression is not enabled, suppress reports // from the 'std' namespace that are known to produce false positives. // The analyzer issues a false use-after-free when std::list::pop_front diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index f673544..8542f7d 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -785,7 +785,7 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const { if (E->isInstanceMessage()) { - // Find the the receiver type. + // Find the receiver type. const ObjCObjectPointerType *ReceiverT = nullptr; bool CanBeSubClassed = false; QualType SupersType = E->getSuperType(); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 8b7f18f..ef515fb 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -816,6 +816,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPTaskyieldDirectiveClass: case Stmt::OMPBarrierDirectiveClass: case Stmt::OMPTaskwaitDirectiveClass: + case Stmt::OMPTaskgroupDirectiveClass: case Stmt::OMPFlushDirectiveClass: case Stmt::OMPOrderedDirectiveClass: case Stmt::OMPAtomicDirectiveClass: @@ -859,6 +860,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, // Cases not handled yet; but will handle some day. case Stmt::DesignatedInitExprClass: + case Stmt::DesignatedInitUpdateExprClass: case Stmt::ExtVectorElementExprClass: case Stmt::ImaginaryLiteralClass: case Stmt::ObjCAtCatchStmtClass: @@ -891,6 +893,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::CXXBoolLiteralExprClass: case Stmt::ObjCBoolLiteralExprClass: case Stmt::FloatingLiteralClass: + case Stmt::NoInitExprClass: case Stmt::SizeOfPackExprClass: case Stmt::StringLiteralClass: case Stmt::ObjCStringLiteralClass: diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 3c1a3b4..cfcf7c6 100644 --- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -22,6 +22,7 @@ #include "clang/Rewrite/Core/Rewriter.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -306,7 +307,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D, FD, llvm::sys::fs::F_RW | llvm::sys::fs::F_Excl); - if (EC && EC != std::errc::file_exists) { + if (EC && EC != llvm::errc::file_exists) { llvm::errs() << "warning: could not create file '" << Model << "': " << EC.message() << '\n'; return; diff --git a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp index 699549f..ee2c3f5 100644 --- a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp +++ b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp @@ -76,7 +76,7 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { // Modules are parsed by a separate CompilerInstance, so this code mimics that // behavior for models - CompilerInstance Instance; + CompilerInstance Instance(CI.getPCHContainerOperations()); Instance.setInvocation(&*Invocation); Instance.createDiagnostics( new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), |