Izaron updated this revision to Diff 416116.
Izaron added a comment.
Herald added a project: All.

Rebased the patch on top of D119927 <https://reviews.llvm.org/D119927>


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119792/new/

https://reviews.llvm.org/D119792

Files:
  clang/include/clang/Sema/Scope.h
  clang/lib/Sema/Scope.cpp
  clang/test/CodeGenCXX/nrvo.cpp

Index: clang/test/CodeGenCXX/nrvo.cpp
===================================================================
--- clang/test/CodeGenCXX/nrvo.cpp
+++ clang/test/CodeGenCXX/nrvo.cpp
@@ -167,81 +167,13 @@
 
 // CHECK-LABEL: @_Z5test3b(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
-// CHECK:       if.then:
 // CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
-// CHECK-NEXT:    br label [[RETURN:%.*]]
-// CHECK:       if.end:
-// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
-// CHECK-NEXT:    br label [[RETURN]]
-// CHECK:       return:
 // CHECK-NEXT:    ret void
 //
-// CHECK-EH-03-LABEL: @_Z5test3b(
-// CHECK-EH-03-NEXT:  entry:
-// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
-// CHECK-EH-03:       if.then:
-// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
-// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
-// CHECK-EH-03:       if.end:
-// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
-// CHECK-EH-03:       invoke.cont:
-// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[RETURN]]
-// CHECK-EH-03:       lpad:
-// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
-// CHECK-EH-03:       invoke.cont1:
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
-// CHECK-EH-03:       return:
-// CHECK-EH-03-NEXT:    ret void
-// CHECK-EH-03:       terminate.lpad:
-// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    catch i8* null
-// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
-// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
-// CHECK-EH-03-NEXT:    unreachable
-//
-// CHECK-EH-11-LABEL: @_Z5test3b(
-// CHECK-EH-11-NEXT:  entry:
-// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
-// CHECK-EH-11:       if.then:
-// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
-// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
-// CHECK-EH-11:       if.end:
-// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
-// CHECK-EH-11:       invoke.cont:
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[RETURN]]
-// CHECK-EH-11:       lpad:
-// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
-// CHECK-EH-11:       return:
-// CHECK-EH-11-NEXT:    ret void
+// CHECK-EH-LABEL: @_Z5test3b(
+// CHECK-EH-NEXT:  entry:
+// CHECK-EH-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-NEXT:    ret void
 //
 X test3(bool B) { // http://wg21.link/p2025r2#ex-4
   if (B) {
@@ -249,7 +181,7 @@
     return y; // NRVO happens
   }
   X x;
-  return x; // FIXME: NRVO could happen, but doesn't
+  return x; // NRVO happens
 }
 
 extern "C" void exit(int) throw();
@@ -745,93 +677,24 @@
 
 // CHECK-LABEL: @_Z6test13b(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
-// CHECK:       if.then:
 // CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
-// CHECK-NEXT:    br label [[RETURN:%.*]]
-// CHECK:       if.end:
-// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
-// CHECK-NEXT:    br label [[RETURN]]
-// CHECK:       return:
 // CHECK-NEXT:    ret void
 //
-// CHECK-EH-03-LABEL: @_Z6test13b(
-// CHECK-EH-03-NEXT:  entry:
-// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
-// CHECK-EH-03:       if.then:
-// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
-// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
-// CHECK-EH-03:       if.end:
-// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
-// CHECK-EH-03:       invoke.cont:
-// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[RETURN]]
-// CHECK-EH-03:       lpad:
-// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
-// CHECK-EH-03:       invoke.cont1:
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
-// CHECK-EH-03:       return:
-// CHECK-EH-03-NEXT:    ret void
-// CHECK-EH-03:       terminate.lpad:
-// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    catch i8* null
-// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
-// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
-// CHECK-EH-03-NEXT:    unreachable
-//
-// CHECK-EH-11-LABEL: @_Z6test13b(
-// CHECK-EH-11-NEXT:  entry:
-// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
-// CHECK-EH-11:       if.then:
-// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
-// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
-// CHECK-EH-11:       if.end:
-// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
-// CHECK-EH-11:       invoke.cont:
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[RETURN]]
-// CHECK-EH-11:       lpad:
-// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
-// CHECK-EH-11:       return:
-// CHECK-EH-11-NEXT:    ret void
+// CHECK-EH-LABEL: @_Z6test13b(
+// CHECK-EH-NEXT:  entry:
+// CHECK-EH-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-NEXT:    ret void
 //
 X test13(bool b) { // http://wg21.link/p2025r2#ex-7
   if (b)
     return X();
   X x;
-  return x; // FIXME: NRVO could happen, but doesn't
+  return x; // NRVO happens
 }
 
 // CHECK-LABEL: @_Z6test14b(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
 // CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
 // CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
@@ -840,12 +703,7 @@
 // CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
 // CHECK-NEXT:    br label [[CLEANUP:%.*]]
 // CHECK:       if.end:
-// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
 // CHECK-NEXT:    br label [[CLEANUP]]
 // CHECK:       cleanup:
 // CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
@@ -855,7 +713,6 @@
 // CHECK-EH-03-LABEL: @_Z6test14b(
 // CHECK-EH-03-NEXT:  entry:
 // CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
 // CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
@@ -866,56 +723,28 @@
 // CHECK-EH-03:       lpad:
 // CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
 // CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7:%.*]]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
 // CHECK-EH-03:       if.end:
-// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]]
-// CHECK-EH-03:       invoke.cont2:
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
-// CHECK-EH-03:       invoke.cont4:
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT5:%.*]] unwind label [[LPAD1]]
-// CHECK-EH-03:       lpad1:
-// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    br label [[EHCLEANUP:%.*]]
-// CHECK-EH-03:       lpad3:
-// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[EHCLEANUP]] unwind label [[TERMINATE_LPAD:%.*]]
-// CHECK-EH-03:       invoke.cont5:
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
-// CHECK-EH-03:       ehcleanup:
-// CHECK-EH-03-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[LPAD1]] ], [ [[TMP4]], [[LPAD3]] ]
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7]]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
 // CHECK-EH-03:       cleanup:
 // CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
 // CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-03-NEXT:    ret void
-// CHECK-EH-03:       ehcleanup7:
-// CHECK-EH-03-NEXT:    [[DOTPN13:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT8:%.*]] unwind label [[TERMINATE_LPAD]]
-// CHECK-EH-03:       invoke.cont8:
+// CHECK-EH-03:       invoke.cont3:
 // CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[DOTPN13]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
 // CHECK-EH-03:       terminate.lpad:
-// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
 // CHECK-EH-03-NEXT:    catch i8* null
-// CHECK-EH-03-NEXT:    [[TMP6:%.*]] = extractvalue { i8*, i32 } [[TMP5]], 0
-// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP6]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
 // CHECK-EH-03-NEXT:    unreachable
 //
 // CHECK-EH-11-LABEL: @_Z6test14b(
 // CHECK-EH-11-NEXT:  entry:
 // CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
 // CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
@@ -926,54 +755,28 @@
 // CHECK-EH-11:       lpad:
 // CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
 // CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5:%.*]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
 // CHECK-EH-11:       if.end:
-// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]]
-// CHECK-EH-11:       invoke.cont2:
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
-// CHECK-EH-11:       invoke.cont4:
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
-// CHECK-EH-11:       lpad1:
-// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP:%.*]]
-// CHECK-EH-11:       lpad3:
-// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP]]
-// CHECK-EH-11:       ehcleanup:
-// CHECK-EH-11-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP4]], [[LPAD3]] ], [ [[TMP3]], [[LPAD1]] ]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5]]
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
 // CHECK-EH-11:       cleanup:
 // CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
 // CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-11-NEXT:    ret void
-// CHECK-EH-11:       ehcleanup5:
-// CHECK-EH-11-NEXT:    [[DOTPN10:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN10]]
 //
 X test14(bool b) { // http://wg21.link/p2025r2#ex-8
   X x;
   if (b)
     return x;
   X y;
-  return y; // FIXME: NRVO could happen, but doesn't
+  return y; // NRVO happens
 }
 
 // CHECK-LABEL: @_Z6test15b(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
 // CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
 // CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
@@ -982,12 +785,7 @@
 // CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
 // CHECK-NEXT:    br label [[CLEANUP:%.*]]
 // CHECK:       if.end:
-// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
 // CHECK-NEXT:    br label [[CLEANUP]]
 // CHECK:       cleanup:
 // CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
@@ -997,7 +795,6 @@
 // CHECK-EH-03-LABEL: @_Z6test15b(
 // CHECK-EH-03-NEXT:  entry:
 // CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
 // CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
@@ -1008,56 +805,28 @@
 // CHECK-EH-03:       lpad:
 // CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
 // CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7:%.*]]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
 // CHECK-EH-03:       if.end:
-// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]]
-// CHECK-EH-03:       invoke.cont2:
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
-// CHECK-EH-03:       invoke.cont4:
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT5:%.*]] unwind label [[LPAD1]]
-// CHECK-EH-03:       lpad1:
-// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    br label [[EHCLEANUP:%.*]]
-// CHECK-EH-03:       lpad3:
-// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[EHCLEANUP]] unwind label [[TERMINATE_LPAD:%.*]]
-// CHECK-EH-03:       invoke.cont5:
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
-// CHECK-EH-03:       ehcleanup:
-// CHECK-EH-03-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[LPAD1]] ], [ [[TMP4]], [[LPAD3]] ]
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7]]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
 // CHECK-EH-03:       cleanup:
 // CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
 // CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-03-NEXT:    ret void
-// CHECK-EH-03:       ehcleanup7:
-// CHECK-EH-03-NEXT:    [[DOTPN13:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT8:%.*]] unwind label [[TERMINATE_LPAD]]
-// CHECK-EH-03:       invoke.cont8:
+// CHECK-EH-03:       invoke.cont3:
 // CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[DOTPN13]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
 // CHECK-EH-03:       terminate.lpad:
-// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
 // CHECK-EH-03-NEXT:    catch i8* null
-// CHECK-EH-03-NEXT:    [[TMP6:%.*]] = extractvalue { i8*, i32 } [[TMP5]], 0
-// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP6]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
 // CHECK-EH-03-NEXT:    unreachable
 //
 // CHECK-EH-11-LABEL: @_Z6test15b(
 // CHECK-EH-11-NEXT:  entry:
 // CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
 // CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
@@ -1068,48 +837,23 @@
 // CHECK-EH-11:       lpad:
 // CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
 // CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5:%.*]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
 // CHECK-EH-11:       if.end:
-// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]]
-// CHECK-EH-11:       invoke.cont2:
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
-// CHECK-EH-11:       invoke.cont4:
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
-// CHECK-EH-11:       lpad1:
-// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP:%.*]]
-// CHECK-EH-11:       lpad3:
-// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP]]
-// CHECK-EH-11:       ehcleanup:
-// CHECK-EH-11-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP4]], [[LPAD3]] ], [ [[TMP3]], [[LPAD1]] ]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5]]
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
 // CHECK-EH-11:       cleanup:
 // CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
 // CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
 // CHECK-EH-11-NEXT:    ret void
-// CHECK-EH-11:       ehcleanup5:
-// CHECK-EH-11-NEXT:    [[DOTPN10:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN10]]
 //
 X test15(bool b) { // http://wg21.link/p2025r2#ex-15
   X x;
   if (b)
     return (x);
   X y;
-  return ((y)); // FIXME: NRVO could happen, but doesn't
+  return ((y)); // NRVO happens
 }
 
 #ifdef CXX11
@@ -1337,151 +1081,54 @@
 
 // CHECK-LABEL: @_Z6test18i(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-NEXT:    [[Z:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
 // CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0
 // CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[NRVO_UNUSED:%.*]]
 // CHECK:       nrvo.unused:
 // CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
-// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I]], 1
-// CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[CLEANUP_CONT7_CRITEDGE:%.*]]
-// CHECK:       if.then2:
-// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
-// CHECK-NEXT:    br label [[RETURN]]
-// CHECK:       cleanup.cont7.critedge:
-// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
-// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Z]], i32 0, i32 0
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR5]]
-// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[I]], 1
+// CHECK-NEXT:    br i1 [[CMP2]], label [[RETURN]], label [[NRVO_UNUSED7:%.*]]
+// CHECK:       nrvo.unused7:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
 // CHECK-NEXT:    br label [[RETURN]]
 // CHECK:       return:
 // CHECK-NEXT:    ret void
 //
 // CHECK-EH-03-LABEL: @_Z6test18i(
 // CHECK-EH-03-NEXT:  entry:
-// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-03-NEXT:    [[Z:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
 // CHECK-EH-03-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0
 // CHECK-EH-03-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[NRVO_UNUSED:%.*]]
 // CHECK-EH-03:       nrvo.unused:
 // CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
-// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I]], 1
-// CHECK-EH-03-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[CLEANUP_CONT8_CRITEDGE:%.*]]
-// CHECK-EH-03:       if.then2:
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[CLEANUP4:%.*]] unwind label [[LPAD:%.*]]
-// CHECK-EH-03:       lpad:
-// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT5:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
-// CHECK-EH-03:       cleanup4:
-// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br i1 [[CMP1]], label [[RETURN]], label [[CLEANUP_CONT8:%.*]]
-// CHECK-EH-03:       cleanup.cont8.critedge:
-// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[CLEANUP_CONT8]]
-// CHECK-EH-03:       cleanup.cont8:
-// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Z]], i32 0, i32 0
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT10:%.*]] unwind label [[LPAD9:%.*]]
-// CHECK-EH-03:       invoke.cont10:
-// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-03-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[I]], 1
+// CHECK-EH-03-NEXT:    br i1 [[CMP2]], label [[RETURN]], label [[NRVO_UNUSED7:%.*]]
+// CHECK-EH-03:       nrvo.unused7:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
 // CHECK-EH-03-NEXT:    br label [[RETURN]]
-// CHECK-EH-03:       invoke.cont5:
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
-// CHECK-EH-03:       lpad9:
-// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    cleanup
-// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
-// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT12:%.*]] unwind label [[TERMINATE_LPAD]]
-// CHECK-EH-03:       invoke.cont12:
-// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-03-NEXT:    br label [[EH_RESUME]]
 // CHECK-EH-03:       return:
 // CHECK-EH-03-NEXT:    ret void
-// CHECK-EH-03:       eh.resume:
-// CHECK-EH-03-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[INVOKE_CONT12]] ], [ [[TMP1]], [[INVOKE_CONT5]] ]
-// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[DOTPN]]
-// CHECK-EH-03:       terminate.lpad:
-// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-03-NEXT:    catch i8* null
-// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { i8*, i32 } [[TMP4]], 0
-// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP5]]) #[[ATTR8]]
-// CHECK-EH-03-NEXT:    unreachable
 //
 // CHECK-EH-11-LABEL: @_Z6test18i(
 // CHECK-EH-11-NEXT:  entry:
-// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
-// CHECK-EH-11-NEXT:    [[Z:%.*]] = alloca [[CLASS_X]], align 1
 // CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
 // CHECK-EH-11-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0
 // CHECK-EH-11-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[NRVO_UNUSED:%.*]]
 // CHECK-EH-11:       nrvo.unused:
 // CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-11-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I]], 1
-// CHECK-EH-11-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[CLEANUP_CONT7_CRITEDGE:%.*]]
-// CHECK-EH-11:       if.then2:
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
-// CHECK-EH-11-NEXT:    to label [[CLEANUP4:%.*]] unwind label [[LPAD:%.*]]
-// CHECK-EH-11:       lpad:
-// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
-// CHECK-EH-11:       cleanup4:
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br i1 [[CMP1]], label [[RETURN]], label [[CLEANUP_CONT7:%.*]]
-// CHECK-EH-11:       cleanup.cont7.critedge:
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[CLEANUP_CONT7]]
-// CHECK-EH-11:       cleanup.cont7:
-// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Z]], i32 0, i32 0
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
-// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
-// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT9:%.*]] unwind label [[LPAD8:%.*]]
-// CHECK-EH-11:       invoke.cont9:
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-11-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[I]], 1
+// CHECK-EH-11-NEXT:    br i1 [[CMP2]], label [[RETURN]], label [[NRVO_UNUSED7:%.*]]
+// CHECK-EH-11:       nrvo.unused7:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
 // CHECK-EH-11-NEXT:    br label [[RETURN]]
-// CHECK-EH-11:       lpad8:
-// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
-// CHECK-EH-11-NEXT:    cleanup
-// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
-// CHECK-EH-11-NEXT:    br label [[EH_RESUME]]
 // CHECK-EH-11:       return:
 // CHECK-EH-11-NEXT:    ret void
-// CHECK-EH-11:       eh.resume:
-// CHECK-EH-11-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[LPAD8]] ], [ [[TMP1]], [[LPAD]] ]
-// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN]]
 //
 X test18(int i) { // http://wg21.link/p2025r2#ex-11
   {
@@ -1492,10 +1139,10 @@
     }
     X y;
     if (i == 1)
-      return y; // FIXME: NRVO could happen, but doesn't
+      return y; // NRVO happens
   }
   X z;
-  return z; // FIXME: NRVO could happen, but doesn't
+  return z; // NRVO happens
 }
 
 #ifdef CXX11
Index: clang/lib/Sema/Scope.cpp
===================================================================
--- clang/lib/Sema/Scope.cpp
+++ clang/lib/Sema/Scope.cpp
@@ -194,7 +194,7 @@
     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
 
   if (NRVO.getInt())
-    OS << "NRVO not allowed\n";
-  else if (NRVO.getPointer())
+    OS << "Invalidates NRVO candidates in parent\n";
+  if (NRVO.getPointer())
     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
 }
Index: clang/include/clang/Sema/Scope.h
===================================================================
--- clang/include/clang/Sema/Scope.h
+++ clang/include/clang/Sema/Scope.h
@@ -199,6 +199,14 @@
   using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>;
   DeclSetTy DeclsInScope;
 
+  /// NRVOCandidatesInScope - This keeps track of all unspoiled NRVO candidates
+  /// in this scope. When a VarDecl is added to the scope, it is added to
+  /// NRVOCandidatesInScope.  When `addNRVOCandidate` is called, all variables
+  /// except the actual candidate are removed from the set.  The set is used
+  /// to calculate the `NRVO` variable.
+  using NRVOCandidatesSetTy = llvm::SmallPtrSet<VarDecl *, 32>;
+  NRVOCandidatesSetTy NRVOCandidatesInScope;
+
   /// The DeclContext with which this scope is associated. For
   /// example, the entity of a class scope is the class itself, the
   /// entity of a function scope is a function, etc.
@@ -210,7 +218,7 @@
   /// Used to determine if errors occurred in this scope.
   DiagnosticErrorTrap ErrorTrap;
 
-  /// A lattice consisting of undefined, a single NRVO candidate variable in
+  /// A lattice consisting of undefined, the single NRVO candidate variable in
   /// this scope, or over-defined. The bit is true when over-defined.
   llvm::PointerIntPair<VarDecl *, 1, bool> NRVO;
 
@@ -305,6 +313,8 @@
 
   void AddDecl(Decl *D) {
     DeclsInScope.insert(D);
+    if (VarDecl *VD = dyn_cast<VarDecl>(D))
+      NRVOCandidatesInScope.insert(VD);
   }
 
   void RemoveDecl(Decl *D) {
@@ -506,18 +516,28 @@
   }
 
   void addNRVOCandidate(VarDecl *VD) {
-    if (NRVO.getInt())
-      return;
-    if (NRVO.getPointer() == nullptr) {
-      NRVO.setPointer(VD);
-      return;
-    }
-    if (NRVO.getPointer() != VD)
-      setNoNRVO();
+    // every candidate except VD is "spoiled" now, remove them from the set
+    bool HasCandidate = NRVOCandidatesInScope.contains(VD);
+    NRVOCandidatesInScope.clear();
+    if (HasCandidate)
+      NRVOCandidatesInScope.insert(VD);
+
+    // the variable may have NRVO if it's an existing candidate or an outer
+    // variable
+    VarDecl *NewNRVO = nullptr;
+    if (HasCandidate || !isDeclScope(VD))
+      NewNRVO = VD;
+
+    // if we changed the candidate, the NRVO for the parent scope is
+    // over-defined
+    if (NRVO.getPointer() != nullptr && NRVO.getPointer() != NewNRVO)
+      NRVO.setInt(true);
+    NRVO.setPointer(NewNRVO);
   }
 
   void setNoNRVO() {
     NRVO.setInt(true);
+    NRVOCandidatesInScope.clear();
     NRVO.setPointer(nullptr);
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to