@@ -31,6 +31,8 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
3131    cgm.errorNYI (d.getSourceRange (), " emitAutoVarAlloca: address space"  );
3232
3333  mlir::Location loc = getLoc (d.getSourceRange ());
34+   bool  nrvo =
35+       getContext ().getLangOpts ().ElideConstructors  && d.isNRVOVariable ();
3436
3537  CIRGenFunction::AutoVarEmission emission (d);
3638  emission.IsEscapingByRef  = d.isEscapingByref ();
@@ -44,16 +46,37 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
4446  if  (ty->isVariablyModifiedType ())
4547    cgm.errorNYI (d.getSourceRange (), " emitAutoVarDecl: variably modified type"  );
4648
49+   assert (!cir::MissingFeatures::openMP ());
50+ 
4751  Address address = Address::invalid ();
4852  if  (!ty->isConstantSizeType ())
4953    cgm.errorNYI (d.getSourceRange (), " emitAutoVarDecl: non-constant size type"  );
5054
5155  //  A normal fixed sized variable becomes an alloca in the entry block,
52-   mlir::Type allocaTy = convertTypeForMem (ty);
53-   //  Create the temp alloca and declare variable using it.
54-   address = createTempAlloca (allocaTy, alignment, loc, d.getName (),
55-                              /* arraySize=*/ nullptr , /* alloca=*/ nullptr , ip);
56-   declare (address.getPointer (), &d, ty, getLoc (d.getSourceRange ()), alignment);
56+   //  unless:
57+   //  - it's an NRVO variable.
58+   //  - we are compiling OpenMP and it's an OpenMP local variable.
59+   if  (nrvo) {
60+     //  The named return value optimization: allocate this variable in the
61+     //  return slot, so that we can elide the copy when returning this
62+     //  variable (C++0x [class.copy]p34).
63+     address = returnValue;
64+ 
65+     if  (const  RecordDecl *rd = ty->getAsRecordDecl ()) {
66+       if  (const  auto  *cxxrd = dyn_cast<CXXRecordDecl>(rd);
67+           (cxxrd && !cxxrd->hasTrivialDestructor ()) ||
68+           rd->isNonTrivialToPrimitiveDestroy ())
69+         cgm.errorNYI (d.getSourceRange (), " emitAutoVarAlloca: set NRVO flag"  );
70+     }
71+   } else  {
72+     //  A normal fixed sized variable becomes an alloca in the entry block,
73+     mlir::Type allocaTy = convertTypeForMem (ty);
74+     //  Create the temp alloca and declare variable using it.
75+     address = createTempAlloca (allocaTy, alignment, loc, d.getName (),
76+                                /* arraySize=*/ nullptr , /* alloca=*/ nullptr , ip);
77+     declare (address.getPointer (), &d, ty, getLoc (d.getSourceRange ()),
78+             alignment);
79+   }
5780
5881  emission.Addr  = address;
5982  setAddrOfLocalVar (&d, address);
0 commit comments