Index: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -792,11 +792,6 @@ VerboseDesc += S; } - /// If the last piece of the report point to the header file, resets - /// the location of the report to be the last location in the main source - /// file. - void resetDiagnosticLocationToMainFile(); - StringRef getVerboseDescription() const { return VerboseDesc; } StringRef getShortDescription() const { @@ -807,11 +802,6 @@ StringRef getBugType() const { return BugType; } StringRef getCategory() const { return Category; } - /// Return the semantic context where an issue occurred. If the - /// issue occurs along a path, this represents the "central" area - /// where the bug manifests. - const Decl *getDeclWithIssue() const { return DeclWithIssue; } - using meta_iterator = std::deque::const_iterator; meta_iterator meta_begin() const { return OtherDesc.begin(); } @@ -826,10 +816,23 @@ return *ExecutedLines; } + /// Return the semantic context where an issue occurred. If the + /// issue occurs along a path, this represents the "central" area + /// where the bug manifests. + const Decl *getDeclWithIssue() const { return DeclWithIssue; } + + void setDeclWithIssue(const Decl *D) { + DeclWithIssue = D; + } + PathDiagnosticLocation getLocation() const { return Loc; } + void setLocation(PathDiagnosticLocation NewLoc) { + Loc = NewLoc; + } + /// Get the location on which the report should be uniqued. PathDiagnosticLocation getUniqueingLoc() const { return UniqueingLoc; Index: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -3125,6 +3125,71 @@ return Out; } +static PathDiagnosticCallPiece * +getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, + const SourceManager &SMgr) { + SourceLocation CallLoc = CP->callEnter.asLocation(); + + // If the call is within a macro, don't do anything (for now). + if (CallLoc.isMacroID()) + return nullptr; + + assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) && + "The call piece should not be in a header file."); + + // Check if CP represents a path through a function outside of the main file. + if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr)) + return CP; + + const PathPieces &Path = CP->path; + if (Path.empty()) + return nullptr; + + // Check if the last piece in the callee path is a call to a function outside + // of the main file. + if (auto *CPInner = dyn_cast(Path.back().get())) + return getFirstStackedCallToHeaderFile(CPInner, SMgr); + + // Otherwise, the last piece is in the main file. + return nullptr; +} + +static void resetDiagnosticLocationToMainFile(PathDiagnostic &PD) { + if (PD.path.empty()) + return; + + PathDiagnosticPiece *LastP = PD.path.back().get(); + assert(LastP); + const SourceManager &SMgr = LastP->getLocation().getManager(); + + // We only need to check if the report ends inside headers, if the last piece + // is a call piece. + if (auto *CP = dyn_cast(LastP)) { + CP = getFirstStackedCallToHeaderFile(CP, SMgr); + if (CP) { + // Mark the piece. + CP->setAsLastInMainSourceFile(); + + // Update the path diagnostic message. + const auto *ND = dyn_cast(CP->getCallee()); + if (ND) { + SmallString<200> buf; + llvm::raw_svector_ostream os(buf); + os << " (within a call to '" << ND->getDeclName() << "')"; + PD.appendToDesc(os.str()); + } + + // Reset the report containing declaration and location. + PD.setDeclWithIssue(CP->getCaller()); + PD.setLocation(CP->getLocation()); + + return; + } + } +} + + + std::unique_ptr PathSensitiveBugReporter::generateDiagnosticForConsumerMap( BugReport *exampleReport, ArrayRef consumers, @@ -3159,7 +3224,7 @@ const AnalyzerOptions &Opts = getAnalyzerOptions(); for (auto const &P : *Out) if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll) - P.second->resetDiagnosticLocationToMainFile(); + resetDiagnosticLocationToMainFile(*P.second); return Out; } Index: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -29,7 +29,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/None.h" @@ -130,69 +129,6 @@ UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)), path(pathImpl) {} -static PathDiagnosticCallPiece * -getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, - const SourceManager &SMgr) { - SourceLocation CallLoc = CP->callEnter.asLocation(); - - // If the call is within a macro, don't do anything (for now). - if (CallLoc.isMacroID()) - return nullptr; - - assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) && - "The call piece should not be in a header file."); - - // Check if CP represents a path through a function outside of the main file. - if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr)) - return CP; - - const PathPieces &Path = CP->path; - if (Path.empty()) - return nullptr; - - // Check if the last piece in the callee path is a call to a function outside - // of the main file. - if (auto *CPInner = dyn_cast(Path.back().get())) - return getFirstStackedCallToHeaderFile(CPInner, SMgr); - - // Otherwise, the last piece is in the main file. - return nullptr; -} - -void PathDiagnostic::resetDiagnosticLocationToMainFile() { - if (path.empty()) - return; - - PathDiagnosticPiece *LastP = path.back().get(); - assert(LastP); - const SourceManager &SMgr = LastP->getLocation().getManager(); - - // We only need to check if the report ends inside headers, if the last piece - // is a call piece. - if (auto *CP = dyn_cast(LastP)) { - CP = getFirstStackedCallToHeaderFile(CP, SMgr); - if (CP) { - // Mark the piece. - CP->setAsLastInMainSourceFile(); - - // Update the path diagnostic message. - const auto *ND = dyn_cast(CP->getCallee()); - if (ND) { - SmallString<200> buf; - llvm::raw_svector_ostream os(buf); - os << " (within a call to '" << ND->getDeclName() << "')"; - appendToDesc(os.str()); - } - - // Reset the report containing declaration and location. - DeclWithIssue = CP->getCaller(); - Loc = CP->getLocation(); - - return; - } - } -} - void PathDiagnosticConsumer::anchor() {} PathDiagnosticConsumer::~PathDiagnosticConsumer() {