diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r-- | lib/StaticAnalyzer/Core/AnalysisManager.cpp | 7 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 19 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporter.cpp | 135 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 74 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 67 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 15 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 125 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/MemRegion.cpp | 15 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 11 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PlistDiagnostics.cpp | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ProgramState.cpp | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 11 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SimpleConstraintManager.h | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 13 |
18 files changed, 296 insertions, 226 deletions
diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp index 747b73c..5798f01 100644 --- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -20,13 +20,16 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, - AnalyzerOptions &Options) + AnalyzerOptions &Options, + CodeInjector *injector) : AnaCtxMgr(Options.UnoptimizedCFG, /*AddImplicitDtors=*/true, /*AddInitializers=*/true, Options.includeTemporaryDtorsInCFG(), Options.shouldSynthesizeBodies(), - Options.shouldConditionalizeStaticInitializers()), + Options.shouldConditionalizeStaticInitializers(), + /*addCXXNewAllocator=*/true, + injector), Ctx(ctx), Diags(diags), LangOpts(lang), diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 7944c7e..d717e3f 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -23,7 +23,8 @@ using namespace llvm; AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { if (UserMode == UMK_NotSet) { - StringRef ModeStr(Config.GetOrCreateValue("mode", "deep").getValue()); + StringRef ModeStr = + Config.insert(std::make_pair("mode", "deep")).first->second; UserMode = llvm::StringSwitch<UserModeKind>(ModeStr) .Case("shallow", UMK_Shallow) .Case("deep", UMK_Deep) @@ -48,7 +49,8 @@ IPAKind AnalyzerOptions::getIPAMode() { assert(DefaultIPA); // Lookup the ipa configuration option, use the default from User Mode. - StringRef ModeStr(Config.GetOrCreateValue("ipa", DefaultIPA).getValue()); + StringRef ModeStr = + Config.insert(std::make_pair("ipa", DefaultIPA)).first->second; IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr) .Case("none", IPAK_None) .Case("basic-inlining", IPAK_BasicInlining) @@ -72,9 +74,9 @@ AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) { if (!CXXMemberInliningMode) { static const char *ModeKey = "c++-inlining"; - - StringRef ModeStr(Config.GetOrCreateValue(ModeKey, - "destructors").getValue()); + + StringRef ModeStr = + Config.insert(std::make_pair(ModeKey, "destructors")).first->second; CXXInlineableMemberKind &MutableMode = const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode); @@ -102,7 +104,8 @@ bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) { // FIXME: We should emit a warning here if the value is something other than // "true", "false", or the empty string (meaning the default value), // but the AnalyzerOptions doesn't have access to a diagnostic engine. - StringRef V(Config.GetOrCreateValue(Name, toString(DefaultVal)).getValue()); + StringRef V = + Config.insert(std::make_pair(Name, toString(DefaultVal))).first->second; return llvm::StringSwitch<bool>(V) .Case("true", true) .Case("false", false) @@ -200,8 +203,8 @@ int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) { SmallString<10> StrBuf; llvm::raw_svector_ostream OS(StrBuf); OS << DefaultVal; - - StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue()); + + StringRef V = Config.insert(std::make_pair(Name, OS.str())).first->second; int Res = DefaultVal; bool b = V.getAsInteger(10, Res); assert(!b && "analyzer-config option should be numeric"); diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 141a48b..dff81e3 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -499,10 +499,9 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { //===----------------------------------------------------------------------===// // "Visitors only" path diagnostic generation algorithm. //===----------------------------------------------------------------------===// -static bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, - PathDiagnosticBuilder &PDB, - const ExplodedNode *N, - ArrayRef<BugReporterVisitor *> visitors) { +static bool GenerateVisitorsOnlyPathDiagnostic( + PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, + ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) { // All path generation skips the very first node (the error node). // This is because there is special handling for the end-of-path note. N = N->getFirstPred(); @@ -511,11 +510,9 @@ static bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic &PD, BugReport *R = PDB.getBugReport(); while (const ExplodedNode *Pred = N->getFirstPred()) { - for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), - E = visitors.end(); - I != E; ++I) { + for (auto &V : visitors) { // Visit all the node pairs, but throw the path pieces away. - PathDiagnosticPiece *Piece = (*I)->VisitNode(N, Pred, PDB, *R); + PathDiagnosticPiece *Piece = V->VisitNode(N, Pred, PDB, *R); delete Piece; } @@ -556,11 +553,10 @@ static void updateStackPiecesWithMessage(PathDiagnosticPiece *P, static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); -static bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, - PathDiagnosticBuilder &PDB, - const ExplodedNode *N, - LocationContextMap &LCM, - ArrayRef<BugReporterVisitor *> visitors) { +static bool GenerateMinimalPathDiagnostic( + PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, + LocationContextMap &LCM, + ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) { SourceManager& SMgr = PDB.getSourceManager(); const LocationContext *LC = PDB.LC; @@ -870,10 +866,8 @@ static bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, if (NextNode) { // Add diagnostic pieces from custom visitors. BugReport *R = PDB.getBugReport(); - for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), - E = visitors.end(); - I != E; ++I) { - if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { + for (auto &V : visitors) { + if (PathDiagnosticPiece *p = V->VisitNode(N, NextNode, PDB, *R)) { PD.getActivePath().push_front(p); updateStackPiecesWithMessage(p, CallStack); } @@ -1392,11 +1386,10 @@ static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) { // Top-level logic for generating extensive path diagnostics. //===----------------------------------------------------------------------===// -static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, - PathDiagnosticBuilder &PDB, - const ExplodedNode *N, - LocationContextMap &LCM, - ArrayRef<BugReporterVisitor *> visitors) { +static bool GenerateExtensivePathDiagnostic( + PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, + LocationContextMap &LCM, + ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) { EdgeBuilder EB(PD, PDB); const SourceManager& SM = PDB.getSourceManager(); StackDiagVector CallStack; @@ -1573,10 +1566,8 @@ static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, // Add pieces from custom visitors. BugReport *R = PDB.getBugReport(); - for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), - E = visitors.end(); - I != E; ++I) { - if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *R)) { + for (auto &V : visitors) { + if (PathDiagnosticPiece *p = V->VisitNode(N, NextNode, PDB, *R)) { const PathDiagnosticLocation &Loc = p->getLocation(); EB.addEdge(Loc, true); PD.getActivePath().push_front(p); @@ -1635,12 +1626,10 @@ static const char StrLoopRangeEmpty[] = static const char StrLoopCollectionEmpty[] = "Loop body skipped when collection is empty"; -static bool -GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, - PathDiagnosticBuilder &PDB, - const ExplodedNode *N, - LocationContextMap &LCM, - ArrayRef<BugReporterVisitor *> visitors) { +static bool GenerateAlternateExtensivePathDiagnostic( + PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, + LocationContextMap &LCM, + ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors) { BugReport *report = PDB.getBugReport(); const SourceManager& SM = PDB.getSourceManager(); @@ -1867,10 +1856,8 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD, continue; // Add pieces from custom visitors. - for (ArrayRef<BugReporterVisitor *>::iterator I = visitors.begin(), - E = visitors.end(); - I != E; ++I) { - if (PathDiagnosticPiece *p = (*I)->VisitNode(N, NextNode, PDB, *report)) { + for (auto &V : visitors) { + if (PathDiagnosticPiece *p = V->VisitNode(N, NextNode, PDB, *report)) { addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC); PD.getActivePath().push_front(p); updateStackPiecesWithMessage(p, CallStack); @@ -2547,7 +2534,7 @@ void BuiltinBug::anchor() {} void BugReport::NodeResolver::anchor() {} -void BugReport::addVisitor(BugReporterVisitor* visitor) { +void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) { if (!visitor) return; @@ -2555,20 +2542,15 @@ void BugReport::addVisitor(BugReporterVisitor* visitor) { visitor->Profile(ID); void *InsertPos; - if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) { - delete visitor; + if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) return; - } - CallbacksSet.InsertNode(visitor, InsertPos); - Callbacks.push_back(visitor); + CallbacksSet.InsertNode(visitor.get(), InsertPos); + Callbacks.push_back(std::move(visitor)); ++ConfigurationChangeToken; } BugReport::~BugReport() { - for (visitor_iterator I = visitor_begin(), E = visitor_end(); I != E; ++I) { - delete *I; - } while (!interestingSymbols.empty()) { popInterestingSymbolsAndRegions(); } @@ -2874,7 +2856,7 @@ TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph, // The trimmed graph is created in the body of the constructor to ensure // that the DenseMaps have been initialized already. InterExplodedGraphMap ForwardMap; - G.reset(OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap)); + G = OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap); // Find the (first) error node in the trimmed graph. We just need to consult // the node map which maps from nodes in the original graph to nodes @@ -2938,8 +2920,7 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) { // Create a new graph with a single path. This is the graph // that will be returned to the caller. - ExplodedGraph *GNew = new ExplodedGraph(); - GraphWrapper.Graph.reset(GNew); + auto GNew = llvm::make_unique<ExplodedGraph>(); GraphWrapper.BackMap.clear(); // Now walk from the error node up the BFS path, always taking the @@ -2976,6 +2957,8 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) { PriorityCompare<false>(PriorityMap)); } + GraphWrapper.Graph = std::move(GNew); + return true; } @@ -3126,9 +3109,9 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, const ExplodedNode *N = ErrorGraph.ErrorNode; // Register additional node visitors. - R->addVisitor(new NilReceiverBRVisitor()); - R->addVisitor(new ConditionBRVisitor()); - R->addVisitor(new LikelyFalsePositiveSuppressionBRVisitor()); + R->addVisitor(llvm::make_unique<NilReceiverBRVisitor>()); + R->addVisitor(llvm::make_unique<ConditionBRVisitor>()); + R->addVisitor(llvm::make_unique<LikelyFalsePositiveSuppressionBRVisitor>()); BugReport::VisitorList visitors; unsigned origReportConfigToken, finalReportConfigToken; @@ -3153,18 +3136,19 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, std::unique_ptr<PathDiagnosticPiece> LastPiece; for (BugReport::visitor_iterator I = visitors.begin(), E = visitors.end(); I != E; ++I) { - if (PathDiagnosticPiece *Piece = (*I)->getEndPath(PDB, N, *R)) { + if (std::unique_ptr<PathDiagnosticPiece> Piece = + (*I)->getEndPath(PDB, N, *R)) { assert (!LastPiece && "There can only be one final piece in a diagnostic."); - LastPiece.reset(Piece); + LastPiece = std::move(Piece); } } if (ActiveScheme != PathDiagnosticConsumer::None) { if (!LastPiece) - LastPiece.reset(BugReporterVisitor::getDefaultEndPath(PDB, N, *R)); + LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, N, *R); assert(LastPiece); - PD.setEndOfPath(LastPiece.release()); + PD.setEndOfPath(std::move(LastPiece)); } // Make sure we get a clean location context map so we don't @@ -3187,7 +3171,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, } // Clean up the visitors we used. - llvm::DeleteContainerPointers(visitors); + visitors.clear(); // Did anything change while generating this path? finalReportConfigToken = R->getConfigurationChangeToken(); @@ -3247,15 +3231,15 @@ void BugReporter::emitReport(BugReport* R) { // To guarantee memory release. std::unique_ptr<BugReport> UniqueR(R); - // Defensive checking: throw the bug away if it comes from a BodyFarm- - // generated body. We do this very early because report processing relies - // on the report's location being valid. - // FIXME: Valid bugs can occur in BodyFarm-generated bodies, so really we - // need to just find a reasonable location like we do later on with the path - // pieces. if (const ExplodedNode *E = R->getErrorNode()) { - const LocationContext *LCtx = E->getLocationContext(); - if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) + const AnalysisDeclContext *DeclCtx = + E->getLocationContext()->getAnalysisDeclContext(); + // The source of autosynthesized body can be handcrafted AST or a model + // file. The locations from handcrafted ASTs have no valid source locations + // and have to be discarded. Locations from model files should be preserved + // for processing and reporting. + if (DeclCtx->isBodyAutosynthesized() && + !DeclCtx->isBodyAutosynthesizedFromModelFile()) return; } @@ -3277,12 +3261,11 @@ void BugReporter::emitReport(BugReport* R) { BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); if (!EQ) { - EQ = new BugReportEquivClass(UniqueR.release()); + EQ = new BugReportEquivClass(std::move(UniqueR)); EQClasses.InsertNode(EQ, InsertPos); EQClassesVector.push_back(EQ); - } - else - EQ->AddReport(UniqueR.release()); + } else + EQ->AddReport(std::move(UniqueR)); } @@ -3449,13 +3432,13 @@ void BugReporter::FlushReport(BugReport *exampleReport, // of the issue. if (D->path.empty()) { PathDiagnosticLocation L = exampleReport->getLocation(getSourceManager()); - PathDiagnosticPiece *piece = - new PathDiagnosticEventPiece(L, exampleReport->getDescription()); + auto piece = llvm::make_unique<PathDiagnosticEventPiece>( + L, exampleReport->getDescription()); BugReport::ranges_iterator Beg, End; std::tie(Beg, End) = exampleReport->getRanges(); for ( ; Beg != End; ++Beg) piece->addRange(*Beg); - D->setEndOfPath(piece); + D->setEndOfPath(std::move(piece)); } // Get the meta data. @@ -3465,7 +3448,7 @@ void BugReporter::FlushReport(BugReport *exampleReport, D->addMeta(*i); } - PD.HandlePathDiagnostic(D.release()); + PD.HandlePathDiagnostic(std::move(D)); } void BugReporter::EmitBasicReport(const Decl *DeclWithIssue, @@ -3497,13 +3480,9 @@ BugType *BugReporter::getBugTypeForName(CheckName CheckName, StringRef name, SmallString<136> fullDesc; llvm::raw_svector_ostream(fullDesc) << CheckName.getName() << ":" << name << ":" << category; - llvm::StringMapEntry<BugType *> & - entry = StrBugTypes.GetOrCreateValue(fullDesc); - BugType *BT = entry.getValue(); - if (!BT) { + BugType *&BT = StrBugTypes[fullDesc]; + if (!BT) BT = new BugType(CheckName, name, category); - entry.setValue(BT); - } return BT; } diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 0503ace..2d56bd0 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -100,17 +100,14 @@ const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { // Definitions for bug reporter visitors. //===----------------------------------------------------------------------===// -PathDiagnosticPiece* +std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getEndPath(BugReporterContext &BRC, - const ExplodedNode *EndPathNode, - BugReport &BR) { + const ExplodedNode *EndPathNode, BugReport &BR) { return nullptr; } -PathDiagnosticPiece* -BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC, - const ExplodedNode *EndPathNode, - BugReport &BR) { +std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath( + BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(EndPathNode,BRC.getSourceManager()); @@ -119,13 +116,12 @@ BugReporterVisitor::getDefaultEndPath(BugReporterContext &BRC, // Only add the statement itself as a range if we didn't specify any // special ranges for this report. - PathDiagnosticPiece *P = new PathDiagnosticEventPiece(L, - BR.getDescription(), - Beg == End); + auto P = llvm::make_unique<PathDiagnosticEventPiece>(L, BR.getDescription(), + Beg == End); for (; Beg != End; ++Beg) P->addRange(*Beg); - return P; + return std::move(P); } @@ -222,7 +218,8 @@ public: EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue(); BR.markInteresting(CalleeContext); - BR.addVisitor(new ReturnVisitor(CalleeContext, EnableNullFPSuppression)); + BR.addVisitor(llvm::make_unique<ReturnVisitor>(CalleeContext, + EnableNullFPSuppression)); } /// Returns true if any counter-suppression heuristics are enabled for @@ -399,9 +396,9 @@ public: llvm_unreachable("Invalid visit mode!"); } - PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR) override { + std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) override { if (EnableNullFPSuppression) BR.markInvalid(ReturnVisitor::getTag(), StackFrame); return nullptr; @@ -569,8 +566,8 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) { if (Optional<KnownSVal> KV = State->getSVal(OriginalR).getAs<KnownSVal>()) - BR.addVisitor(new FindLastStoreBRVisitor(*KV, OriginalR, - EnableNullFPSuppression)); + BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>( + *KV, OriginalR, EnableNullFPSuppression)); } } } @@ -979,8 +976,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, // got initialized. if (const MemRegion *RR = getLocationRegionIfReference(Inner, N)) { if (Optional<KnownSVal> KV = LVal.getAs<KnownSVal>()) - report.addVisitor(new FindLastStoreBRVisitor(*KV, RR, - EnableNullFPSuppression)); + report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>( + *KV, RR, EnableNullFPSuppression)); } } @@ -990,30 +987,26 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, report.markInteresting(R); report.markInteresting(V); - report.addVisitor(new UndefOrNullArgVisitor(R)); + report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R)); // If the contents are symbolic, find out when they became null. - if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true)) { - BugReporterVisitor *ConstraintTracker = - new TrackConstraintBRVisitor(V.castAs<DefinedSVal>(), false); - report.addVisitor(ConstraintTracker); - } + if (V.getAsLocSymbol(/*IncludeBaseRegions*/ true)) + report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>( + V.castAs<DefinedSVal>(), false)); // Add visitor, which will suppress inline defensive checks. if (Optional<DefinedSVal> DV = V.getAs<DefinedSVal>()) { - if (!DV->isZeroConstant() && - LVState->isNull(*DV).isConstrainedTrue() && - EnableNullFPSuppression) { - BugReporterVisitor *IDCSuppressor = - new SuppressInlineDefensiveChecksVisitor(*DV, - LVNode); - report.addVisitor(IDCSuppressor); + if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() && + EnableNullFPSuppression) { + report.addVisitor( + llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV, + LVNode)); } } if (Optional<KnownSVal> KV = V.getAs<KnownSVal>()) - report.addVisitor(new FindLastStoreBRVisitor(*KV, R, - EnableNullFPSuppression)); + report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>( + *KV, R, EnableNullFPSuppression)); return true; } } @@ -1044,12 +1037,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, RVal = state->getSVal(L->getRegion()); const MemRegion *RegionRVal = RVal.getAsRegion(); - report.addVisitor(new UndefOrNullArgVisitor(L->getRegion())); + report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion())); if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) { report.markInteresting(RegionRVal); - report.addVisitor(new TrackConstraintBRVisitor( - loc::MemRegionVal(RegionRVal), false)); + report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>( + loc::MemRegionVal(RegionRVal), false)); } } @@ -1132,8 +1125,8 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) { // Register a new visitor with the BugReport. - BR.addVisitor(new FindLastStoreBRVisitor(V.castAs<KnownSVal>(), R, - EnableNullFPSuppression)); + BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>( + V.castAs<KnownSVal>(), R, EnableNullFPSuppression)); } } } @@ -1517,8 +1510,7 @@ static bool isInStdNamespace(const Decl *D) { return ND->isStdNamespace(); } - -PathDiagnosticPiece * +std::unique_ptr<PathDiagnosticPiece> LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) { diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 7e0670a..f673544 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -607,7 +607,7 @@ RuntimeDefinition CXXDestructorCall::getRuntimeDefinition() const { ArrayRef<ParmVarDecl*> ObjCMethodCall::parameters() const { const ObjCMethodDecl *D = getDecl(); if (!D) - return ArrayRef<ParmVarDecl*>(); + return None; return D->parameters(); } diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index 4623c35..7844ad4 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -14,6 +14,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" @@ -164,7 +165,7 @@ WorkList* WorkList::makeBFSBlockDFSContents() { bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps, ProgramStateRef InitState) { - if (G->num_roots() == 0) { // Initialize the analysis by constructing + if (G.num_roots() == 0) { // Initialize the analysis by constructing // the root if none exists. const CFGBlock *Entry = &(L->getCFG()->getEntry()); @@ -273,8 +274,8 @@ bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L, ProgramStateRef InitState, ExplodedNodeSet &Dst) { bool DidNotFinish = ExecuteWorkList(L, Steps, InitState); - for (ExplodedGraph::eop_iterator I = G->eop_begin(), - E = G->eop_end(); I != E; ++I) { + for (ExplodedGraph::eop_iterator I = G.eop_begin(), E = G.eop_end(); I != E; + ++I) { Dst.Add(*I); } return DidNotFinish; @@ -346,6 +347,11 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { default: llvm_unreachable("Analysis for this terminator not implemented."); + case Stmt::CXXBindTemporaryExprClass: + HandleCleanupTemporaryBranch( + cast<CXXBindTemporaryExpr>(B->getTerminator().getStmt()), B, Pred); + return; + // Model static initializers. case Stmt::DeclStmtClass: HandleStaticInit(cast<DeclStmt>(Term), B, Pred); @@ -461,6 +467,17 @@ void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term, enqueue(Dst); } +void CoreEngine::HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, + const CFGBlock *B, + ExplodedNode *Pred) { + assert(B->succ_size() == 2); + NodeBuilderContext Ctx(*this, B, Pred); + ExplodedNodeSet Dst; + SubEng.processCleanupTemporaryBranch(BTE, Ctx, Pred, Dst, *(B->succ_begin()), + *(B->succ_begin() + 1)); + // Enqueue the new frontier onto the worklist. + enqueue(Dst); +} void CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B, ExplodedNode *Pred) { @@ -494,13 +511,13 @@ void CoreEngine::generateNode(const ProgramPoint &Loc, ExplodedNode *Pred) { bool IsNew; - ExplodedNode *Node = G->getNode(Loc, State, false, &IsNew); + ExplodedNode *Node = G.getNode(Loc, State, false, &IsNew); if (Pred) - Node->addPredecessor(Pred, *G); // Link 'Node' with its predecessor. + Node->addPredecessor(Pred, G); // Link 'Node' with its predecessor. else { assert (IsNew); - G->addRoot(Node); // 'Node' has no predecessor. Make it a root. + G.addRoot(Node); // 'Node' has no predecessor. Make it a root. } // Only add 'Node' to the worklist if it was freshly generated. @@ -549,8 +566,8 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N, } bool IsNew; - ExplodedNode *Succ = G->getNode(Loc, N->getState(), false, &IsNew); - Succ->addPredecessor(N, *G); + ExplodedNode *Succ = G.getNode(Loc, N->getState(), false, &IsNew); + Succ->addPredecessor(N, G); if (IsNew) WList->enqueue(Succ, Block, Idx+1); @@ -565,8 +582,8 @@ ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) { CallExitBegin Loc(LocCtx); bool isNew; - ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew); - Node->addPredecessor(N, *G); + ExplodedNode *Node = G.getNode(Loc, N->getState(), false, &isNew); + Node->addPredecessor(N, G); return isNew ? Node : nullptr; } @@ -596,7 +613,7 @@ void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set) { WList->enqueue(N); } else { // TODO: We should run remove dead bindings here. - G->addEndOfPath(N); + G.addEndOfPath(N); NumPathsExplored++; } } @@ -611,8 +628,8 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, bool MarkAsSink) { HasGeneratedNodes = true; bool IsNew; - ExplodedNode *N = C.Eng.G->getNode(Loc, State, MarkAsSink, &IsNew); - N->addPredecessor(FromN, *C.Eng.G); + ExplodedNode *N = C.Eng.G.getNode(Loc, State, MarkAsSink, &IsNew); + N->addPredecessor(FromN, C.Eng.G); Frontier.erase(FromN); if (!IsNew) @@ -653,10 +670,10 @@ IndirectGotoNodeBuilder::generateNode(const iterator &I, ProgramStateRef St, bool IsSink) { bool IsNew; - ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(), - Pred->getLocationContext()), St, - IsSink, &IsNew); - Succ->addPredecessor(Pred, *Eng.G); + ExplodedNode *Succ = + Eng.G.getNode(BlockEdge(Src, I.getBlock(), Pred->getLocationContext()), + St, IsSink, &IsNew); + Succ->addPredecessor(Pred, Eng.G); if (!IsNew) return nullptr; @@ -673,10 +690,10 @@ SwitchNodeBuilder::generateCaseStmtNode(const iterator &I, ProgramStateRef St) { bool IsNew; - ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, I.getBlock(), - Pred->getLocationContext()), St, - false, &IsNew); - Succ->addPredecessor(Pred, *Eng.G); + ExplodedNode *Succ = + Eng.G.getNode(BlockEdge(Src, I.getBlock(), Pred->getLocationContext()), + St, false, &IsNew); + Succ->addPredecessor(Pred, Eng.G); if (!IsNew) return nullptr; @@ -698,10 +715,10 @@ SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St, return nullptr; bool IsNew; - ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock, - Pred->getLocationContext()), St, - IsSink, &IsNew); - Succ->addPredecessor(Pred, *Eng.G); + ExplodedNode *Succ = + Eng.G.getNode(BlockEdge(Src, DefaultBlock, Pred->getLocationContext()), + St, IsSink, &IsNew); + Succ->addPredecessor(Pred, Eng.G); if (!IsNew) return nullptr; diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp index 1c9a282..010d26e 100644 --- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -336,10 +336,10 @@ ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L, return V; } -ExplodedGraph * +std::unique_ptr<ExplodedGraph> ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks, InterExplodedGraphMap *ForwardMap, - InterExplodedGraphMap *InverseMap) const{ + InterExplodedGraphMap *InverseMap) const { if (Nodes.empty()) return nullptr; @@ -365,12 +365,9 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks, const ExplodedNode *N = WL1.pop_back_val(); // Have we already visited this node? If so, continue to the next one. - if (Pass1.count(N)) + if (!Pass1.insert(N).second) continue; - // Otherwise, mark this node as visited. - Pass1.insert(N); - // If this is a root enqueue it to the second worklist. if (N->Preds.empty()) { WL2.push_back(N); @@ -378,9 +375,7 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks, } // Visit our predecessors and enqueue them. - for (ExplodedNode::pred_iterator I = N->Preds.begin(), E = N->Preds.end(); - I != E; ++I) - WL1.push_back(*I); + WL1.append(N->Preds.begin(), N->Preds.end()); } // We didn't hit a root? Return with a null pointer for the new graph. @@ -388,7 +383,7 @@ ExplodedGraph::trim(ArrayRef<const NodeTy *> Sinks, return nullptr; // Create an empty graph. - ExplodedGraph* G = MakeEmptyGraph(); + std::unique_ptr<ExplodedGraph> G = MakeEmptyGraph(); // ===- Pass 2 (forward DFS to construct the new graph) -=== while (!WL2.empty()) { diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 4e4095c..4699df8 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -51,6 +51,15 @@ STATISTIC(NumMaxBlockCountReachedInInlined, STATISTIC(NumTimesRetriedWithoutInlining, "The # of times we re-evaluated a call without inlining"); +typedef std::pair<const CXXBindTemporaryExpr *, const StackFrameContext *> + CXXBindTemporaryContext; + +// Keeps track of whether CXXBindTemporaryExpr nodes have been evaluated. +// The StackFrameContext assures that nested calls due to inlined recursive +// functions do not interfere. +REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedTemporariesSet, + llvm::ImmutableSet<CXXBindTemporaryContext>) + //===----------------------------------------------------------------------===// // Engine construction and deletion. //===----------------------------------------------------------------------===// @@ -659,13 +668,71 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst) { + ExplodedNodeSet CleanDtorState; + StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx); + ProgramStateRef State = Pred->getState(); + if (State->contains<InitializedTemporariesSet>( + std::make_pair(D.getBindTemporaryExpr(), Pred->getStackFrame()))) { + // FIXME: Currently we insert temporary destructors for default parameters, + // but we don't insert the constructors. + State = State->remove<InitializedTemporariesSet>( + std::make_pair(D.getBindTemporaryExpr(), Pred->getStackFrame())); + } + StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State); QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType(); - - // FIXME: Inlining of temporary destructors is not supported yet anyway, so we - // just put a NULL region for now. This will need to be changed later. + // FIXME: Currently CleanDtorState can be empty here due to temporaries being + // bound to default parameters. + assert(CleanDtorState.size() <= 1); + ExplodedNode *CleanPred = + CleanDtorState.empty() ? Pred : *CleanDtorState.begin(); + // FIXME: Inlining of temporary destructors is not supported yet anyway, so + // we just put a NULL region for now. This will need to be changed later. VisitCXXDestructor(varType, nullptr, D.getBindTemporaryExpr(), - /*IsBase=*/ false, Pred, Dst); + /*IsBase=*/false, CleanPred, Dst); +} + +void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, + NodeBuilderContext &BldCtx, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) { + BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF); + if (Pred->getState()->contains<InitializedTemporariesSet>( + std::make_pair(BTE, Pred->getStackFrame()))) { + TempDtorBuilder.markInfeasible(false); + TempDtorBuilder.generateNode(Pred->getState(), true, Pred); + } else { + TempDtorBuilder.markInfeasible(true); + TempDtorBuilder.generateNode(Pred->getState(), false, Pred); + } +} + +void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, + ExplodedNodeSet &PreVisit, + ExplodedNodeSet &Dst) { + if (!getAnalysisManager().options.includeTemporaryDtorsInCFG()) { + // In case we don't have temporary destructors in the CFG, do not mark + // the initialization - we would otherwise never clean it up. + Dst = PreVisit; + return; + } + StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx); + for (ExplodedNode *Node : PreVisit) { + ProgramStateRef State = Node->getState(); + + if (!State->contains<InitializedTemporariesSet>( + std::make_pair(BTE, Node->getStackFrame()))) { + // FIXME: Currently the state might already contain the marker due to + // incorrect handling of temporaries bound to default parameters; for + // those, we currently skip the CXXBindTemporaryExpr but rely on adding + // temporary destructor nodes. + State = State->add<InitializedTemporariesSet>( + std::make_pair(BTE, Node->getStackFrame())); + } + StmtBldr.generateNode(BTE, Node, State); + } } void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, @@ -685,6 +752,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::CXXTryStmtClass: case Stmt::CXXTypeidExprClass: case Stmt::CXXUuidofExprClass: + case Stmt::CXXFoldExprClass: case Stmt::MSPropertyRefExprClass: case Stmt::CXXUnresolvedConstructExprClass: case Stmt::DependentScopeDeclRefExprClass: @@ -693,6 +761,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::ExpressionTraitExprClass: case Stmt::UnresolvedLookupExprClass: case Stmt::UnresolvedMemberExprClass: + case Stmt::TypoExprClass: case Stmt::CXXNoexceptExprClass: case Stmt::PackExpansionExprClass: case Stmt::SubstNonTypeTemplateParmPackExprClass: @@ -734,18 +803,24 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPParallelDirectiveClass: case Stmt::OMPSimdDirectiveClass: case Stmt::OMPForDirectiveClass: + case Stmt::OMPForSimdDirectiveClass: case Stmt::OMPSectionsDirectiveClass: case Stmt::OMPSectionDirectiveClass: case Stmt::OMPSingleDirectiveClass: case Stmt::OMPMasterDirectiveClass: case Stmt::OMPCriticalDirectiveClass: case Stmt::OMPParallelForDirectiveClass: + case Stmt::OMPParallelForSimdDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: case Stmt::OMPTaskDirectiveClass: case Stmt::OMPTaskyieldDirectiveClass: case Stmt::OMPBarrierDirectiveClass: case Stmt::OMPTaskwaitDirectiveClass: case Stmt::OMPFlushDirectiveClass: + case Stmt::OMPOrderedDirectiveClass: + case Stmt::OMPAtomicDirectiveClass: + case Stmt::OMPTargetDirectiveClass: + case Stmt::OMPTeamsDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: @@ -771,6 +846,17 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, // Handled due to fully linearised CFG. break; + case Stmt::CXXBindTemporaryExprClass: { + Bldr.takeNodes(Pred); + ExplodedNodeSet PreVisit; + getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this); + ExplodedNodeSet Next; + VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next); + getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this); + Bldr.addNodes(Dst); + break; + } + // Cases not handled yet; but will handle some day. case Stmt::DesignatedInitExprClass: case Stmt::ExtVectorElementExprClass: @@ -784,7 +870,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::ObjCProtocolExprClass: case Stmt::ObjCSelectorExprClass: case Stmt::ParenListExprClass: - case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::ConvertVectorExprClass: case Stmt::VAArgExprClass: @@ -796,6 +881,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, // Cases we intentionally don't evaluate, since they don't need // to be explicitly evaluated. + case Stmt::PredefinedExprClass: case Stmt::AddrLabelExprClass: case Stmt::AttributedStmtClass: case Stmt::IntegerLiteralClass: @@ -808,7 +894,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::SizeOfPackExprClass: case Stmt::StringLiteralClass: case Stmt::ObjCStringLiteralClass: - case Stmt::CXXBindTemporaryExprClass: case Stmt::CXXPseudoDestructorExprClass: case Stmt::SubstNonTypeTemplateParmExprClass: case Stmt::CXXNullPtrLiteralExprClass: { @@ -1403,11 +1488,8 @@ static const Stmt *ResolveCondition(const Stmt *Condition, if (!BO || !BO->isLogicalOp()) return Condition; - // FIXME: This is a workaround until we handle temporary destructor branches - // correctly; currently, temporary destructor branches lead to blocks that - // only have a terminator (and no statements). These blocks violate the - // invariant this function assumes. - if (B->getTerminator().isTemporaryDtorsBranch()) return Condition; + assert(!B->getTerminator().isTemporaryDtorsBranch() && + "Temporary destructor branches handled by processBindTemporary."); // For logical operations, we still have the case where some branches // use the traditional "merge" approach and others sink the branch @@ -1436,6 +1518,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) { + assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) && + "CXXBindTemporaryExprs are handled by processBindTemporary."); const LocationContext *LCtx = Pred->getLocationContext(); PrettyStackTraceLocationContext StackCrashInfo(LCtx); currBldrCtx = &BldCtx; @@ -1599,10 +1683,29 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) { builder.generateNode(I, state); } +#if 0 +static bool stackFrameDoesNotContainInitializedTemporaries(ExplodedNode &Pred) { + const StackFrameContext* Frame = Pred.getStackFrame(); + const llvm::ImmutableSet<CXXBindTemporaryContext> &Set = + Pred.getState()->get<InitializedTemporariesSet>(); + return std::find_if(Set.begin(), Set.end(), + [&](const CXXBindTemporaryContext &Ctx) { + if (Ctx.second == Frame) { + Ctx.first->dump(); + llvm::errs() << "\n"; + } + return Ctx.second == Frame; + }) == Set.end(); +} +#endif + /// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. void ExprEngine::processEndOfFunction(NodeBuilderContext& BC, ExplodedNode *Pred) { + // FIXME: Assert that stackFrameDoesNotContainInitializedTemporaries(*Pred)). + // We currently cannot enable this assert, as lifetime extended temporaries + // are not modelled correctly. PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext()); StateMgr.EndPath(Pred->getState()); diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index b1e9f06..88b5464 100644 --- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -20,8 +20,8 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/Rewrite/Core/Rewriter.h" -#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 22711f5..76cead6 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -1116,17 +1116,6 @@ const SymbolicRegion *MemRegion::getSymbolicBase() const { return nullptr; } -// FIXME: Merge with the implementation of the same method in Store.cpp -static bool IsCompleteType(ASTContext &Ctx, QualType Ty) { - if (const RecordType *RT = Ty->getAs<RecordType>()) { - const RecordDecl *D = RT->getDecl(); - if (!D->getDefinition()) - return false; - } - - return true; -} - RegionRawOffset ElementRegion::getAsArrayOffset() const { CharUnits offset = CharUnits::Zero(); const ElementRegion *ER = this; @@ -1148,7 +1137,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const { QualType elemType = ER->getElementType(); // If we are pointing to an incomplete type, go no further. - if (!IsCompleteType(C, elemType)) { + if (elemType->isIncompleteType()) { superR = ER; break; } @@ -1288,7 +1277,7 @@ RegionOffset MemRegion::getAsOffset() const { R = ER->getSuperRegion(); QualType EleTy = ER->getValueType(); - if (!IsCompleteType(getContext(), EleTy)) { + if (EleTy->isIncompleteType()) { // We cannot compute the offset of the base class. SymbolicOffsetBase = R; continue; diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index fd25bd8..b971fff 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -197,9 +197,8 @@ PathDiagnosticConsumer::~PathDiagnosticConsumer() { } } -void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) { - std::unique_ptr<PathDiagnostic> OwningD(D); - +void PathDiagnosticConsumer::HandlePathDiagnostic( + std::unique_ptr<PathDiagnostic> D) { if (!D || D->path.empty()) return; @@ -213,7 +212,7 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) { if (!supportsCrossFileDiagnostics()) { // Verify that the entire path is from the same FileID. FileID FID; - const SourceManager &SMgr = (*D->path.begin())->getLocation().getManager(); + const SourceManager &SMgr = D->path.front()->getLocation().getManager(); SmallVector<const PathPieces *, 5> WorkList; WorkList.push_back(&D->path); @@ -272,12 +271,12 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) { if (orig_size <= new_size) return; - assert(orig != D); + assert(orig != D.get()); Diags.RemoveNode(orig); delete orig; } - Diags.InsertNode(OwningD.release()); + Diags.InsertNode(D.release()); } static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y); diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp index ba3ad2e..a2c66f8 100644 --- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -42,7 +42,7 @@ namespace { void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags, FilesMade *filesMade) override; - virtual StringRef getName() const override { + StringRef getName() const override { return "PlistDiagnostics"; } @@ -338,10 +338,10 @@ void PlistDiagnostics::FlushDiagnosticsImpl( } // Open the file. - std::string ErrMsg; - llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg, llvm::sys::fs::F_Text); - if (!ErrMsg.empty()) { - llvm::errs() << "warning: could not create file: " << OutputFile << '\n'; + std::error_code EC; + llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::F_Text); + if (EC) { + llvm::errs() << "warning: could not create file: " << EC.message() << '\n'; return; } diff --git a/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h b/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h index c2af36f..e7cc23c 100644 --- a/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h +++ b/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_STATICANALYZER_PRETTYSTACKTRACELOCATIONCONTEXT_H -#define LLVM_CLANG_STATICANALYZER_PRETTYSTACKTRACELOCATIONCONTEXT_H +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CORE_PRETTYSTACKTRACELOCATIONCONTEXT_H +#define LLVM_CLANG_LIB_STATICANALYZER_CORE_PRETTYSTACKTRACELOCATIONCONTEXT_H #include "clang/Analysis/AnalysisContext.h" diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index 1714a27..60b32c7 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -75,8 +75,8 @@ ProgramStateManager::ProgramStateManager(ASTContext &Ctx, : Eng(SubEng), EnvMgr(alloc), GDMFactory(alloc), svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)), CallEventMgr(new CallEventManager(alloc)), Alloc(alloc) { - StoreMgr.reset((*CreateSMgr)(*this)); - ConstraintMgr.reset((*CreateCMgr)(*this, SubEng)); + StoreMgr = (*CreateSMgr)(*this); + ConstraintMgr = (*CreateCMgr)(*this, SubEng); } diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index 77578d3..170f7c0 100644 --- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -328,9 +328,9 @@ private: } // end anonymous namespace -ConstraintManager * +std::unique_ptr<ConstraintManager> ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) { - return new RangeConstraintManager(Eng, StMgr.getSValBuilder()); + return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder()); } const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St, diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 3bbbb34..4505622 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -609,16 +609,17 @@ public: // Part of public interface to class. // RegionStore creation. //===----------------------------------------------------------------------===// -StoreManager *ento::CreateRegionStoreManager(ProgramStateManager& StMgr) { +std::unique_ptr<StoreManager> +ento::CreateRegionStoreManager(ProgramStateManager &StMgr) { RegionStoreFeatures F = maximal_features_tag(); - return new RegionStoreManager(StMgr, F); + return llvm::make_unique<RegionStoreManager>(StMgr, F); } -StoreManager * +std::unique_ptr<StoreManager> ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) { RegionStoreFeatures F = minimal_features_tag(); F.enableFields(true); - return new RegionStoreManager(StMgr, F); + return llvm::make_unique<RegionStoreManager>(StMgr, F); } @@ -708,7 +709,7 @@ public: } bool AddToWorkList(WorkListElement E, const ClusterBindings *C) { - if (C && !Visited.insert(C)) + if (C && !Visited.insert(C).second) return false; WL.push_back(E); return true; diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h index 21e2283..a72d1d4 100644 --- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h +++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_SIMPLE_CONSTRAINT_MANAGER_H -#define LLVM_CLANG_GR_SIMPLE_CONSTRAINT_MANAGER_H +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CORE_SIMPLECONSTRAINTMANAGER_H +#define LLVM_CLANG_LIB_STATICANALYZER_CORE_SIMPLECONSTRAINTMANAGER_H #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index e38be3e..99ec1e7 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -48,17 +48,6 @@ const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base, return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext()); } -// FIXME: Merge with the implementation of the same method in MemRegion.cpp -static bool IsCompleteType(ASTContext &Ctx, QualType Ty) { - if (const RecordType *RT = Ty->getAs<RecordType>()) { - const RecordDecl *D = RT->getDecl(); - if (!D->getDefinition()) - return false; - } - - return true; -} - StoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) { return StoreRef(store, *this); } @@ -196,7 +185,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) const MemRegion *newSuperR = nullptr; // We can only compute sizeof(PointeeTy) if it is a complete type. - if (IsCompleteType(Ctx, PointeeTy)) { + if (!PointeeTy->isIncompleteType()) { // Compute the size in **bytes**. CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy); if (!pointeeTySize.isZero()) { |