Index: lib/Analysis/CFG.cpp =================================================================== --- lib/Analysis/CFG.cpp +++ lib/Analysis/CFG.cpp @@ -1458,16 +1458,15 @@ if (const CastExpr *CE = dyn_cast(Init)) { if ((CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_UncheckedDerivedToBase || - CE->getCastKind() == CK_NoOp) && - Init->getType()->isRecordType()) { + CE->getCastKind() == CK_NoOp)) { Init = CE->getSubExpr(); continue; } } - // Skip member accesses into rvalues. + // Skip member accesses. if (const MemberExpr *ME = dyn_cast(Init)) { - if (!ME->isArrow() && ME->getBase()->isRValue()) { + if (!ME->isArrow()) { Init = ME->getBase(); continue; } @@ -4873,10 +4872,12 @@ const VarDecl *VD = DE->getVarDecl(); Helper.handleDecl(VD, OS); - const Type* T = VD->getType().getTypePtr(); - if (const ReferenceType* RT = T->getAs()) - T = RT->getPointeeType().getTypePtr(); - T = T->getBaseElementTypeUnsafe(); + ASTContext &ACtx = VD->getASTContext(); + QualType T = VD->getType(); + if (T->isReferenceType()) + T = getReferenceInitTemporaryType(ACtx, VD->getInit(), nullptr); + if (const ArrayType *AT = ACtx.getAsArrayType(T)) + T = ACtx.getBaseElementType(AT); OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; OS << " (Implicit destructor)\n"; Index: test/Analysis/auto-obj-dtors-cfg-output.cpp =================================================================== --- test/Analysis/auto-obj-dtors-cfg-output.cpp +++ test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -14,6 +14,8 @@ class A { public: + int x; + // CHECK: [B1 (ENTRY)] // CHECK-NEXT: Succs (1): B0 // CHECK: [B0 (EXIT)] @@ -67,6 +69,25 @@ const A& c = A(); } +// CHECK: [B2 (ENTRY)] +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// WARNINGS-NEXT: 1: A() (CXXConstructExpr, class A) +// ANALYZER-NEXT: 1: A() (CXXConstructExpr, [B1.2], [B1.3], class A) +// CHECK-NEXT: 2: [B1.1] (BindTemporary) +// CHECK-NEXT: 3: [B1.2] +// CHECK-NEXT: 4: [B1.3].x +// CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const int) +// CHECK-NEXT: 6: const int &x = A().x; +// CHECK-NEXT: 7: [B1.6].~A() (Implicit destructor) +// CHECK-NEXT: Preds (1): B2 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 +void test_const_ref_to_field() { + const int &x = A().x; +} + // CHECK: [B2 (ENTRY)] // CHECK-NEXT: Succs (1): B1 // CHECK: [B1]