Rewrite control-flow diagnostic generation "extensive" algorithm using "edge
contexts". This allows us to use a stack of contexts to keep track of what control-flow pieces to include when exiting blocks like 'if', 'for', etc. llvm-svn: 68473
This commit is contained in:
		
							parent
							
								
									2ed6a20934
								
							
						
					
					
						commit
						c4c9ed0f9b
					
				| 
						 | 
				
			
			@ -456,6 +456,8 @@ public:
 | 
			
		|||
// "Minimal" path diagnostic generation algorithm.
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
static void CompactPathDiagnostic(PathDiagnostic &PD, const SourceManager& SM);
 | 
			
		||||
 | 
			
		||||
static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
 | 
			
		||||
                                          PathDiagnosticBuilder &PDB,
 | 
			
		||||
                                          const ExplodedNode<GRState> *N) {
 | 
			
		||||
| 
						 | 
				
			
			@ -740,6 +742,10 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
      PDB.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, PDB.getSourceManager());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
| 
						 | 
				
			
			@ -748,7 +754,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
 | 
			
		||||
static bool IsControlFlowExpr(const Stmt *S) {
 | 
			
		||||
  const Expr *E = dyn_cast<Expr>(S);
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  if (!E)
 | 
			
		||||
    return false;
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			@ -764,12 +770,264 @@ static bool IsControlFlowExpr(const Stmt *S) {
 | 
			
		|||
  return false;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
class VISIBILITY_HIDDEN EdgeBuilder {
 | 
			
		||||
  std::vector<PathDiagnosticLocation> CLocs;
 | 
			
		||||
  typedef std::vector<PathDiagnosticLocation>::iterator iterator;
 | 
			
		||||
  PathDiagnostic &PD;
 | 
			
		||||
  PathDiagnosticBuilder &PDB;
 | 
			
		||||
  PathDiagnosticLocation PrevLoc;
 | 
			
		||||
 | 
			
		||||
  bool containsLocation(const PathDiagnosticLocation &Container,
 | 
			
		||||
                        const PathDiagnosticLocation &Containee);
 | 
			
		||||
  
 | 
			
		||||
  PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L);
 | 
			
		||||
  void rawAddEdge(PathDiagnosticLocation NewLoc);
 | 
			
		||||
  
 | 
			
		||||
  void popLocation() {
 | 
			
		||||
    rawAddEdge(CLocs.back());
 | 
			
		||||
    CLocs.pop_back();
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  PathDiagnosticLocation IgnoreParens(const PathDiagnosticLocation &L);  
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
 | 
			
		||||
    : PD(pd), PDB(pdb) {
 | 
			
		||||
      CLocs.push_back(PathDiagnosticLocation(&PDB.getCodeDecl(),
 | 
			
		||||
                                             PDB.getSourceManager()));
 | 
			
		||||
      if (!PD.empty()) {
 | 
			
		||||
        PrevLoc = PD.begin()->getLocation();
 | 
			
		||||
        
 | 
			
		||||
        if (const Stmt *S = PrevLoc.asStmt())
 | 
			
		||||
          addContext(PDB.getEnclosingStmtLocation(S).asStmt());
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ~EdgeBuilder() {
 | 
			
		||||
    while (!CLocs.empty()) popLocation();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
 | 
			
		||||
  
 | 
			
		||||
  void addEdge(const Stmt *S, bool alwaysAdd = false) {
 | 
			
		||||
    addEdge(PathDiagnosticLocation(S, PDB.getSourceManager()), alwaysAdd);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  void addContext(const Stmt *S);
 | 
			
		||||
};  
 | 
			
		||||
} // end anonymous namespace
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PathDiagnosticLocation
 | 
			
		||||
EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) {
 | 
			
		||||
  if (const Stmt *S = L.asStmt()) {
 | 
			
		||||
    if (IsControlFlowExpr(S))
 | 
			
		||||
      return L;
 | 
			
		||||
    
 | 
			
		||||
    return PDB.getEnclosingStmtLocation(S);    
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  return L;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
 | 
			
		||||
                                   const PathDiagnosticLocation &Containee) {
 | 
			
		||||
 | 
			
		||||
  if (Container == Containee)
 | 
			
		||||
    return true;
 | 
			
		||||
    
 | 
			
		||||
  if (Container.asDecl())
 | 
			
		||||
    return true;
 | 
			
		||||
  
 | 
			
		||||
  if (const Stmt *S = Containee.asStmt())
 | 
			
		||||
    if (const Stmt *ContainerS = Container.asStmt()) {
 | 
			
		||||
      while (S) {
 | 
			
		||||
        if (S == ContainerS)
 | 
			
		||||
          return true;
 | 
			
		||||
        S = PDB.getParent(S);
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  // Less accurate: compare using source ranges.
 | 
			
		||||
  SourceRange ContainerR = Container.asRange();
 | 
			
		||||
  SourceRange ContaineeR = Containee.asRange();
 | 
			
		||||
  
 | 
			
		||||
  SourceManager &SM = PDB.getSourceManager();
 | 
			
		||||
  SourceLocation ContainerRBeg = SM.getInstantiationLoc(ContainerR.getBegin());
 | 
			
		||||
  SourceLocation ContainerREnd = SM.getInstantiationLoc(ContainerR.getEnd());
 | 
			
		||||
  SourceLocation ContaineeRBeg = SM.getInstantiationLoc(ContaineeR.getBegin());
 | 
			
		||||
  SourceLocation ContaineeREnd = SM.getInstantiationLoc(ContaineeR.getEnd());
 | 
			
		||||
  
 | 
			
		||||
  unsigned ContainerBegLine = SM.getInstantiationLineNumber(ContainerRBeg);
 | 
			
		||||
  unsigned ContainerEndLine = SM.getInstantiationLineNumber(ContainerREnd);
 | 
			
		||||
  unsigned ContaineeBegLine = SM.getInstantiationLineNumber(ContaineeRBeg);
 | 
			
		||||
  unsigned ContaineeEndLine = SM.getInstantiationLineNumber(ContaineeREnd);
 | 
			
		||||
  
 | 
			
		||||
  assert(ContainerBegLine <= ContainerEndLine);
 | 
			
		||||
  assert(ContaineeBegLine <= ContaineeEndLine);  
 | 
			
		||||
  
 | 
			
		||||
  return (ContainerBegLine <= ContaineeBegLine &&
 | 
			
		||||
          ContainerEndLine >= ContaineeEndLine &&
 | 
			
		||||
          (ContainerBegLine != ContaineeBegLine ||
 | 
			
		||||
           SM.getInstantiationColumnNumber(ContainerRBeg) <= 
 | 
			
		||||
           SM.getInstantiationColumnNumber(ContaineeRBeg)) &&
 | 
			
		||||
          (ContainerEndLine != ContaineeEndLine ||
 | 
			
		||||
           SM.getInstantiationColumnNumber(ContainerREnd) >=
 | 
			
		||||
           SM.getInstantiationColumnNumber(ContainerREnd)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PathDiagnosticLocation
 | 
			
		||||
EdgeBuilder::IgnoreParens(const PathDiagnosticLocation &L) {
 | 
			
		||||
  if (const Expr* E = dyn_cast_or_null<Expr>(L.asStmt()))
 | 
			
		||||
      return PathDiagnosticLocation(E->IgnoreParenCasts(),
 | 
			
		||||
                                    PDB.getSourceManager());
 | 
			
		||||
  return L;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
 | 
			
		||||
  if (!PrevLoc.isValid()) {
 | 
			
		||||
    PrevLoc = NewLoc;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  if (NewLoc.asLocation() == PrevLoc.asLocation())
 | 
			
		||||
    return;
 | 
			
		||||
    
 | 
			
		||||
  // FIXME: Ignore intra-macro edges for now.
 | 
			
		||||
  if (NewLoc.asLocation().getInstantiationLoc() ==
 | 
			
		||||
      PrevLoc.asLocation().getInstantiationLoc())
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  PD.push_front(new PathDiagnosticControlFlowPiece(NewLoc, PrevLoc));
 | 
			
		||||
  PrevLoc = NewLoc;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) {
 | 
			
		||||
  const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc);
 | 
			
		||||
 | 
			
		||||
  while (!CLocs.empty()) {
 | 
			
		||||
    const PathDiagnosticLocation &TopContextLoc = CLocs.back();
 | 
			
		||||
    
 | 
			
		||||
    // Is the top location context the same as the one for the new location?
 | 
			
		||||
    if (TopContextLoc == CLoc) {
 | 
			
		||||
      if (alwaysAdd && NewLoc.asLocation() != CLoc.asLocation())
 | 
			
		||||
        rawAddEdge(NewLoc);
 | 
			
		||||
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (containsLocation(TopContextLoc, CLoc)) {
 | 
			
		||||
      if (alwaysAdd)
 | 
			
		||||
        rawAddEdge(NewLoc);
 | 
			
		||||
 | 
			
		||||
      CLocs.push_back(CLoc);
 | 
			
		||||
      return;      
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Context does not contain the location.  Flush it.
 | 
			
		||||
    popLocation();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  assert(0 && "addEdge should never pop the top context");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EdgeBuilder::addContext(const Stmt *S) {
 | 
			
		||||
  if (!S)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  PathDiagnosticLocation L(S, PDB.getSourceManager());
 | 
			
		||||
  
 | 
			
		||||
  while (!CLocs.empty()) {
 | 
			
		||||
    const PathDiagnosticLocation &TopContextLoc = CLocs.back();
 | 
			
		||||
 | 
			
		||||
    // Is the top location context the same as the one for the new location?
 | 
			
		||||
    if (TopContextLoc == L)
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    if (containsLocation(TopContextLoc, L)) {
 | 
			
		||||
    //   if (const Stmt *S = L.asStmt())
 | 
			
		||||
    //     if (isa<Expr>(S))
 | 
			
		||||
    //       if (const Stmt *P = PDB.getParent(S))
 | 
			
		||||
    //         addContext(PDB.getEnclosingStmtLocation(P).asStmt());
 | 
			
		||||
      
 | 
			
		||||
      CLocs.push_back(L);
 | 
			
		||||
      return;      
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Context does not contain the location.  Flush it.
 | 
			
		||||
    popLocation();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  CLocs.push_back(L);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
 | 
			
		||||
                                            PathDiagnosticBuilder &PDB,
 | 
			
		||||
                                            const ExplodedNode<GRState> *N) {
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  EdgeBuilder EB(PD, PDB);
 | 
			
		||||
 | 
			
		||||
  const ExplodedNode<GRState>* NextNode = N->pred_empty() 
 | 
			
		||||
                                        ? NULL : *(N->pred_begin());
 | 
			
		||||
 | 
			
		||||
  while (NextNode) {
 | 
			
		||||
    N = NextNode;
 | 
			
		||||
    NextNode = GetPredecessorNode(N);
 | 
			
		||||
    ProgramPoint P = N->getLocation();
 | 
			
		||||
 | 
			
		||||
    // Block edges.
 | 
			
		||||
    if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
 | 
			
		||||
      const CFGBlock &Blk = *BE->getSrc();
 | 
			
		||||
 | 
			
		||||
      if (const Stmt *Term = Blk.getTerminator())
 | 
			
		||||
        EB.addContext(Term);
 | 
			
		||||
 | 
			
		||||
      // Only handle blocks with more than 1 statement here, as the blocks
 | 
			
		||||
      // with one statement are handled at BlockEntrances.
 | 
			
		||||
      if (Blk.size() > 1) {
 | 
			
		||||
        const Stmt *S = *Blk.rbegin();
 | 
			
		||||
        EB.addEdge(S);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
 | 
			
		||||
      if (const Stmt* S = BE->getFirstStmt()) {
 | 
			
		||||
       if (IsControlFlowExpr(S))
 | 
			
		||||
         EB.addContext(S);
 | 
			
		||||
       else
 | 
			
		||||
        EB.addEdge(S);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    PathDiagnosticPiece* p =
 | 
			
		||||
    PDB.getReport().VisitNode(N, NextNode, PDB.getGraph(),
 | 
			
		||||
                              PDB.getBugReporter(), PDB.getNodeMapClosure());
 | 
			
		||||
    
 | 
			
		||||
    if (p) {
 | 
			
		||||
      EB.addEdge(p->getLocation(), true);
 | 
			
		||||
      PD.push_front(p);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
static void GenExtAddEdge(PathDiagnostic& PD,
 | 
			
		||||
                          PathDiagnosticBuilder &PDB,
 | 
			
		||||
                          PathDiagnosticLocation NewLoc,
 | 
			
		||||
                          PathDiagnosticLocation &PrevLoc,
 | 
			
		||||
                          bool allowBlockJump = false) {
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  if (const Stmt *S = NewLoc.asStmt()) {
 | 
			
		||||
    if (IsControlFlowExpr(S))
 | 
			
		||||
      return;    
 | 
			
		||||
| 
						 | 
				
			
			@ -783,7 +1041,7 @@ static void GenExtAddEdge(PathDiagnostic& PD,
 | 
			
		|||
  
 | 
			
		||||
  if (NewLoc == PrevLoc)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  // Are we jumping between statements within the same compound statement?
 | 
			
		||||
  if (!allowBlockJump)
 | 
			
		||||
    if (const Stmt *PS = PrevLoc.asStmt())
 | 
			
		||||
| 
						 | 
				
			
			@ -801,18 +1059,18 @@ static void GenExtAddEdge(PathDiagnostic& PD,
 | 
			
		|||
        PathDiagnosticLocation X = PDB.getEnclosingStmtLocation(PS);
 | 
			
		||||
        // FIXME: We need a version of getParent that ignores '()' and casts.
 | 
			
		||||
        const Stmt *parentX = PDB.getParent(X.asStmt());
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        const PathDiagnosticLocation &Y = PDB.getEnclosingStmtLocation(NS);
 | 
			
		||||
        // FIXME: We need a version of getParent that ignores '()' and casts.
 | 
			
		||||
        const Stmt *parentY = PDB.getParent(Y.asStmt());
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        if (parentX && IsControlFlowExpr(parentX)) {
 | 
			
		||||
          if (parentX == parentY)
 | 
			
		||||
            break;
 | 
			
		||||
          else {
 | 
			
		||||
            if (const Stmt *grandparentX = PDB.getParent(parentX)) {
 | 
			
		||||
              const PathDiagnosticLocation &W =
 | 
			
		||||
                PDB.getEnclosingStmtLocation(grandparentX);
 | 
			
		||||
              PDB.getEnclosingStmtLocation(grandparentX);
 | 
			
		||||
              
 | 
			
		||||
              if (W != Y) X = W;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -833,7 +1091,7 @@ static void GenExtAddEdge(PathDiagnostic& PD,
 | 
			
		|||
 | 
			
		||||
static bool IsNestedDeclStmt(const Stmt *S, ParentMap &PM) {
 | 
			
		||||
  const DeclStmt *DS = dyn_cast<DeclStmt>(S);
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  if (!DS)
 | 
			
		||||
    return false;
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			@ -843,7 +1101,7 @@ static bool IsNestedDeclStmt(const Stmt *S, ParentMap &PM) {
 | 
			
		|||
  
 | 
			
		||||
  if (const ForStmt *FS = dyn_cast<ForStmt>(Parent))
 | 
			
		||||
    return FS->getInit() == DS;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  // FIXME: In the future IfStmt/WhileStmt may contain DeclStmts in their
 | 
			
		||||
  // condition.
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			@ -853,11 +1111,11 @@ static bool IsNestedDeclStmt(const Stmt *S, ParentMap &PM) {
 | 
			
		|||
static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
 | 
			
		||||
                                            PathDiagnosticBuilder &PDB,
 | 
			
		||||
                                            const ExplodedNode<GRState> *N) {
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  SourceManager& SMgr = PDB.getSourceManager();
 | 
			
		||||
  const ExplodedNode<GRState>* NextNode = N->pred_empty()  
 | 
			
		||||
                                          ? NULL : *(N->pred_begin());
 | 
			
		||||
 | 
			
		||||
  ? NULL : *(N->pred_begin());
 | 
			
		||||
  
 | 
			
		||||
  PathDiagnosticLocation PrevLoc;
 | 
			
		||||
  
 | 
			
		||||
  while (NextNode) {
 | 
			
		||||
| 
						 | 
				
			
			@ -868,7 +1126,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
    // Block edges.
 | 
			
		||||
    if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
 | 
			
		||||
      const CFGBlock &Blk = *BE->getSrc();
 | 
			
		||||
 | 
			
		||||
      
 | 
			
		||||
      // Add a special edge for the entrance into the function/method.
 | 
			
		||||
      if (&Blk == &PDB.getCFG().getEntry()) {
 | 
			
		||||
        FullSourceLoc L = FullSourceLoc(PDB.getCodeDecl().getLocation(), SMgr);
 | 
			
		||||
| 
						 | 
				
			
			@ -899,7 +1157,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
          GenExtAddEdge(PD, PDB, PathDiagnosticLocation(S, SMgr), PrevLoc);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -910,7 +1168,7 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
            // Are we jumping within the same enclosing statement?          
 | 
			
		||||
            if (PDB.getEnclosingStmtLocation(S) ==
 | 
			
		||||
                PDB.getEnclosingStmtLocation(PrevLoc))
 | 
			
		||||
            continue;
 | 
			
		||||
              continue;
 | 
			
		||||
          }
 | 
			
		||||
          
 | 
			
		||||
          GenExtAddEdge(PD, PDB, PDB.getEnclosingStmtLocation(S), PrevLoc);
 | 
			
		||||
| 
						 | 
				
			
			@ -919,10 +1177,10 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
      
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
      
 | 
			
		||||
    
 | 
			
		||||
    PathDiagnosticPiece* p =
 | 
			
		||||
      PDB.getReport().VisitNode(N, NextNode, PDB.getGraph(),
 | 
			
		||||
                                PDB.getBugReporter(), PDB.getNodeMapClosure());
 | 
			
		||||
    PDB.getReport().VisitNode(N, NextNode, PDB.getGraph(),
 | 
			
		||||
                              PDB.getBugReporter(), PDB.getNodeMapClosure());
 | 
			
		||||
    
 | 
			
		||||
    if (p) {
 | 
			
		||||
      GenExtAddEdge(PD, PDB, p->getLocation(), PrevLoc, true);
 | 
			
		||||
| 
						 | 
				
			
			@ -930,7 +1188,8 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
// Methods for BugType and subclasses.
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
| 
						 | 
				
			
			@ -1337,10 +1596,6 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
 | 
			
		|||
      GenerateMinimalPathDiagnostic(PD, PDB, N);
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // After constructing the full PathDiagnostic, do a pass over it to compact
 | 
			
		||||
  // PathDiagnosticPieces that occur within a macro.
 | 
			
		||||
  CompactPathDiagnostic(PD, PDB.getSourceManager());  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BugReporter::Register(BugType *BT) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue