Index: test/Analysis/temp-obj-dtors-cfg-output.cpp
===================================================================
--- test/Analysis/temp-obj-dtors-cfg-output.cpp	(revision 0)
+++ test/Analysis/temp-obj-dtors-cfg-output.cpp	(revision 0)
@@ -0,0 +1,581 @@
+// RUN: %clang_cc1 -analyze -cfg-dump -cfg-add-implicit-dtors -cfg-add-initializers %s 2>&1 | FileCheck %s
+// XPASS: *
+
+class A {
+public:
+  A() {}
+  ~A() {}
+
+  static A make() { return A(); }
+
+  operator bool() { return false; }
+  operator int() { return 0; }
+};
+
+class B {
+public:
+  B() {}
+  ~B() {}
+
+  operator bool() { return true; }
+  operator int() { return 1; }
+  operator A() { return A(); }
+};
+
+void foo(int);
+void foo(bool);
+void foo(const A&);
+
+void test_binary() {
+  int a = int(A()) + int(B());
+  foo(int(A()) + int(B()));
+  int b;
+}
+
+void test_and() {
+  bool a = A() && B();
+  foo(A() && B());
+  int b;
+}
+
+void test_or() {
+  bool a = A() || B();
+  foo(A() || B());
+  int b;
+}
+
+void test_cond() {
+  A a = B() ? A() : A(B());
+  if (B()) { foo(0); } else { foo(0); }
+  int b;
+}
+
+void test_cond_cref() {
+  const A& a = B() ? A() : A(B());
+  foo(B() ? A() : A(B()));
+  int b;
+}
+
+void test_cond_implicit() {
+  A a = A() ?: A();
+  int b;
+}
+
+void test_cond_implicit_cref() {
+  const A& a = A() ?: A();
+  foo(A() ?: A());
+  int b;
+}
+
+void test_copy_init() {
+  A a = A();
+  int b;
+}
+
+void test_cref_init() {
+  const A& a = A();
+  foo(A());
+  int b;
+}
+
+void test_call_copy_init() {
+  A a = A::make();
+  int b;
+}
+
+void test_call_cref_init() {
+  const A& a = A::make();
+  foo(A::make());
+  int b;
+}
+
+void test_assign() {
+  int a;
+  a = A();
+  int b;
+}
+
+class TestCtorInits {
+  int a;
+  int b;
+public:
+  TestCtorInits();
+};
+
+TestCtorInits::TestCtorInits()
+  : a(int(A()) + int(B()))
+  , b() {}
+
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: [B1.1].operator int()
+// CHECK:       3: B()
+// CHECK:       4: [B1.3].operator int()
+// CHECK:       5: int a = int(A().operator int()) + int(B().operator int());
+// CHECK:       6: ~B() (Temporary object destructor)
+// CHECK:       7: ~A() (Temporary object destructor)
+// CHECK:       8: A()
+// CHECK:       9: [B1.8].operator int()
+// CHECK:      10: B()
+// CHECK:      11: [B1.10].operator int()
+// CHECK:      12: foo(int([B1.9]) + int([B1.11]))
+// CHECK:      13: ~B() (Temporary object destructor)
+// CHECK:      14: ~A() (Temporary object destructor)
+// CHECK:      15: int b;
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B10 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B8
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B4.3] && [B5.2]
+// CHECK:       2: foo([B3.1])
+// CHECK:       T: [B4.3] && ...
+// CHECK:     Predecessors (2): B5 B4
+// CHECK:     Successors (2): B2 B1
+// CHECK:  [ B4 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: A()
+// CHECK:       3: [B4.2].operator _Bool()
+// CHECK:       T: [B4.3] && ...
+// CHECK:     Predecessors (2): B6 B7
+// CHECK:     Successors (2): B5 B3
+// CHECK:  [ B5 ]
+// CHECK:       1: B()
+// CHECK:       2: [B5.1].operator _Bool()
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B3
+// CHECK:  [ B6 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B8.2] && [B9.2]
+// CHECK:       2: bool a = A().operator _Bool() && B().operator _Bool();
+// CHECK:       T: [B8.2] && ...
+// CHECK:     Predecessors (2): B9 B8
+// CHECK:     Successors (2): B6 B4
+// CHECK:  [ B8 ]
+// CHECK:       1: A()
+// CHECK:       2: [B8.1].operator _Bool()
+// CHECK:       T: [B8.2] && ...
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (2): B9 B7
+// CHECK:  [ B9 ]
+// CHECK:       1: B()
+// CHECK:       2: [B9.1].operator _Bool()
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B7
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B10 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B8
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B4.3] || [B5.2]
+// CHECK:       2: foo([B3.1])
+// CHECK:       T: [B4.3] || ...
+// CHECK:     Predecessors (2): B5 B4
+// CHECK:     Successors (2): B1 B2
+// CHECK:  [ B4 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: A()
+// CHECK:       3: [B4.2].operator _Bool()
+// CHECK:       T: [B4.3] || ...
+// CHECK:     Predecessors (2): B6 B7
+// CHECK:     Successors (2): B3 B5
+// CHECK:  [ B5 ]
+// CHECK:       1: B()
+// CHECK:       2: [B5.1].operator _Bool()
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B3
+// CHECK:  [ B6 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B8.2] || [B9.2]
+// CHECK:       2: bool a = A().operator _Bool() || B().operator _Bool();
+// CHECK:       T: [B8.2] || ...
+// CHECK:     Predecessors (2): B9 B8
+// CHECK:     Successors (2): B4 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: A()
+// CHECK:       2: [B8.1].operator _Bool()
+// CHECK:       T: [B8.2] || ...
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (2): B7 B9
+// CHECK:  [ B9 ]
+// CHECK:       1: B()
+// CHECK:       2: [B9.1].operator _Bool()
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B7
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B11 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B10
+// CHECK:  [ B1 ]
+// CHECK:       1: int b;
+// CHECK:       2: [B7.3].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: foo(0)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: foo(0)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:       2: B()
+// CHECK:       3: [B4.2].operator _Bool()
+// CHECK:       4: ~B() (Temporary object destructor)
+// CHECK:       T: if [B4.3]
+// CHECK:     Predecessors (2): B5 B6
+// CHECK:     Successors (2): B3 B2
+// CHECK:  [ B5 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B6 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:       3: ~A() (Temporary object destructor)
+// CHECK:       4: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: [B10.2] ? [B8.3] : [B9.5]
+// CHECK:       2: [B7.1]
+// CHECK:       3: A a = B().operator _Bool() ? A() : A(B().operator A());
+// CHECK:       T: [B10.2] ? ... : ...
+// CHECK:     Predecessors (2): B8 B9
+// CHECK:     Successors (2): B5 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: A()
+// CHECK:       2: [B8.1]
+// CHECK:       3: [B8.2] (BindTemporary)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B9 ]
+// CHECK:       1: B()
+// CHECK:       2: [B9.1].operator A()
+// CHECK:       3: [B9.2]
+// CHECK:       4: A([B9.3])
+// CHECK:       5: [B9.4] (BindTemporary)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B10 ]
+// CHECK:       1: B()
+// CHECK:       2: [B10.1].operator _Bool()
+// CHECK:       T: [B10.2] ? ... : ...
+// CHECK:     Predecessors (1): B11
+// CHECK:     Successors (2): B8 B9
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B14 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B13
+// CHECK:  [ B1 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:       3: [B10.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:       3: ~A() (Temporary object destructor)
+// CHECK:       4: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: [B7.3] ? [B5.3] : [B6.5]
+// CHECK:       2: foo([B4.1])
+// CHECK:       T: [B7.3] ? ... : ...
+// CHECK:     Predecessors (2): B5 B6
+// CHECK:     Successors (2): B2 B3
+// CHECK:  [ B5 ]
+// CHECK:       1: A()
+// CHECK:       2: [B5.1]
+// CHECK:       3: [B5.2] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B6 ]
+// CHECK:       1: B()
+// CHECK:       2: [B6.1].operator A()
+// CHECK:       3: [B6.2]
+// CHECK:       4: A([B6.3])
+// CHECK:       5: [B6.4] (BindTemporary)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B4
+// CHECK:  [ B7 ]
+// CHECK:       1: ~B() (Temporary object destructor)
+// CHECK:       2: B()
+// CHECK:       3: [B7.2].operator _Bool()
+// CHECK:       T: [B7.3] ? ... : ...
+// CHECK:     Predecessors (2): B8 B9
+// CHECK:     Successors (2): B5 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B9 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:       3: ~B() (Temporary object destructor)
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (1): B7
+// CHECK:  [ B10 ]
+// CHECK:       1: [B13.2] ? [B11.3] : [B12.5]
+// CHECK:       2: const A &a = B().operator _Bool() ? A() : A(B().operator A());
+// CHECK:       T: [B13.2] ? ... : ...
+// CHECK:     Predecessors (2): B11 B12
+// CHECK:     Successors (2): B8 B9
+// CHECK:  [ B11 ]
+// CHECK:       1: A()
+// CHECK:       2: [B11.1]
+// CHECK:       3: [B11.2] (BindTemporary)
+// CHECK:     Predecessors (1): B13
+// CHECK:     Successors (1): B10
+// CHECK:  [ B12 ]
+// CHECK:       1: B()
+// CHECK:       2: [B12.1].operator A()
+// CHECK:       3: [B12.2]
+// CHECK:       4: A([B12.3])
+// CHECK:       5: [B12.4] (BindTemporary)
+// CHECK:     Predecessors (1): B13
+// CHECK:     Successors (1): B10
+// CHECK:  [ B13 ]
+// CHECK:       1: B()
+// CHECK:       2: [B13.1].operator _Bool()
+// CHECK:       T: [B13.2] ? ... : ...
+// CHECK:     Predecessors (1): B14
+// CHECK:     Successors (2): B11 B12
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B6 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B5
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:       3: [B3.3].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B3 B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B5.2] ?: [B4.3]
+// CHECK:       2: [B3.1]
+// CHECK:       3: A a = A().operator _Bool() ?: A();
+// CHECK:       T: [B5.2] ? ... : ...
+// CHECK:     Predecessors (2): B5 B4
+// CHECK:     Successors (2): B1 B2
+// CHECK:  [ B4 ]
+// CHECK:       1: A()
+// CHECK:       2: [B4.1]
+// CHECK:       3: [B4.2] (BindTemporary)
+// CHECK:     Predecessors (1): B5
+// CHECK:     Successors (1): B3
+// CHECK:  [ B5 ]
+// CHECK:       1: A()
+// CHECK:       2: [B5.1].operator _Bool()
+// CHECK:       T: [B5.2] ? ... : ...
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (2): B3 B4
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B10 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B9
+// CHECK:  [ B1 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: int b;
+// CHECK:       3: [B7.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B3 B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B5.3] ?: [B4.3]
+// CHECK:       2: foo([B3.1])
+// CHECK:       T: [B5.3] ? ... : ...
+// CHECK:     Predecessors (2): B5 B4
+// CHECK:     Successors (2): B1 B2
+// CHECK:  [ B4 ]
+// CHECK:       1: A()
+// CHECK:       2: [B4.1]
+// CHECK:       3: [B4.2] (BindTemporary)
+// CHECK:     Predecessors (1): B5
+// CHECK:     Successors (1): B3
+// CHECK:  [ B5 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:       2: A()
+// CHECK:       3: [B5.2].operator _Bool()
+// CHECK:       T: [B5.3] ? ... : ...
+// CHECK:     Predecessors (2): B7 B6
+// CHECK:     Successors (2): B3 B4
+// CHECK:  [ B6 ]
+// CHECK:       1: ~A() (Temporary object destructor)
+// CHECK:     Predecessors (1): B7
+// CHECK:     Successors (1): B5
+// CHECK:  [ B7 ]
+// CHECK:       1: [B9.2] ?: [B8.3]
+// CHECK:       2: const A &a = A().operator _Bool() ?: A();
+// CHECK:       T: [B9.2] ? ... : ...
+// CHECK:     Predecessors (2): B9 B8
+// CHECK:     Successors (2): B5 B6
+// CHECK:  [ B8 ]
+// CHECK:       1: A()
+// CHECK:       2: [B8.1]
+// CHECK:       3: [B8.2] (BindTemporary)
+// CHECK:     Predecessors (1): B9
+// CHECK:     Successors (1): B7
+// CHECK:  [ B9 ]
+// CHECK:       1: A()
+// CHECK:       2: [B9.1].operator _Bool()
+// CHECK:       T: [B9.2] ? ... : ...
+// CHECK:     Predecessors (1): B10
+// CHECK:     Successors (2): B7 B8
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: [B1.1]
+// CHECK:       3: A a = A();
+// CHECK:       4: ~A() (Temporary object destructor)
+// CHECK:       5: int b;
+// CHECK:       6: [B1.3].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: const A &a = A();
+// CHECK:       3: A()
+// CHECK:       4: foo([B1.3])
+// CHECK:       5: ~A() (Temporary object destructor)
+// CHECK:       6: int b;
+// CHECK:       7: [B1.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A::make()
+// CHECK:       2: [B1.1]
+// CHECK:       3: A a = A::make();
+// CHECK:       4: ~A() (Temporary object destructor)
+// CHECK:       5: int b;
+// CHECK:       6: [B1.3].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A::make()
+// CHECK:       2: const A &a = A::make();
+// CHECK:       3: A::make()
+// CHECK:       4: foo([B1.3])
+// CHECK:       5: ~A() (Temporary object destructor)
+// CHECK:       6: int b;
+// CHECK:       7: [B1.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: int a;
+// CHECK:       2: A()
+// CHECK:       3: [B1.2].operator int()
+// CHECK:       4: a = [B1.3]
+// CHECK:       5: ~A() (Temporary object destructor)
+// CHECK:       6: int b;
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A()
+// CHECK:       2: [B1.1].operator int()
+// CHECK:       3: B()
+// CHECK:       4: [B1.3].operator int()
+// CHECK:       5: a(int([B1.2]) + int([B1.4])) (Member initializer)
+// CHECK:       6: ~B() (Temporary object destructor)
+// CHECK:       7: ~A() (Temporary object destructor)
+// CHECK:       8: b(/*implicit*/int()) (Member initializer)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
Index: include/clang/Analysis/CFG.h
===================================================================
--- include/clang/Analysis/CFG.h	(revision 117909)
+++ include/clang/Analysis/CFG.h	(working copy)
@@ -35,6 +35,7 @@
   class VarDecl;
   class CXXBaseOrMemberInitializer;
   class CXXBaseSpecifier;
+  class CXXBindTemporaryExpr;
   class CFG;
   class PrinterHelper;
   class LangOptions;
@@ -198,8 +199,18 @@
   }
 };
 
+/// 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() == Dtor && E->getDtorKind() == TemporaryDtor;
   }
@@ -495,6 +506,10 @@
   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
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp	(revision 117909)
+++ lib/Analysis/CFG.cpp	(working copy)
@@ -258,6 +258,8 @@
   CFGBlock *VisitBlockExpr(BlockExpr* E, AddStmtChoice asc);
   CFGBlock *VisitBreakStmt(BreakStmt *B);
   CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
+  CFGBlock *VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E,
+      AddStmtChoice asc);
   CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
   CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
   CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 
@@ -275,7 +277,7 @@
   CFGBlock *VisitConditionalOperator(ConditionalOperator *C, AddStmtChoice asc);
   CFGBlock *VisitContinueStmt(ContinueStmt *C);
   CFGBlock *VisitDeclStmt(DeclStmt *DS);
-  CFGBlock *VisitDeclSubExpr(Decl* D);
+  CFGBlock *VisitDeclSubExpr(DeclStmt* DS);
   CFGBlock *VisitDefaultStmt(DefaultStmt *D);
   CFGBlock *VisitDoStmt(DoStmt *D);
   CFGBlock *VisitForStmt(ForStmt *F);
@@ -300,6 +302,16 @@
   CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
   CFGBlock *VisitChildren(Stmt* S);
 
+  // Visitors to walk an AST and generate destructors of temporaries in
+  // full expression.
+  CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false);
+  CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E);
+  CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E);
+  CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E,
+      bool BindToTemporary);
+  CFGBlock *VisitConditionalOperatorForTemporaryDtors(ConditionalOperator *E,
+      bool BindToTemporary);
+
   // NYS == Not Yet Supported
   CFGBlock* NYS() {
     badCFG = true;
@@ -340,6 +352,9 @@
   void appendMemberDtor(CFGBlock *B, FieldDecl *FD) {
     B->appendMemberDtor(FD, cfg->getBumpVectorContext());
   }
+  void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
+    B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
+  }
 
   void insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I,
     LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S);
@@ -498,18 +513,38 @@
   if (!BuildOpts.AddInitializers)
     return Block;
 
+  bool IsReference = false;
+  bool HasTemporaries = false;
+
+  // Destructors of temporaries in initialization expression should be called
+  // after initialization finishes.
+  Expr *Init = I->getInit();
+  if (Init) {
+    if (FieldDecl *FD = I->getMember())
+      IsReference = FD->getType()->isReferenceType();
+    HasTemporaries = isa<CXXExprWithTemporaries>(Init);
+
+    if (BuildOpts.AddImplicitDtors && HasTemporaries) {
+      // Generate destructors for temporaries in initialization expression.
+      VisitForTemporaryDtors(cast<CXXExprWithTemporaries>(Init)->getSubExpr(),
+          IsReference);
+    }
+  }
+
   autoCreateBlock();
   appendInitializer(Block, I);
 
-  if (Expr *Init = I->getInit()) {
-    AddStmtChoice::Kind K = AddStmtChoice::NotAlwaysAdd;
-    if (FieldDecl *FD = I->getMember())
-      if (FD->getType()->isReferenceType())
-        K = AddStmtChoice::AsLValueNotAlwaysAdd;
+  if (Init) {
+    AddStmtChoice asc = IsReference
+        ? AddStmtChoice::AsLValueNotAlwaysAdd
+        : AddStmtChoice::NotAlwaysAdd;
+    if (HasTemporaries)
+      // For expression with temporaries go directly to subexpression to omit
+      // generating destructors for the second time.
+      return Visit(cast<CXXExprWithTemporaries>(Init)->getSubExpr(), asc);
+    return Visit(Init, asc);
+  }
 
-    return Visit(Init, AddStmtChoice(K));
-  }
-  
   return Block;
 }
 
@@ -763,11 +798,8 @@
     case Stmt::CXXCatchStmtClass:
       return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
 
-    case Stmt::CXXExprWithTemporariesClass: {
-      // FIXME: Handle temporaries.  For now, just visit the subexpression
-      // so we don't artificially create extra blocks.
-      return Visit(cast<CXXExprWithTemporaries>(S)->getSubExpr(), asc);
-    }
+    case Stmt::CXXExprWithTemporariesClass:
+      return VisitCXXExprWithTemporaries(cast<CXXExprWithTemporaries>(S), asc);
 
     case Stmt::CXXBindTemporaryExprClass:
       return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc);
@@ -1184,13 +1216,9 @@
 }
 
 CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
-  autoCreateBlock();
+  if (DS->isSingleDecl())
+    return VisitDeclSubExpr(DS);
 
-  if (DS->isSingleDecl()) {
-    AppendStmt(Block, DS);
-    return VisitDeclSubExpr(DS->getSingleDecl());
-  }
-
   CFGBlock *B = 0;
 
   // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy.
@@ -1210,30 +1238,55 @@
     DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
 
     // Append the fake DeclStmt to block.
-    AppendStmt(Block, DSNew);
-    B = VisitDeclSubExpr(D);
+    B = VisitDeclSubExpr(DSNew);
   }
 
   return B;
 }
 
 /// VisitDeclSubExpr - Utility method to add block-level expressions for
-///  initializers in Decls.
-CFGBlock *CFGBuilder::VisitDeclSubExpr(Decl* D) {
-  assert(Block);
+/// DeclStmts and initializers in them.
+CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) {
+  assert(DS->isSingleDecl() && "Can handle single declarations only.");
 
-  VarDecl *VD = dyn_cast<VarDecl>(D);
+  VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
 
-  if (!VD)
+  if (!VD) {
+    autoCreateBlock();
+    AppendStmt(Block, DS);
     return Block;
+  }
 
+  bool IsReference = false;
+  bool HasTemporaries = false;
+
+  // Destructors of temporaries in initialization expression should be called
+  // after initialization finishes.
   Expr *Init = VD->getInit();
+  if (Init) {
+    IsReference = VD->getType()->isReferenceType();
+    HasTemporaries = isa<CXXExprWithTemporaries>(Init);
 
+    if (BuildOpts.AddImplicitDtors && HasTemporaries) {
+      // Generate destructors for temporaries in initialization expression.
+      VisitForTemporaryDtors(cast<CXXExprWithTemporaries>(Init)->getSubExpr(),
+          IsReference);
+    }
+  }
+
+  autoCreateBlock();
+  AppendStmt(Block, DS);
+
   if (Init) {
-    AddStmtChoice::Kind k =
-      VD->getType()->isReferenceType() ? AddStmtChoice::AsLValueNotAlwaysAdd
-                                       : AddStmtChoice::NotAlwaysAdd;
-    Visit(Init, AddStmtChoice(k));
+    AddStmtChoice asc = IsReference
+          ? AddStmtChoice::AsLValueNotAlwaysAdd
+          : AddStmtChoice::NotAlwaysAdd;
+    if (HasTemporaries)
+      // For expression with temporaries go directly to subexpression to omit
+      // generating destructors for the second time.
+      Visit(cast<CXXExprWithTemporaries>(Init)->getSubExpr(), asc);
+    else
+      Visit(Init, asc);
   }
 
   // If the type of VD is a VLA, then we must process its size expressions.
@@ -2305,6 +2358,22 @@
   return CatchBlock;
 }
 
+CFGBlock *CFGBuilder::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E,
+    AddStmtChoice asc) {
+  if (BuildOpts.AddImplicitDtors) {
+    // If adding implicit destructors visit the full expression for adding
+    // destructors of temporaries.
+    VisitForTemporaryDtors(E->getSubExpr());
+
+    // Full expression has to be added as CFGStmt so it will be sequenced
+    // before destructors of it's temporaries.
+    asc = asc.asLValue()
+        ? AddStmtChoice::AlwaysAddAsLValue
+        : AddStmtChoice::AlwaysAdd;
+  }
+  return Visit(E->getSubExpr(), asc);
+}
+
 CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
                                                 AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
@@ -2389,6 +2458,196 @@
   return addStmt(I->getTarget());
 }
 
+CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) {
+tryAgain:
+  if (!E) {
+    badCFG = true;
+    return NULL;
+  }
+  switch (E->getStmtClass()) {
+    default:
+      return VisitChildrenForTemporaryDtors(E);
+
+    case Stmt::BinaryOperatorClass:
+      return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E));
+
+    case Stmt::CXXBindTemporaryExprClass:
+      return VisitCXXBindTemporaryExprForTemporaryDtors(
+          cast<CXXBindTemporaryExpr>(E), BindToTemporary);
+
+    case Stmt::ConditionalOperatorClass:
+      return VisitConditionalOperatorForTemporaryDtors(
+          cast<ConditionalOperator>(E), BindToTemporary);
+
+    case Stmt::ImplicitCastExprClass:
+      // For implicit cast we want BindToTemporary to be passed further.
+      E = cast<CastExpr>(E)->getSubExpr();
+      goto tryAgain;
+
+    case Stmt::ParenExprClass:
+      E = cast<ParenExpr>(E)->getSubExpr();
+      goto tryAgain;
+  }
+}
+
+CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) {
+  // When visiting children for destructors we want to visit them in reverse
+  // order. Because there's no reverse iterator for children must to reverse
+  // them in helper vector.
+  typedef llvm::SmallVector<Stmt *, 4> ChildrenVect;
+  ChildrenVect ChildrenRev;
+  for (Stmt::child_iterator I = E->child_begin(), L = E->child_end();
+      I != L; ++I) {
+    if (*I) ChildrenRev.push_back(*I);
+  }
+
+  CFGBlock *B = Block;
+  for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(),
+      L = ChildrenRev.rend(); I != L; ++I) {
+    if (CFGBlock *R = VisitForTemporaryDtors(*I))
+      B = R;
+  }
+  return B;
+}
+
+CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) {
+  if (E->isLogicalOp()) {
+    // Destructors for temporaries in LHS expression should be called after
+    // those for RHS expression. Even if this will unnecessarily create a block,
+    // this block will be used at least by the full expression.
+    autoCreateBlock();
+    CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS());
+    if (badCFG)
+      return NULL;
+
+    Succ = ConfluenceBlock;
+    Block = NULL;
+    CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS());
+
+    if (RHSBlock) {
+      if (badCFG)
+        return NULL;
+
+      // If RHS expression did produce destructors we need to connect created
+      // blocks to CFG in same manner as for binary operator itself.
+      CFGBlock *LHSBlock = createBlock(false);
+      LHSBlock->setTerminator(CFGTerminator(E, true));
+
+      // For binary operator LHS block is before RHS in list of predecessors
+      // of ConfluenceBlock.
+      std::reverse(ConfluenceBlock->pred_begin(),
+          ConfluenceBlock->pred_end());
+
+      // See if this is a known constant.
+      TryResult KnownVal = TryEvaluateBool(E->getLHS());
+      if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr))
+        KnownVal.negate();
+
+      // Link LHSBlock with RHSBlock exactly the same way as for binary operator
+      // itself.
+      if (E->getOpcode() == BO_LOr) {
+        AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+        AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+      } else {
+        assert (E->getOpcode() == BO_LAnd);
+        AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
+        AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
+      }
+
+      Block = LHSBlock;
+      return LHSBlock;
+    }
+
+    Block = ConfluenceBlock;
+    return ConfluenceBlock;
+  }
+
+  else if (E->isAssignmentOp()) {
+    // For assignment operator (=) LHS expression is visited
+    // before RHS expression. For destructors visit them in reverse order.
+    CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS());
+    CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS());
+    return LHSBlock ? LHSBlock : RHSBlock;
+  }
+
+  // For any other binary operator RHS expression is visited before
+  // LHS expression (order of children). For destructors visit them in reverse
+  // order.
+  CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS());
+  CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS());
+  return RHSBlock ? RHSBlock : LHSBlock;
+}
+
+CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
+    CXXBindTemporaryExpr *E, bool BindToTemporary) {
+  // First add destructors for temporaries in subexpression.
+  CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr());
+  if (!BindToTemporary) {
+    // If lifetime of temporary is not prolonged (by assigning to constant
+    // reference) add destructor for it.
+    autoCreateBlock();
+    appendTemporaryDtor(Block, E);
+    B = Block;
+  }
+  return B;
+}
+
+CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
+    ConditionalOperator *E, bool BindToTemporary) {
+  // First add destructors for condition expression.  Even if this will
+  // unnecessarily create a block, this block will be used at least by the full
+  // expression.
+  autoCreateBlock();
+  CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond());
+  if (badCFG)
+    return NULL;
+
+  // Try to add block with destructors for LHS expression.
+  CFGBlock *LHSBlock = NULL;
+  if (E->getLHS()) {
+    Succ = ConfluenceBlock;
+    Block = NULL;
+    LHSBlock = VisitForTemporaryDtors(E->getLHS(), BindToTemporary);
+    if (badCFG)
+      return NULL;
+  }
+
+  // Try to add block with destructors for RHS expression;
+  Succ = ConfluenceBlock;
+  Block = NULL;
+  CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), BindToTemporary);
+  if (badCFG)
+    return NULL;
+
+  if (!RHSBlock && !LHSBlock) {
+    // If neither LHS nor RHS expression had temporaries to destroy don't create
+    // more blocks.
+    Block = ConfluenceBlock;
+    return Block;
+  }
+
+  Block = createBlock(false);
+  Block->setTerminator(CFGTerminator(E, true));
+
+  // See if this is a known constant.
+  const TryResult &KnownVal = TryEvaluateBool(E->getCond());
+
+  if (LHSBlock) {
+    AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
+  } else if (KnownVal.isFalse()) {
+    AddSuccessor(Block, NULL);
+  } else {
+    AddSuccessor(Block, ConfluenceBlock);
+    std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end());
+  }
+
+  if (!RHSBlock)
+    RHSBlock = ConfluenceBlock;
+  AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
+
+  return Block;
+}
+
 } // end anonymous namespace
 
 /// createBlock - Constructs and adds a new CFGBlock to the CFG.  The block has
@@ -2828,6 +3087,11 @@
     OS << "this->" << FD->getName();
     OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()";
     OS << " (Member object destructor)\n";
+
+  } else if (CFGTemporaryDtor TE = E.getAs<CFGTemporaryDtor>()) {
+    CXXBindTemporaryExpr *BT = TE.getBindTemporaryExpr();
+    OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()";
+    OS << " (Temporary object destructor)\n";
   }
 }
 
