summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r--clang/lib/Analysis/BugReporter.cpp96
-rw-r--r--clang/lib/Analysis/PathDiagnostic.cpp26
2 files changed, 122 insertions, 0 deletions
diff --git a/clang/lib/Analysis/BugReporter.cpp b/clang/lib/Analysis/BugReporter.cpp
index 12e50d34601..86ee484f36c 100644
--- a/clang/lib/Analysis/BugReporter.cpp
+++ b/clang/lib/Analysis/BugReporter.cpp
@@ -563,6 +563,98 @@ public:
};
}
+/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
+/// and collapses PathDiagosticPieces that are expanded by macros.
+static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM) {
+ typedef std::vector<std::pair<PathDiagnosticMacroPiece*, SourceLocation> >
+ MacroStackTy;
+
+ typedef std::vector<PathDiagnosticPiece*>
+ PiecesTy;
+
+ MacroStackTy MacroStack;
+ PiecesTy Pieces;
+
+ for (PathDiagnostic::iterator I = PD.begin(), E = PD.end(); I!=E; ++I) {
+ // Get the location of the PathDiagnosticPiece.
+ const FullSourceLoc Loc = I->getLocation();
+
+ // Determine the instantiation location, which is the location we group
+ // related PathDiagnosticPieces.
+ SourceLocation InstantiationLoc = Loc.isMacroID() ?
+ SM.getInstantiationLoc(Loc) :
+ SourceLocation();
+
+ if (Loc.isFileID()) {
+ MacroStack.clear();
+ Pieces.push_back(&*I);
+ continue;
+ }
+
+ assert(Loc.isMacroID());
+
+ // Is the PathDiagnosticPiece within the same macro group?
+ if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
+ MacroStack.back().first->push_back(&*I);
+ continue;
+ }
+
+ // We aren't in the same group. Are we descending into a new macro
+ // or are part of an old one?
+ PathDiagnosticMacroPiece *MacroGroup = 0;
+
+ SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
+ SM.getInstantiationLoc(Loc) :
+ SourceLocation();
+
+ // Walk the entire macro stack.
+ while (!MacroStack.empty()) {
+ if (InstantiationLoc == MacroStack.back().second) {
+ MacroGroup = MacroStack.back().first;
+ break;
+ }
+
+ if (ParentInstantiationLoc == MacroStack.back().second) {
+ MacroGroup = MacroStack.back().first;
+ break;
+ }
+
+ MacroStack.pop_back();
+ }
+
+ if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
+ // Create a new macro group and add it to the stack.
+ PathDiagnosticMacroPiece *NewGroup = new PathDiagnosticMacroPiece(Loc);
+
+ if (MacroGroup)
+ MacroGroup->push_back(NewGroup);
+ else {
+ assert(InstantiationLoc.isFileID());
+ Pieces.push_back(NewGroup);
+ }
+
+ MacroGroup = NewGroup;
+ MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
+ }
+
+ // Finally, add the PathDiagnosticPiece to the group.
+ MacroGroup->push_back(&*I);
+ }
+
+ // Now take the pieces and construct a new PathDiagnostic.
+ PD.resetPath(false);
+
+ for (PiecesTy::iterator I=Pieces.begin(), E=Pieces.end(); I!=E; ++I) {
+ if (PathDiagnosticMacroPiece *MP=dyn_cast<PathDiagnosticMacroPiece>(*I))
+ if (!MP->containsEvent()) {
+ delete MP;
+ continue;
+ }
+
+ PD.push_back(*I);
+ }
+}
+
void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
BugReportEquivClass& EQ) {
@@ -799,6 +891,10 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
getStateManager().iterBindings(N->getState(), SNS);
}
}
+
+ // After constructing the full PathDiagnostic, do a pass over it to compact
+ // PathDiagnosticPieces that occur within a macro.
+ CompactPathDiagnostic(PD, getSourceManager());
}
diff --git a/clang/lib/Analysis/PathDiagnostic.cpp b/clang/lib/Analysis/PathDiagnostic.cpp
index ae53ed9dbf0..a504e80b596 100644
--- a/clang/lib/Analysis/PathDiagnostic.cpp
+++ b/clang/lib/Analysis/PathDiagnostic.cpp
@@ -13,8 +13,24 @@
#include "clang/Analysis/PathDiagnostic.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Casting.h"
#include <sstream>
using namespace clang;
+using llvm::dyn_cast;
+using llvm::isa;
+
+bool PathDiagnosticMacroPiece::containsEvent() const {
+ for (const_iterator I = begin(), E = end(); I!=E; ++I) {
+ if (isa<PathDiagnosticEventPiece>(*I))
+ return true;
+
+ if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
+ if (MP->containsEvent())
+ return true;
+ }
+
+ return false;
+}
static size_t GetNumCharsToLastNonPeriod(const char *s) {
const char *start = s;
@@ -63,6 +79,16 @@ PathDiagnostic::~PathDiagnostic() {
for (iterator I = begin(), E = end(); I != E; ++I) delete &*I;
}
+void PathDiagnostic::resetPath(bool deletePieces) {
+ Size = 0;
+
+ if (deletePieces)
+ for (iterator I=begin(), E=end(); I!=E; ++I)
+ delete &*I;
+
+ path.clear();
+}
+
PathDiagnostic::PathDiagnostic(const char* bugtype, const char* desc,
const char* category)
OpenPOWER on IntegriCloud