#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/ImmutableList.h"
namespace clang {
namespace ento {
-typedef llvm::SmallPtrSet<Decl*, 24> SetOfDecls;
-typedef llvm::SmallPtrSet<const Decl*, 24> SetOfConstDecls;
+typedef llvm::ImmutableList<Decl*> SetOfDecls;
+typedef llvm::DenseSet<const Decl*> SetOfConstDecls;
class FunctionSummariesTy {
struct FunctionSummary {
/// working with a PCH file.
SetOfDecls LocalTUDecls;
+ SetOfDecls::Factory LocalTUDeclsFactory;
+
// PD is owned by AnalysisManager.
PathDiagnosticConsumer *PD;
if (isa<ObjCMethodDecl>(*I))
continue;
- LocalTUDecls.insert(*I);
+ // We use an ImmutableList to avoid issues with invalidating iterators
+ // to the list while we are traversing it.
+ LocalTUDecls = LocalTUDeclsFactory.add(*I, LocalTUDecls);
}
}
// Build the Call Graph.
CallGraph CG;
// Add all the top level declarations to the graph.
+ //
+ // NOTE: We use an ImmutableList to avoid issues with invalidating iterators
+ // to the list while we are traversing it.
for (SetOfDecls::iterator I = LocalTUDecls.begin(),
E = LocalTUDecls.end(); I != E; ++I)
CG.addToCallGraph(*I);
// translation unit. This step is very important for performance. It ensures
// that we analyze the root functions before the externally available
// subroutines.
- std::queue<CallGraphNode*> BFSQueue;
+ std::deque<CallGraphNode*> BFSQueue;
for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
TI != TE; ++TI)
- BFSQueue.push(*TI);
+ BFSQueue.push_front(*TI);
// BFS over all of the functions, while skipping the ones inlined into
// the previously processed functions. Use external Visited set, which is
SmallPtrSet<CallGraphNode*,24> Visited;
while(!BFSQueue.empty()) {
CallGraphNode *N = BFSQueue.front();
- BFSQueue.pop();
+ BFSQueue.pop_front();
// Skip the functions which have been processed already or previously
// inlined.
(Mgr->InliningMode == All ? 0 : &VisitedCallees));
// Add the visited callees to the global visited set.
- for (SetOfConstDecls::const_iterator I = VisitedCallees.begin(),
- E = VisitedCallees.end(); I != E; ++I){
+ for (SetOfConstDecls::iterator I = VisitedCallees.begin(),
+ E = VisitedCallees.end(); I != E; ++I) {
CallGraphNode *VN = CG.getNode(*I);
if (VN)
Visited.insert(VN);
// Push the children into the queue.
for (CallGraphNode::const_iterator CI = N->begin(),
CE = N->end(); CI != CE; ++CI) {
- BFSQueue.push(*CI);
+ BFSQueue.push_front(*CI);
}
}
}
RecVisitorBR = &BR;
// Process all the top level declarations.
+ //
+ // NOTE: We use an ImmutableList to avoid issues with invalidating iterators
+ // to the list while we are traversing it.
+ //
for (SetOfDecls::iterator I = LocalTUDecls.begin(),
- E = LocalTUDecls.end(); I != E; ++I)
+ E = LocalTUDecls.end(); I != E; ++I) {
TraverseDecl(*I);
+ }
if (Mgr->shouldInlineCall())
HandleDeclsGallGraph();