diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/ParentMap.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Analysis/AnalysisDeclContext.cpp | 23 | ||||
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 57 | 
4 files changed, 76 insertions, 16 deletions
| diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp index dbe0b98e186..ff44d938d3a 100644 --- a/clang/lib/AST/ParentMap.cpp +++ b/clang/lib/AST/ParentMap.cpp @@ -110,6 +110,13 @@ void ParentMap::addStmt(Stmt* S) {    }  } +void ParentMap::setParent(const Stmt *S, const Stmt *Parent) { +  assert(S); +  assert(Parent); +  MapTy *M = reinterpret_cast<MapTy *>(Impl); +  M->insert(std::make_pair(const_cast<Stmt *>(S), const_cast<Stmt *>(Parent))); +} +  Stmt* ParentMap::getParent(Stmt* S) const {    MapTy* M = (MapTy*) Impl;    MapTy::iterator I = M->find(S); diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp index 5ff7842407a..66dbd3e7856 100644 --- a/clang/lib/Analysis/AnalysisDeclContext.cpp +++ b/clang/lib/Analysis/AnalysisDeclContext.cpp @@ -157,6 +157,19 @@ AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {    return itr->second;  } +/// Add each synthetic statement in the CFG to the parent map, using the +/// source statement's parent. +static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) { +  if (!TheCFG) +    return; + +  for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(), +                                    E = TheCFG->synthetic_stmt_end(); +       I != E; ++I) { +    PM.setParent(I->first, PM.getParent(I->second)); +  } +} +  CFG *AnalysisDeclContext::getCFG() {    if (!cfgBuildOptions.PruneTriviallyFalseEdges)      return getUnoptimizedCFG(); @@ -167,6 +180,9 @@ CFG *AnalysisDeclContext::getCFG() {      // Even when the cfg is not successfully built, we don't      // want to try building it again.      builtCFG = true; + +    if (PM) +      addParentsForSyntheticStmts(cfg.get(), *PM);    }    return cfg.get();  } @@ -180,6 +196,9 @@ CFG *AnalysisDeclContext::getUnoptimizedCFG() {      // Even when the cfg is not successfully built, we don't      // want to try building it again.      builtCompleteCFG = true; + +    if (PM) +      addParentsForSyntheticStmts(completeCFG.get(), *PM);    }    return completeCFG.get();  } @@ -222,6 +241,10 @@ ParentMap &AnalysisDeclContext::getParentMap() {          PM->addStmt((*I)->getInit());        }      } +    if (builtCFG) +      addParentsForSyntheticStmts(getCFG(), *PM); +    if (builtCompleteCFG) +      addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);    }    return *PM;  } diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 9945dcb36ce..f4858951854 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1627,6 +1627,7 @@ CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {      Decl *D = *I;      void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A);      DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); +    cfg->addSyntheticDeclStmt(DSNew, DS);      // Append the fake DeclStmt to block.      B = VisitDeclSubExpr(DSNew); @@ -3953,6 +3954,10 @@ Stmt *CFGBlock::getTerminatorCondition() {      default:        break; +    case Stmt::CXXForRangeStmtClass: +      E = cast<CXXForRangeStmt>(Terminator)->getCond(); +      break; +      case Stmt::ForStmtClass:        E = cast<ForStmt>(Terminator)->getCond();        break; diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 829e7482ebe..96aa4886186 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -363,6 +363,7 @@ static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {    case Stmt::DoStmtClass:    case Stmt::WhileStmtClass:    case Stmt::ObjCForCollectionStmtClass: +  case Stmt::CXXForRangeStmtClass:      return Parent;    default:      break; @@ -404,6 +405,10 @@ getEnclosingStmtLocation(const Stmt *S, SourceManager &SMgr, const ParentMap &P,            return PathDiagnosticLocation(Parent, SMgr, LC);          else            return PathDiagnosticLocation(S, SMgr, LC); +      case Stmt::CXXForRangeStmtClass: +        if (cast<CXXForRangeStmt>(Parent)->getBody() == S) +          return PathDiagnosticLocation(S, SMgr, LC); +        break;        case Stmt::DoStmtClass:            return PathDiagnosticLocation(S, SMgr, LC);        case Stmt::ForStmtClass: @@ -1253,6 +1258,7 @@ static bool isLoop(const Stmt *Term) {      case Stmt::ForStmtClass:      case Stmt::WhileStmtClass:      case Stmt::ObjCForCollectionStmtClass: +    case Stmt::CXXForRangeStmtClass:        return true;      default:        // Note that we intentionally do not include do..while here. @@ -1302,6 +1308,15 @@ static const Stmt *getStmtBeforeCond(ParentMap &PM, const Stmt *Term,  static bool isInLoopBody(ParentMap &PM, const Stmt *S, const Stmt *Term) {    const Stmt *LoopBody = 0;    switch (Term->getStmtClass()) { +    case Stmt::CXXForRangeStmtClass: { +      const CXXForRangeStmt *FR = cast<CXXForRangeStmt>(Term); +      if (isContainedByStmt(PM, FR->getInc(), S)) +        return true; +      if (isContainedByStmt(PM, FR->getLoopVarStmt(), S)) +        return true; +      LoopBody = FR->getBody(); +      break; +    }      case Stmt::ForStmtClass: {        const ForStmt *FS = cast<ForStmt>(Term);        if (isContainedByStmt(PM, FS->getInc(), S)) @@ -1718,16 +1733,20 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,          // Are we jumping to the head of a loop?  Add a special diagnostic.          if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {            PathDiagnosticLocation L(Loop, SM, PDB.LC); -          const CompoundStmt *CS = NULL; +          const Stmt *Body = NULL;            if (const ForStmt *FS = dyn_cast<ForStmt>(Loop)) -            CS = dyn_cast<CompoundStmt>(FS->getBody()); +            Body = FS->getBody();            else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Loop)) -            CS = dyn_cast<CompoundStmt>(WS->getBody()); +            Body = WS->getBody();            else if (const ObjCForCollectionStmt *OFS = -                   dyn_cast<ObjCForCollectionStmt>(Loop)) { -            CS = dyn_cast<CompoundStmt>(OFS->getBody()); +                     dyn_cast<ObjCForCollectionStmt>(Loop)) { +            Body = OFS->getBody(); +          } else if (const CXXForRangeStmt *FRS = +                       dyn_cast<CXXForRangeStmt>(Loop)) { +            Body = FRS->getBody();            } +          // do-while statements are explicitly excluded here            PathDiagnosticEventPiece *p =              new PathDiagnosticEventPiece(L, "Looping back to the head " @@ -1737,7 +1756,7 @@ GenerateAlternateExtensivePathDiagnostic(PathDiagnostic& PD,            addEdgeToPath(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);            PD.getActivePath().push_front(p); -          if (CS) { +          if (const CompoundStmt *CS = dyn_cast_or_null<CompoundStmt>(Body)) {              addEdgeToPath(PD.getActivePath(), PrevLoc,                            PathDiagnosticLocation::createEndBrace(CS, SM),                            PDB.LC); @@ -1871,16 +1890,22 @@ static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {      }      case Stmt::ObjCForCollectionStmtClass:        return cast<ObjCForCollectionStmt>(S)->getElement() == Cond; +    case Stmt::CXXForRangeStmtClass: { +      const CXXForRangeStmt *FRS = cast<CXXForRangeStmt>(S); +      return FRS->getCond() == Cond || FRS->getRangeInit() == Cond; +    }      default:        return false;    }  }  static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) { -  const ForStmt *FS = dyn_cast<ForStmt>(FL); -  if (!FS) -    return false; -  return FS->getInc() == S || FS->getInit() == S; +  if (const ForStmt *FS = dyn_cast<ForStmt>(FL)) +    return FS->getInc() == S || FS->getInit() == S; +  if (const CXXForRangeStmt *FRS = dyn_cast<CXXForRangeStmt>(FL)) +    return FRS->getInc() == S || FRS->getRangeStmt() == S || +           FRS->getLoopVarStmt() || FRS->getRangeInit() == S; +  return false;  }  typedef llvm::DenseSet<const PathDiagnosticCallPiece *> @@ -1903,16 +1928,15 @@ static void addContextEdges(PathPieces &pieces, SourceManager &SM,        continue;      PathDiagnosticLocation SrcLoc = Piece->getStartLocation(); -    const Stmt *Src = getLocStmt(SrcLoc);      SmallVector<PathDiagnosticLocation, 4> SrcContexts; -    PathDiagnosticLocation NextSrcContext = -      getEnclosingStmtLocation(Src, SM, PM, LCtx, /*allowNested=*/true); -    const Stmt *InnerStmt = Src; +    PathDiagnosticLocation NextSrcContext = SrcLoc; +    const Stmt *InnerStmt = 0;      while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {        SrcContexts.push_back(NextSrcContext);        InnerStmt = NextSrcContext.asStmt(); -      NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx, true); +      NextSrcContext = getEnclosingStmtLocation(InnerStmt, SM, PM, LCtx, +                                                /*allowNested=*/true);      }      // Repeatedly split the edge as necessary. @@ -2024,7 +2048,8 @@ static void simplifySimpleBranches(PathPieces &pieces) {      // We only perform this transformation for specific branch kinds.      // We don't want to do this for do..while, for example.      if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) || -          isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start))) +          isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start) || +          isa<CXXForRangeStmt>(s1Start)))        continue;      // Is s1End the branch condition? | 

