From 39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Sun, 20 Feb 2011 13:06:31 +0000
Subject: Vendor import of clang trunk r126079:
 http://llvm.org/svn/llvm-project/cfe/trunk@126079

---
 include/clang/Analysis/Analyses/FormatString.h     |  13 +-
 include/clang/Analysis/Analyses/LiveVariables.h    |   3 +-
 .../Analysis/Analyses/UninitializedValuesV2.h      |  40 ++
 include/clang/Analysis/AnalysisContext.h           |  37 +-
 include/clang/Analysis/AnalysisDiagnostic.h        |   2 +-
 include/clang/Analysis/CFG.h                       | 409 ++++++++++++++++++---
 .../Analysis/DomainSpecific/CocoaConventions.h     |  40 ++
 .../clang/Analysis/FlowSensitive/DataflowSolver.h  |  18 +-
 include/clang/Analysis/ProgramPoint.h              |  48 ++-
 include/clang/Analysis/Support/BumpVector.h        |  29 +-
 .../Analysis/Visitors/CFGRecStmtDeclVisitor.h      |   4 +
 .../clang/Analysis/Visitors/CFGRecStmtVisitor.h    |   5 +
 include/clang/Analysis/Visitors/CFGStmtVisitor.h   |   4 +-
 13 files changed, 554 insertions(+), 98 deletions(-)
 create mode 100644 include/clang/Analysis/Analyses/UninitializedValuesV2.h
 create mode 100644 include/clang/Analysis/DomainSpecific/CocoaConventions.h

(limited to 'include/clang/Analysis')

diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 280b126..7cc76a8 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -379,6 +379,7 @@ using analyze_format_string::OptionalAmount;
 using analyze_format_string::OptionalFlag;
 
 class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
+  OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
   OptionalFlag IsLeftJustified; // '-'
   OptionalFlag HasPlusPrefix; // '+'
   OptionalFlag HasSpacePrefix; // ' '
@@ -388,8 +389,8 @@ class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
 public:
   PrintfSpecifier() :
     FormatSpecifier(/* isPrintf = */ true),
-    IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
-    HasAlternativeForm("#"), HasLeadingZeroes("0") {}
+    HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"),
+    HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0") {}
 
   static PrintfSpecifier Parse(const char *beg, const char *end);
 
@@ -397,6 +398,10 @@ public:
   void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
     CS = cs;
   }
+  void setHasThousandsGrouping(const char *position) {
+    HasThousandsGrouping = true;
+    HasThousandsGrouping.setPosition(position);
+  }
   void setIsLeftJustified(const char *position) {
     IsLeftJustified = true;
     IsLeftJustified.setPosition(position);
@@ -445,6 +450,9 @@ public:
   /// more than one type.
   ArgTypeResult getArgType(ASTContext &Ctx) const;
 
+  const OptionalFlag &hasThousandsGrouping() const { 
+      return HasThousandsGrouping;
+  }
   const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
   const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
   const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
@@ -465,6 +473,7 @@ public:
   bool hasValidLeadingZeros() const;
   bool hasValidSpacePrefix() const;
   bool hasValidLeftJustified() const;
+  bool hasValidThousandsGroupingPrefix() const;
 
   bool hasValidPrecision() const;
   bool hasValidFieldWidth() const;
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 237fe14..fbbd261 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -55,7 +55,8 @@ struct LiveVariables_ValueTypes {
 
     /// ObserveStmt - A callback invoked right before invoking the
     ///  liveness transfer function on the given statement.
-    virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD,
+    virtual void ObserveStmt(Stmt* S, const CFGBlock *currentBlock,
+                             const AnalysisDataTy& AD,
                              const ValTy& V) {}
 
     virtual void ObserverKill(DeclRefExpr* DR) {}
diff --git a/include/clang/Analysis/Analyses/UninitializedValuesV2.h b/include/clang/Analysis/Analyses/UninitializedValuesV2.h
new file mode 100644
index 0000000..c1fe040
--- /dev/null
+++ b/include/clang/Analysis/Analyses/UninitializedValuesV2.h
@@ -0,0 +1,40 @@
+//= UninitializedValuesV2.h - Finding uses of uninitialized values --*- C++ -*-=
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines APIs for invoking and reported uninitialized values
+// warnings.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNINIT_VALS_H
+#define LLVM_CLANG_UNINIT_VALS_H
+
+namespace clang {
+
+class AnalysisContext;
+class CFG;  
+class DeclContext;
+class Expr;
+class VarDecl;
+  
+class UninitVariablesHandler {
+public:
+  UninitVariablesHandler() {}
+  virtual ~UninitVariablesHandler();
+  
+  virtual void handleUseOfUninitVariable(const Expr *ex,
+                                         const VarDecl *vd) {}
+};
+  
+void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
+                                       AnalysisContext &ac,
+                                       UninitVariablesHandler &handler);
+
+}
+#endif
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 7d4d25f..2ecbfdc 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
 
 #include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/PointerUnion.h"
@@ -56,15 +57,20 @@ class AnalysisContext {
   llvm::BumpPtrAllocator A;
   bool UseUnoptimizedCFG;  
   bool AddEHEdges;
+  bool AddImplicitDtors;
+  bool AddInitializers;
 public:
   AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
                   bool useUnoptimizedCFG = false,
-                  bool addehedges = false)
+                  bool addehedges = false,
+                  bool addImplicitDtors = false,
+                  bool addInitializers = false)
     : D(d), TU(tu), cfg(0), completeCFG(0),
       builtCFG(false), builtCompleteCFG(false),
       liveness(0), relaxedLiveness(0), PM(0), PCA(0),
       ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
-      AddEHEdges(addehedges) {}
+      AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
+      AddInitializers(addInitializers) {}
 
   ~AnalysisContext();
 
@@ -80,13 +86,17 @@ public:
   bool getAddEHEdges() const { return AddEHEdges; }
   
   bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+  bool getAddImplicitDtors() const { return AddImplicitDtors; }
+  bool getAddInitializers() const { return AddInitializers; }
 
   Stmt *getBody();
   CFG *getCFG();
-  
+
   /// Return a version of the CFG without any edges pruned.
   CFG *getUnoptimizedCFG();
 
+  void dumpCFG();
+
   ParentMap &getParentMap();
   PseudoConstantAnalysis *getPseudoConstantAnalysis();
   LiveVariables *getLiveVariables();
@@ -106,15 +116,21 @@ class AnalysisContextManager {
   typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
   ContextMap Contexts;
   bool UseUnoptimizedCFG;
+  bool AddImplicitDtors;
+  bool AddInitializers;
 public:
-  AnalysisContextManager(bool useUnoptimizedCFG = false)
-    : UseUnoptimizedCFG(useUnoptimizedCFG) {}
+  AnalysisContextManager(bool useUnoptimizedCFG = false,
+      bool addImplicitDtors = false, bool addInitializers = false)
+    : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
+      AddInitializers(addInitializers) {}
   
   ~AnalysisContextManager();
 
   AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
 
   bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+  bool getAddImplicitDtors() const { return AddImplicitDtors; }
+  bool getAddInitializers() const { return AddInitializers; }
 
   // Discard all previously created AnalysisContexts.
   void clear();
@@ -196,9 +212,10 @@ class StackFrameContext : public LocationContext {
 
   friend class LocationContextManager;
   StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
-                    const Stmt *s, const CFGBlock *blk, unsigned idx)
-    : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
-      Index(idx) {}
+                    const Stmt *s, const CFGBlock *blk, 
+                    unsigned idx)
+    : LocationContext(StackFrame, ctx, parent), CallSite(s),
+      Block(blk), Index(idx) {}
 
 public:
   ~StackFrameContext() {}
@@ -282,8 +299,8 @@ public:
 
   const StackFrameContext *getStackFrame(AnalysisContext *ctx,
                                          const LocationContext *parent,
-                                         const Stmt *s, const CFGBlock *blk,
-                                         unsigned idx);
+                                         const Stmt *s,
+                                         const CFGBlock *blk, unsigned idx);
 
   const ScopeContext *getScope(AnalysisContext *ctx,
                                const LocationContext *parent,
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index e98a3df..295d0a2 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -15,7 +15,7 @@
 namespace clang {
   namespace diag {
     enum {
-#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM,
 #define ANALYSISSTART
 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
 #undef DIAG
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index b7a8e11..b337d74 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -22,14 +22,21 @@
 #include "clang/Analysis/Support/BumpVector.h"
 #include "clang/Basic/SourceLocation.h"
 #include <cassert>
+#include <iterator>
 
 namespace llvm {
   class raw_ostream;
 }
+
 namespace clang {
   class Decl;
   class Stmt;
   class Expr;
+  class FieldDecl;
+  class VarDecl;
+  class CXXCtorInitializer;
+  class CXXBaseSpecifier;
+  class CXXBindTemporaryExpr;
   class CFG;
   class PrinterHelper;
   class LangOptions;
@@ -37,19 +44,203 @@ namespace clang {
 
 /// CFGElement - Represents a top-level expression in a basic block.
 class CFGElement {
-  llvm::PointerIntPair<Stmt *, 2> Data;
 public:
-  enum Type { StartScope, EndScope };
-  explicit CFGElement() {}
-  CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
-  CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {}
-  Stmt *getStmt() const { return Data.getPointer(); }
-  bool asLValue() const { return Data.getInt() == 1; }
-  bool asStartScope() const { return Data.getInt() == 2; }
-  bool asEndScope() const { return Data.getInt() == 3; }
-  bool asDtor() const { return Data.getInt() == 4; }
+  enum Kind {
+    // main kind
+    Statement,
+    Initializer,
+    ImplicitDtor,
+    // dtor kind
+    AutomaticObjectDtor,
+    BaseDtor,
+    MemberDtor,
+    TemporaryDtor,
+    DTOR_BEGIN = AutomaticObjectDtor
+  };
+
+protected:
+  // The int bits are used to mark the main kind.
+  llvm::PointerIntPair<void *, 2> Data1;
+  // The int bits are used to mark the dtor kind.
+  llvm::PointerIntPair<void *, 2> Data2;
+
+  CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {}
+  CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2)
+      : Data1(Ptr1, Int1), Data2(Ptr2, Int2) {}
+
+public:
+  CFGElement() {}
+
+  Kind getKind() const { return static_cast<Kind>(Data1.getInt()); }
+
+  Kind getDtorKind() const {
+    assert(getKind() == ImplicitDtor);
+    return static_cast<Kind>(Data2.getInt() + DTOR_BEGIN);
+  }
+
+  bool isValid() const { return Data1.getPointer(); }
+
+  operator bool() const { return isValid(); }
+
+  template<class ElemTy> ElemTy getAs() const {
+    if (llvm::isa<ElemTy>(this))
+      return *static_cast<const ElemTy*>(this);
+    return ElemTy();
+  }
+
+  static bool classof(const CFGElement *E) { return true; }
+};
+
+class CFGStmt : public CFGElement {
+public:
+  CFGStmt() {}
+  CFGStmt(Stmt *S) : CFGElement(S, 0) {}
+
+  Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); }
+
   operator Stmt*() const { return getStmt(); }
-  operator bool() const { return getStmt() != 0; }
+
+  static bool classof(const CFGElement *E) {
+    return E->getKind() == Statement;
+  }
+};
+
+/// CFGInitializer - Represents C++ base or member initializer from
+/// constructor's initialization list.
+class CFGInitializer : public CFGElement {
+public:
+  CFGInitializer() {}
+  CFGInitializer(CXXCtorInitializer* I)
+      : CFGElement(I, Initializer) {}
+
+  CXXCtorInitializer* getInitializer() const {
+    return static_cast<CXXCtorInitializer*>(Data1.getPointer());
+  }
+  operator CXXCtorInitializer*() const { return getInitializer(); }
+
+  static bool classof(const CFGElement *E) {
+    return E->getKind() == Initializer;
+  }
+};
+
+/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
+/// by compiler on various occasions.
+class CFGImplicitDtor : public CFGElement {
+protected:
+  CFGImplicitDtor(unsigned K, void* P, void* S)
+      : CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {}
+
+public:
+  CFGImplicitDtor() {}
+
+  static bool classof(const CFGElement *E) {
+    return E->getKind() == ImplicitDtor;
+  }
+};
+
+/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
+/// for automatic object or temporary bound to const reference at the point
+/// of leaving its local scope.
+class CFGAutomaticObjDtor: public CFGImplicitDtor {
+public:
+  CFGAutomaticObjDtor() {}
+  CFGAutomaticObjDtor(VarDecl* VD, Stmt* S)
+      : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {}
+
+  VarDecl* getVarDecl() const {
+    return static_cast<VarDecl*>(Data1.getPointer());
+  }
+
+  // Get statement end of which triggered the destructor call.
+  Stmt* getTriggerStmt() const {
+    return static_cast<Stmt*>(Data2.getPointer());
+  }
+
+  static bool classof(const CFGElement *E) {
+    return E->getKind() == ImplicitDtor && 
+           E->getDtorKind() == AutomaticObjectDtor;
+  }
+};
+
+/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
+/// base object in destructor.
+class CFGBaseDtor : public CFGImplicitDtor {
+public:
+  CFGBaseDtor() {}
+  CFGBaseDtor(const CXXBaseSpecifier *BS)
+      : CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {}
+
+  const CXXBaseSpecifier *getBaseSpecifier() const {
+    return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
+  }
+
+  static bool classof(const CFGElement *E) {
+    return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor;
+  }
+};
+
+/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
+/// member object in destructor.
+class CFGMemberDtor : public CFGImplicitDtor {
+public:
+  CFGMemberDtor() {}
+  CFGMemberDtor(FieldDecl *FD)
+      : CFGImplicitDtor(MemberDtor, FD, NULL) {}
+
+  FieldDecl *getFieldDecl() const {
+    return static_cast<FieldDecl*>(Data1.getPointer());
+  }
+
+  static bool classof(const CFGElement *E) {
+    return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor;
+  }
+};
+
+/// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
+/// at the end of full expression for temporary object.
+class CFGTemporaryDtor : public CFGImplicitDtor {
+public:
+  CFGTemporaryDtor() {}
+  CFGTemporaryDtor(CXXBindTemporaryExpr *E)
+      : CFGImplicitDtor(TemporaryDtor, E, NULL) {}
+
+  CXXBindTemporaryExpr *getBindTemporaryExpr() const {
+    return static_cast<CXXBindTemporaryExpr *>(Data1.getPointer());
+  }
+
+  static bool classof(const CFGElement *E) {
+    return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor;
+  }
+};
+
+/// CFGTerminator - Represents CFGBlock terminator statement.
+///
+/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
+/// in control flow of destructors of temporaries. In this case terminator
+/// statement is the same statement that branches control flow in evaluation
+/// of matching full expression.
+class CFGTerminator {
+  llvm::PointerIntPair<Stmt *, 1> Data;
+public:
+  CFGTerminator() {}
+  CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
+      : Data(S, TemporaryDtorsBranch) {}
+
+  Stmt *getStmt() { return Data.getPointer(); }
+  const Stmt *getStmt() const { return Data.getPointer(); }
+
+  bool isTemporaryDtorsBranch() const { return Data.getInt(); }
+
+  operator Stmt *() { return getStmt(); }
+  operator const Stmt *() const { return getStmt(); }
+
+  Stmt *operator->() { return getStmt(); }
+  const Stmt *operator->() const { return getStmt(); }
+
+  Stmt &operator*() { return *getStmt(); }
+  const Stmt &operator*() const { return *getStmt(); }
+
+  operator bool() const { return getStmt(); }
 };
 
 /// CFGBlock - Represents a single basic block in a source-level CFG.
@@ -77,11 +268,11 @@ public:
 ///     &&, ||          expression that uses result of && or ||, RHS
 ///
 class CFGBlock {
-  class StatementList {
+  class ElementList {
     typedef BumpVector<CFGElement> ImplTy;
     ImplTy Impl;
   public:
-    StatementList(BumpVectorContext &C) : Impl(C, 4) {}
+    ElementList(BumpVectorContext &C) : Impl(C, 4) {}
     
     typedef std::reverse_iterator<ImplTy::iterator>       iterator;
     typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator;
@@ -89,6 +280,11 @@ class CFGBlock {
     typedef ImplTy::const_iterator                        const_reverse_iterator;
   
     void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
+    reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E,
+        BumpVectorContext& C) {
+      return Impl.insert(I, Cnt, E, C);
+    }
+
     CFGElement front() const { return Impl.back(); }
     CFGElement back() const { return Impl.front(); }
     
@@ -111,7 +307,7 @@ class CFGBlock {
   };
 
   /// Stmts - The set of statements in the basic block.
-  StatementList Stmts;
+  ElementList Elements;
 
   /// Label - An (optional) label that prefixes the executable
   ///  statements in the block.  When this variable is non-NULL, it is
@@ -121,7 +317,7 @@ class CFGBlock {
   /// Terminator - The terminator for a basic block that
   ///  indicates the type of control-flow that occurs between a block
   ///  and its successors.
-  Stmt *Terminator;
+  CFGTerminator Terminator;
 
   /// LoopTarget - Some blocks are used to represent the "loop edge" to
   ///  the start of a loop from within the loop body.  This Stmt* will be
@@ -140,33 +336,33 @@ class CFGBlock {
 
 public:
   explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
-    : Stmts(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
+    : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
       BlockID(blockid), Preds(C, 1), Succs(C, 1) {}
   ~CFGBlock() {}
 
   // Statement iterators
-  typedef StatementList::iterator                      iterator;
-  typedef StatementList::const_iterator                const_iterator;
-  typedef StatementList::reverse_iterator              reverse_iterator;
-  typedef StatementList::const_reverse_iterator        const_reverse_iterator;
+  typedef ElementList::iterator                      iterator;
+  typedef ElementList::const_iterator                const_iterator;
+  typedef ElementList::reverse_iterator              reverse_iterator;
+  typedef ElementList::const_reverse_iterator        const_reverse_iterator;
 
-  CFGElement                   front()       const { return Stmts.front();   }
-  CFGElement                   back()        const { return Stmts.back();    }
+  CFGElement                 front()       const { return Elements.front();   }
+  CFGElement                 back()        const { return Elements.back();    }
 
-  iterator                     begin()             { return Stmts.begin();   }
-  iterator                     end()               { return Stmts.end();     }
-  const_iterator               begin()       const { return Stmts.begin();   }
-  const_iterator               end()         const { return Stmts.end();     }
+  iterator                   begin()             { return Elements.begin();   }
+  iterator                   end()               { return Elements.end();     }
+  const_iterator             begin()       const { return Elements.begin();   }
+  const_iterator             end()         const { return Elements.end();     }
 
-  reverse_iterator             rbegin()            { return Stmts.rbegin();  }
-  reverse_iterator             rend()              { return Stmts.rend();    }
-  const_reverse_iterator       rbegin()      const { return Stmts.rbegin();  }
-  const_reverse_iterator       rend()        const { return Stmts.rend();    }
+  reverse_iterator           rbegin()            { return Elements.rbegin();  }
+  reverse_iterator           rend()              { return Elements.rend();    }
+  const_reverse_iterator     rbegin()      const { return Elements.rbegin();  }
+  const_reverse_iterator     rend()        const { return Elements.rend();    }
 
-  unsigned                     size()        const { return Stmts.size();    }
-  bool                         empty()       const { return Stmts.empty();   }
+  unsigned                   size()        const { return Elements.size();    }
+  bool                       empty()       const { return Elements.empty();   }
 
-  CFGElement operator[](size_t i) const  { return Stmts[i]; }
+  CFGElement operator[](size_t i) const  { return Elements[i]; }
 
   // CFG iterators
   typedef AdjacentBlocks::iterator                              pred_iterator;
@@ -205,14 +401,67 @@ public:
   unsigned                     pred_size()   const { return Preds.size();    }
   bool                         pred_empty()  const { return Preds.empty();   }
 
+
+  class FilterOptions {
+  public:
+    FilterOptions() {
+      IgnoreDefaultsWithCoveredEnums = 0;
+    }
+
+    unsigned IgnoreDefaultsWithCoveredEnums : 1;
+  };
+
+  static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src,
+       const CFGBlock *Dst);
+
+  template <typename IMPL, bool IsPred>
+  class FilteredCFGBlockIterator {
+  private:
+    IMPL I, E;
+    const FilterOptions F;
+    const CFGBlock *From;
+   public:
+    explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
+              const CFGBlock *from,
+              const FilterOptions &f)
+      : I(i), E(e), F(f), From(from) {}
+
+    bool hasMore() const { return I != E; }
+
+    FilteredCFGBlockIterator &operator++() {
+      do { ++I; } while (hasMore() && Filter(*I));
+      return *this;
+    }
+
+    const CFGBlock *operator*() const { return *I; }
+  private:
+    bool Filter(const CFGBlock *To) {
+      return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
+    }
+  };
+
+  typedef FilteredCFGBlockIterator<const_pred_iterator, true>
+          filtered_pred_iterator;
+
+  typedef FilteredCFGBlockIterator<const_succ_iterator, false>
+          filtered_succ_iterator;
+
+  filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const {
+    return filtered_pred_iterator(pred_begin(), pred_end(), this, f);
+  }
+
+  filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const {
+    return filtered_succ_iterator(succ_begin(), succ_end(), this, f);
+  }
+
   // Manipulation of block contents
 
   void setTerminator(Stmt* Statement) { Terminator = Statement; }
   void setLabel(Stmt* Statement) { Label = Statement; }
   void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
 
-  Stmt* getTerminator() { return Terminator; }
-  const Stmt* getTerminator() const { return Terminator; }
+  CFGTerminator getTerminator() { return Terminator; }
+  const CFGTerminator getTerminator() const { return Terminator; }
 
   Stmt* getTerminatorCondition();
 
@@ -239,17 +488,39 @@ public:
     Succs.push_back(Block, C);
   }
   
-  void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) {
-      Stmts.push_back(CFGElement(Statement, asLValue), C);
-  }  
-  void StartScope(Stmt* S, BumpVectorContext &C) {
-    Stmts.push_back(CFGElement(S, CFGElement::StartScope), C);
+  void appendStmt(Stmt* statement, BumpVectorContext &C) {
+    Elements.push_back(CFGStmt(statement), C);
+  }
+
+  void appendInitializer(CXXCtorInitializer *initializer,
+                        BumpVectorContext& C) {
+    Elements.push_back(CFGInitializer(initializer), C);
   }
-  void EndScope(Stmt* S, BumpVectorContext &C) {
-    Stmts.push_back(CFGElement(S, CFGElement::EndScope), C);
+
+  void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
+    Elements.push_back(CFGBaseDtor(BS), C);
   }
-};
 
+  void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) {
+    Elements.push_back(CFGMemberDtor(FD), C);
+  }
+  
+  void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) {
+    Elements.push_back(CFGTemporaryDtor(E), C);
+  }
+
+  // Destructors must be inserted in reversed order. So insertion is in two
+  // steps. First we prepare space for some number of elements, then we insert
+  // the elements beginning at the last position in prepared space.
+  iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
+      BumpVectorContext& C) {
+    return iterator(Elements.insert(I.base(), Cnt, CFGElement(), C));
+  }
+  iterator insertAutomaticObjDtor(iterator I, VarDecl* VD, Stmt* S) {
+    *I = CFGAutomaticObjDtor(VD, S);
+    return ++I;
+  }
+};
 
 /// CFG - Represents a source-level, intra-procedural CFG that represents the
 ///  control-flow of a Stmt.  The Stmt can represent an entire function body,
@@ -264,13 +535,24 @@ public:
   // CFG Construction & Manipulation.
   //===--------------------------------------------------------------------===//
 
+  class BuildOptions {
+  public:
+    bool PruneTriviallyFalseEdges:1;
+    bool AddEHEdges:1;
+    bool AddInitializers:1;
+    bool AddImplicitDtors:1;
+
+    BuildOptions()
+        : PruneTriviallyFalseEdges(true)
+        , AddEHEdges(false)
+        , AddInitializers(false)
+        , AddImplicitDtors(false) {}
+  };
+
   /// buildCFG - Builds a CFG from an AST.  The responsibility to free the
   ///   constructed CFG belongs to the caller.
   static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
-                       bool pruneTriviallyFalseEdges = true,
-                       bool AddEHEdges = false,
-                       bool AddScopes = false /* NOT FULLY IMPLEMENTED.
-                                                 NOT READY FOR GENERAL USE. */);
+      BuildOptions BO = BuildOptions());
 
   /// createBlock - Create a new block in the CFG.  The CFG owns the block;
   ///  the caller should not directly free it.
@@ -324,8 +606,10 @@ public:
   void VisitBlockStmts(CALLBACK& O) const {
     for (const_iterator I=begin(), E=end(); I != E; ++I)
       for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
-           BI != BE; ++BI)
-        O(*BI);
+           BI != BE; ++BI) {
+        if (CFGStmt S = BI->getAs<CFGStmt>())
+          O(S);
+      }
   }
 
   //===--------------------------------------------------------------------===//
@@ -340,7 +624,10 @@ public:
     operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
   };
 
-  bool          isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
+  bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
+  bool isBlkExpr(const Stmt *S) const {
+    return const_cast<CFG*>(this)->isBlkExpr(S);
+  }
   BlkExprNumTy  getBlkExprNum(const Stmt* S);
   unsigned      getNumBlkExprs();
 
@@ -398,18 +685,22 @@ private:
 
 namespace llvm {
 
-/// Implement simplify_type for CFGElement, so that we can dyn_cast from
-/// CFGElement to a specific Stmt class.
-template <> struct simplify_type<const ::clang::CFGElement> {
-  typedef ::clang::Stmt* SimpleType;
-  static SimpleType getSimplifiedValue(const ::clang::CFGElement &Val) {
+/// Implement simplify_type for CFGTerminator, so that we can dyn_cast from
+/// CFGTerminator to a specific Stmt class.
+template <> struct simplify_type<const ::clang::CFGTerminator> {
+  typedef const ::clang::Stmt *SimpleType;
+  static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
     return Val.getStmt();
   }
 };
-  
-template <> struct simplify_type< ::clang::CFGElement> 
-  : public simplify_type<const ::clang::CFGElement> {};
-  
+
+template <> struct simplify_type< ::clang::CFGTerminator> {
+  typedef ::clang::Stmt *SimpleType;
+  static SimpleType getSimplifiedValue(const ::clang::CFGTerminator &Val) {
+    return const_cast<SimpleType>(Val.getStmt());
+  }
+};
+
 // Traits for: CFGBlock
 
 template <> struct GraphTraits< ::clang::CFGBlock* > {
diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
new file mode 100644
index 0000000..7e6e381
--- /dev/null
+++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -0,0 +1,40 @@
+//===- CocoaConventions.h - Special handling of Cocoa conventions -*- C++ -*--//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines 
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA
+#define LLVM_CLANG_ANALYSIS_DS_COCOA
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace ento {
+namespace cocoa {
+ 
+  enum NamingConvention { NoConvention, CreateRule, InitRule };
+
+  NamingConvention deriveNamingConvention(Selector S, bool ignorePrefix = true);
+
+  static inline bool followsFundamentalRule(Selector S) {
+    return deriveNamingConvention(S) == CreateRule;
+  }
+  
+  bool isRefType(QualType RetTy, llvm::StringRef Prefix,
+                 llvm::StringRef Name = llvm::StringRef());
+  
+  bool isCFObjectRef(QualType T);
+  
+  bool isCocoaObjectRef(QualType T);
+
+}}}
+
+#endif
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
index 9375db0..d75d333 100644
--- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h
+++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -273,8 +273,13 @@ private:
   void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
                     dataflow::forward_analysis_tag) {
 
-    for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
-      ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
+    TF.setCurrentBlock(B);
+    
+    for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
+      CFGElement El = *I;
+      if (CFGStmt S = El.getAs<CFGStmt>())
+        ProcessStmt(S, recordStmtValues, AnalysisDirTag());
+    }
 
     TF.VisitTerminator(const_cast<CFGBlock*>(B));
   }
@@ -282,10 +287,15 @@ private:
   void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
                     dataflow::backward_analysis_tag) {
 
+    TF.setCurrentBlock(B);
+    
     TF.VisitTerminator(const_cast<CFGBlock*>(B));
 
-    for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
-      ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
+    for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
+      CFGElement El = *I;
+      if (CFGStmt S = El.getAs<CFGStmt>())
+        ProcessStmt(S, recordStmtValues, AnalysisDirTag());
+    }
   }
 
   void ProcessStmt(const Stmt* S, bool record, dataflow::forward_analysis_tag) {
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index ba303de..54cfc3d 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -17,7 +17,7 @@
 
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/CFG.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/Support/Casting.h"
@@ -44,6 +44,7 @@ public:
               PostPurgeDeadSymbolsKind,
               PostStmtCustomKind,
               PostLValueKind,
+              PostInitializerKind,
               CallEnterKind,
               CallExitKind,
               MinPostStmtKind = PostStmtKind,
@@ -70,11 +71,12 @@ protected:
 protected:
   const void* getData1() const { return Data.first; }
   const void* getData2() const { return Data.second; }
-  const void *getTag() const { return Tag; }
 
 public:
   Kind getKind() const { return K; }
 
+  const void *getTag() const { return Tag; }
+
   const LocationContext *getLocationContext() const { return L; }
 
   // For use with DenseMap.  This hash is probably slow.
@@ -118,10 +120,12 @@ public:
     return B->empty() ? CFGElement() : B->front();
   }
   
-  const Stmt *getFirstStmt() const {
-    return getFirstElement().getStmt();
+  /// Create a new BlockEntrance object that is the same as the original
+  /// except for using the specified tag value.
+  BlockEntrance withTag(const void *tag) {
+    return BlockEntrance(getBlock(), getLocationContext(), tag);
   }
-
+  
   static bool classof(const ProgramPoint* Location) {
     return Location->getKind() == BlockEntranceKind;
   }
@@ -136,11 +140,6 @@ public:
     return reinterpret_cast<const CFGBlock*>(getData1());
   }
 
-  const Stmt* getLastStmt() const {
-    const CFGBlock* B = getBlock();
-    return B->empty() ? CFGElement() : B->back();
-  }
-
   const Stmt* getTerminator() const {
     return getBlock()->getTerminator();
   }
@@ -183,14 +182,15 @@ public:
 
 class PostStmt : public StmtPoint {
 protected:
-  PostStmt(const Stmt* S, Kind k, const LocationContext *L, const void *tag = 0)
-    : StmtPoint(S, NULL, k, L, tag) {}
-
   PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L,
            const void *tag =0)
     : StmtPoint(S, data, k, L, tag) {}
 
 public:
+  explicit PostStmt(const Stmt* S, Kind k, 
+                    const LocationContext *L, const void *tag = 0)
+    : StmtPoint(S, NULL, k, L, tag) {}
+
   explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0)
     : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
 
@@ -313,19 +313,29 @@ public:
   }
 };
 
+class PostInitializer : public ProgramPoint {
+public:
+  PostInitializer(const CXXCtorInitializer *I, 
+                  const LocationContext *L)
+    : ProgramPoint(I, PostInitializerKind, L) {}
+
+  static bool classof(const ProgramPoint *Location) {
+    return Location->getKind() == PostInitializerKind;
+  }
+};
+
 class CallEnter : public StmtPoint {
 public:
-  // L is caller's location context. AC is callee's AnalysisContext.
-  CallEnter(const Stmt *S, const AnalysisContext *AC, const LocationContext *L)
-    : StmtPoint(S, AC, CallEnterKind, L, 0) {}
+  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, 
+            const LocationContext *callerCtx)
+    : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
 
   const Stmt *getCallExpr() const {
     return static_cast<const Stmt *>(getData1());
   }
 
-  AnalysisContext *getCalleeContext() const {
-    return const_cast<AnalysisContext *>(
-                              static_cast<const AnalysisContext *>(getData2()));
+  const StackFrameContext *getCalleeContext() const {
+    return static_cast<const StackFrameContext *>(getData2());
   }
 
   static bool classof(const ProgramPoint *Location) {
diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h
index 7cd4812..83532e6 100644
--- a/include/clang/Analysis/Support/BumpVector.h
+++ b/include/clang/Analysis/Support/BumpVector.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/PointerIntPair.h"
 #include <algorithm>
 #include <cstring>
+#include <iterator>
 #include <memory>
 
 namespace clang {
@@ -155,7 +156,25 @@ public:
     grow(C);
     goto Retry;    
   }
-  
+
+  /// insert - Insert some number of copies of element into a position. Return
+  /// iterator to position after last inserted copy.
+  iterator insert(iterator I, size_t Cnt, const_reference E,
+      BumpVectorContext &C) {
+    assert (I >= Begin && I <= End && "Iterator out of bounds.");
+    if (End + Cnt <= Capacity) {
+    Retry:
+      move_range_right(I, End, Cnt);
+      construct_range(I, I + Cnt, E);
+      End += Cnt;
+      return I + Cnt;
+    }
+    ptrdiff_t D = I - Begin;
+    grow(C, size() + Cnt);
+    I = Begin + D;
+    goto Retry;
+  }
+
   void reserve(BumpVectorContext &C, unsigned N) {
     if (unsigned(Capacity-Begin) < N)
       grow(C, N);
@@ -181,6 +200,14 @@ private:
       E->~T();
     }
   }
+
+  void move_range_right(T *S, T *E, size_t D) {
+    for (T *I = E + D - 1, *IL = S + D - 1; I != IL; --I) {
+      --E;
+      new (I) T(*E);
+      E->~T();
+    }
+  }
 };
   
 // Define this out-of-line to dissuade the C++ compiler from inlining it.
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
index f20a49a..95f4ace 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -66,6 +66,8 @@ public:
         DISPATCH_CASE(Record)    // FIXME: Refine.  VisitStructDecl?
         DISPATCH_CASE(CXXRecord)
         DISPATCH_CASE(Enum)
+        DISPATCH_CASE(UsingDirective)
+        DISPATCH_CASE(Using)
       default:
         assert(false && "Subtype of ScopedDecl not handled.");
     }
@@ -85,6 +87,8 @@ public:
   DEFAULT_DISPATCH(ObjCMethod)
   DEFAULT_DISPATCH(ObjCProtocol)
   DEFAULT_DISPATCH(ObjCCategory)
+  DEFAULT_DISPATCH(UsingDirective)
+  DEFAULT_DISPATCH(Using)
 
   void VisitCXXRecordDecl(CXXRecordDecl *D) {
     static_cast<ImplClass*>(this)->VisitRecordDecl(D);
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
index 75a4ac6..bb7cf0b 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
@@ -26,6 +26,11 @@ public:
     static_cast< ImplClass* >(this)->VisitChildren(S);
   }
   
+  void VisitCompoundStmt(CompoundStmt *S) {
+    // Do nothing.  Everything in a CompoundStmt is inlined
+    // into the CFG.
+  }
+  
   void VisitConditionVariableInit(Stmt *S) {
     assert(S == this->getCurrentBlkStmt());
     VarDecl *CondVar = 0;
diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
index 6421f18..d197e69 100644
--- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
@@ -80,6 +80,7 @@ public:
 
       DISPATCH_CASE(StmtExpr)
       DISPATCH_CASE(ConditionalOperator)
+      DISPATCH_CASE(BinaryConditionalOperator)
       DISPATCH_CASE(ObjCForCollectionStmt)
 
       case Stmt::BinaryOperatorClass: {
@@ -102,6 +103,7 @@ public:
 
   DEFAULT_BLOCKSTMT_VISIT(StmtExpr)
   DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
+  DEFAULT_BLOCKSTMT_VISIT(BinaryConditionalOperator)
 
   RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
     return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
@@ -155,7 +157,7 @@ public:
       }
     }
 
-    for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
+    for (Stmt::child_range I = S->children(); I; ++I)
       if (*I) static_cast<ImplClass*>(this)->Visit(*I);
   }
 };
-- 
cgit v1.1