PathDiagnostic.cpp revision 802e02463b880f53a6e645bde78cc412481ce9e0
1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===// 2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// 3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// The LLVM Compiler Infrastructure 4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// 5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// License. See LICENSE.TXT for details. 7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===// 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// 10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// This file defines the PathDiagnostic-related interfaces. 11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===// 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "clang/AST/Expr.h" 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/Decl.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/DeclObjC.h" 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/ParentMap.h" 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "clang/AST/StmtCXX.h" 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "llvm/ADT/SmallString.h" 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using namespace clang; 24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using namespace ento; 25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool PathDiagnosticMacroPiece::containsEvent() const { 27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end(); 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) I!=E; ++I) { 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (isa<PathDiagnosticEventPiece>(*I)) 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I)) 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (MP->containsEvent()) 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static StringRef StripTrailingDots(StringRef s) { 39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (StringRef::size_type i = s.size(); i != 0; --i) 40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (s[i - 1] != '.') 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return s.substr(0, i); 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ""; 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticPiece::PathDiagnosticPiece(StringRef s, 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Kind k, DisplayHint hint) 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : str(StripTrailingDots(s)), kind(k), Hint(hint) {} 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint) 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : kind(k), Hint(hint) {} 518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticPiece::~PathDiagnosticPiece() {} 538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {} 548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticCallEnterPiece::~PathDiagnosticCallEnterPiece() {} 558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticCallExitPiece::~PathDiagnosticCallExitPiece() {} 568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {} 578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {} 588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnostic::PathDiagnostic() {} 598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathPieces::~PathPieces() {} 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnostic::~PathDiagnostic() {} 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnostic::PathDiagnostic(StringRef bugtype, StringRef desc, 638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) StringRef category) 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : BugType(StripTrailingDots(bugtype)), 658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Desc(StripTrailingDots(desc)), 668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Category(StripTrailingDots(category)) {} 678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void PathDiagnosticConsumer::anchor() { } 698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticConsumer::~PathDiagnosticConsumer() { 718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Delete the contents of the FoldingSet if it isn't empty already. 728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (llvm::FoldingSet<PathDiagnostic>::iterator it = 738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Diags.begin(), et = Diags.end() ; it != et ; ++it) { 748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) delete &*it; 758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) { 798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!D) 808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (D->path.empty()) { 838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) delete D; 848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We need to flatten the locations (convert Stmt* to locations) because 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // the referenced statements may be freed by the time the diagnostics 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // are emitted. 90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) D->flattenLocations(); 91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Profile the node to see if we already have something matching it 93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) llvm::FoldingSetNodeID profile; 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) D->Profile(profile); 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) void *InsertPos = 0; 96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) { 98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Keep the PathDiagnostic with the shorter path. 99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (orig->path.size() <= D->path.size()) { 100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool shouldKeepOriginal = true; 101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (orig->path.size() == D->path.size()) { 102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Here we break ties in a fairly arbitrary, but deterministic, way. 103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) llvm::FoldingSetNodeID fullProfile, fullProfileOrig; 104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) D->FullProfile(fullProfile); 105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) orig->FullProfile(fullProfileOrig); 106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (fullProfile.ComputeHash() < fullProfileOrig.ComputeHash()) 107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) shouldKeepOriginal = false; 108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (shouldKeepOriginal) { 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delete D; 112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Diags.RemoveNode(orig); 116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delete orig; 117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Diags.InsertNode(D); 120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace { 124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)struct CompareDiagnostics { 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Compare if 'X' is "<" than 'Y'. 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const { 127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // First compare by location 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const FullSourceLoc &XLoc = X->getLocation().asLocation(); 129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const FullSourceLoc &YLoc = Y->getLocation().asLocation(); 130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (XLoc < YLoc) 131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (XLoc != YLoc) 133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Next, compare by bug type. 1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) StringRef XBugType = X->getBugType(); 1378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) StringRef YBugType = Y->getBugType(); 1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (XBugType < YBugType) 1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (XBugType != YBugType) 1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Next, compare by bug description. 1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) StringRef XDesc = X->getDescription(); 1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) StringRef YDesc = Y->getDescription(); 1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (XDesc < YDesc) 147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (XDesc != YDesc) 149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // FIXME: Further refine by comparing PathDiagnosticPieces? 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void 158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticConsumer::FlushDiagnostics(SmallVectorImpl<std::string> *Files) { 159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (flushed) 160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) flushed = true; 163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::vector<const PathDiagnostic *> BatchDiags; 165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(), 166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) et = Diags.end(); it != et; ++it) { 167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) BatchDiags.push_back(&*it); 168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Clear out the FoldingSet. 171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Diags.clear(); 172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Sort the diagnostics so that they are always emitted in a deterministic 174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // order. 175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!BatchDiags.empty()) 176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::sort(BatchDiags.begin(), BatchDiags.end(), CompareDiagnostics()); 177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FlushDiagnosticsImpl(BatchDiags, Files); 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Delete the flushed diagnostics. 181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(), 182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) et = BatchDiags.end(); it != et; ++it) { 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const PathDiagnostic *D = *it; 184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) delete D; 185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===// 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// PathDiagnosticLocation methods. 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//===----------------------------------------------------------------------===// 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static SourceLocation getValidSourceLocation(const Stmt* S, 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LocationOrAnalysisDeclContext LAC) { 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SourceLocation L = S->getLocStart(); 195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) assert(!LAC.isNull() && "A valid LocationContext or AnalysisDeclContext should " 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) "be passed to PathDiagnosticLocation upon creation."); 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // S might be a temporary statement that does not have a location in the 199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // source code, so find an enclosing statement and use it's location. 200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!L.isValid()) { 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) ParentMap *PM = 0; 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (LAC.is<const LocationContext*>()) 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PM = &LAC.get<const LocationContext*>()->getParentMap(); 205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) else 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PM = &LAC.get<AnalysisDeclContext*>()->getParentMap(); 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) while (!L.isValid()) { 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) S = PM->getParent(S); 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) L = S->getLocStart(); 2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 2128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return L; 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) PathDiagnosticLocation::createBegin(const Decl *D, 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SM) { 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(D->getLocStart(), SM, SingleLocK); 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PathDiagnosticLocation::createBegin(const Stmt *S, 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SM, 226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LocationOrAnalysisDeclContext LAC) { 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(getValidSourceLocation(S, LAC), 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SM, SingleLocK); 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO, 233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SM) { 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK); 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME, 239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SM) { 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK); 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS, 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SM) { 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SourceLocation L = CS->getLBracLoc(); 247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(L, SM, SingleLocK); 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS, 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SM) { 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SourceLocation L = CS->getRBracLoc(); 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(L, SM, SingleLocK); 255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PathDiagnosticLocation::createDeclBegin(const LocationContext *LC, 2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const SourceManager &SM) { 2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. 2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (const CompoundStmt *CS = 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody())) 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!CS->body_empty()) { 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SourceLocation Loc = (*CS->body_begin())->getLocStart(); 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(Loc, SM, SingleLocK); 266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(); 269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)PathDiagnosticLocation 272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PathDiagnosticLocation::createDeclEnd(const LocationContext *LC, 273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SM) { 274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SourceLocation L = LC->getDecl()->getBodyRBrace(); 275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return PathDiagnosticLocation(L, SM, SingleLocK); 2768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)PathDiagnosticLocation 2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) PathDiagnosticLocation::create(const ProgramPoint& P, 280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const SourceManager &SMng) { 281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const Stmt* S = 0; 283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CFGBlock *BSrc = BE->getSrc(); 285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) S = BSrc->getTerminatorCondition(); 286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 287 else if (const PostStmt *PS = dyn_cast<PostStmt>(&P)) { 288 S = PS->getStmt(); 289 } 290 291 return PathDiagnosticLocation(S, SMng, P.getLocationContext()); 292} 293 294PathDiagnosticLocation 295 PathDiagnosticLocation::createEndOfPath(const ExplodedNode* N, 296 const SourceManager &SM) { 297 assert(N && "Cannot create a location with a null node."); 298 299 const ExplodedNode *NI = N; 300 301 while (NI) { 302 ProgramPoint P = NI->getLocation(); 303 const LocationContext *LC = P.getLocationContext(); 304 if (const StmtPoint *PS = dyn_cast<StmtPoint>(&P)) 305 return PathDiagnosticLocation(PS->getStmt(), SM, LC); 306 else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { 307 const Stmt *Term = BE->getSrc()->getTerminator(); 308 assert(Term); 309 return PathDiagnosticLocation(Term, SM, LC); 310 } 311 NI = NI->succ_empty() ? 0 : *(NI->succ_begin()); 312 } 313 314 return createDeclEnd(N->getLocationContext(), SM); 315} 316 317PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation( 318 const PathDiagnosticLocation &PDL) { 319 FullSourceLoc L = PDL.asLocation(); 320 return PathDiagnosticLocation(L, L.getManager(), SingleLocK); 321} 322 323FullSourceLoc 324 PathDiagnosticLocation::genLocation(SourceLocation L, 325 LocationOrAnalysisDeclContext LAC) const { 326 assert(isValid()); 327 // Note that we want a 'switch' here so that the compiler can warn us in 328 // case we add more cases. 329 switch (K) { 330 case SingleLocK: 331 case RangeK: 332 break; 333 case StmtK: 334 // Defensive checking. 335 if (!S) 336 break; 337 return FullSourceLoc(getValidSourceLocation(S, LAC), 338 const_cast<SourceManager&>(*SM)); 339 case DeclK: 340 // Defensive checking. 341 if (!D) 342 break; 343 return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM)); 344 } 345 346 return FullSourceLoc(L, const_cast<SourceManager&>(*SM)); 347} 348 349PathDiagnosticRange 350 PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const { 351 assert(isValid()); 352 // Note that we want a 'switch' here so that the compiler can warn us in 353 // case we add more cases. 354 switch (K) { 355 case SingleLocK: 356 return PathDiagnosticRange(SourceRange(Loc,Loc), true); 357 case RangeK: 358 break; 359 case StmtK: { 360 const Stmt *S = asStmt(); 361 switch (S->getStmtClass()) { 362 default: 363 break; 364 case Stmt::DeclStmtClass: { 365 const DeclStmt *DS = cast<DeclStmt>(S); 366 if (DS->isSingleDecl()) { 367 // Should always be the case, but we'll be defensive. 368 return SourceRange(DS->getLocStart(), 369 DS->getSingleDecl()->getLocation()); 370 } 371 break; 372 } 373 // FIXME: Provide better range information for different 374 // terminators. 375 case Stmt::IfStmtClass: 376 case Stmt::WhileStmtClass: 377 case Stmt::DoStmtClass: 378 case Stmt::ForStmtClass: 379 case Stmt::ChooseExprClass: 380 case Stmt::IndirectGotoStmtClass: 381 case Stmt::SwitchStmtClass: 382 case Stmt::BinaryConditionalOperatorClass: 383 case Stmt::ConditionalOperatorClass: 384 case Stmt::ObjCForCollectionStmtClass: { 385 SourceLocation L = getValidSourceLocation(S, LAC); 386 return SourceRange(L, L); 387 } 388 } 389 SourceRange R = S->getSourceRange(); 390 if (R.isValid()) 391 return R; 392 break; 393 } 394 case DeclK: 395 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 396 return MD->getSourceRange(); 397 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 398 if (Stmt *Body = FD->getBody()) 399 return Body->getSourceRange(); 400 } 401 else { 402 SourceLocation L = D->getLocation(); 403 return PathDiagnosticRange(SourceRange(L, L), true); 404 } 405 } 406 407 return SourceRange(Loc,Loc); 408} 409 410void PathDiagnosticLocation::flatten() { 411 if (K == StmtK) { 412 K = RangeK; 413 S = 0; 414 D = 0; 415 } 416 else if (K == DeclK) { 417 K = SingleLocK; 418 S = 0; 419 D = 0; 420 } 421} 422 423//===----------------------------------------------------------------------===// 424// FoldingSet profiling methods. 425//===----------------------------------------------------------------------===// 426 427void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const { 428 ID.AddInteger(Range.getBegin().getRawEncoding()); 429 ID.AddInteger(Range.getEnd().getRawEncoding()); 430 ID.AddInteger(Loc.getRawEncoding()); 431 return; 432} 433 434void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const { 435 ID.AddInteger((unsigned) getKind()); 436 ID.AddString(str); 437 // FIXME: Add profiling support for code hints. 438 ID.AddInteger((unsigned) getDisplayHint()); 439 for (range_iterator I = ranges_begin(), E = ranges_end(); I != E; ++I) { 440 ID.AddInteger(I->getBegin().getRawEncoding()); 441 ID.AddInteger(I->getEnd().getRawEncoding()); 442 } 443} 444 445void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const { 446 PathDiagnosticPiece::Profile(ID); 447 ID.Add(Pos); 448} 449 450void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const { 451 PathDiagnosticPiece::Profile(ID); 452 for (const_iterator I = begin(), E = end(); I != E; ++I) 453 ID.Add(*I); 454} 455 456void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const { 457 PathDiagnosticSpotPiece::Profile(ID); 458 for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end(); 459 I != E; ++I) 460 ID.Add(**I); 461} 462 463void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const { 464 if (!path.empty()) 465 getLocation().Profile(ID); 466 ID.AddString(BugType); 467 ID.AddString(Desc); 468 ID.AddString(Category); 469} 470 471void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const { 472 Profile(ID); 473 for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I) 474 ID.Add(**I); 475 for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I) 476 ID.AddString(*I); 477} 478