@@ -1096,6 +1096,154 @@ void CIRGenFunction::emitAnyExprToMem(const Expr *e, Address location,
10961096 llvm_unreachable (" bad evaluation kind" );
10971097}
10981098
1099+ static Address createReferenceTemporary (CIRGenFunction &cgf,
1100+ const MaterializeTemporaryExpr *m,
1101+ const Expr *inner) {
1102+ // TODO(cir): cgf.getTargetHooks();
1103+ switch (m->getStorageDuration ()) {
1104+ case SD_FullExpression:
1105+ case SD_Automatic: {
1106+ QualType ty = inner->getType ();
1107+
1108+ assert (!cir::MissingFeatures::mergeAllConstants ());
1109+
1110+ // The temporary memory should be created in the same scope as the extending
1111+ // declaration of the temporary materialization expression.
1112+ cir::AllocaOp extDeclAlloca;
1113+ if (const clang::ValueDecl *extDecl = m->getExtendingDecl ()) {
1114+ auto extDeclAddrIter = cgf.localDeclMap .find (extDecl);
1115+ if (extDeclAddrIter != cgf.localDeclMap .end ()) {
1116+ extDeclAlloca = mlir::dyn_cast_if_present<cir::AllocaOp>(
1117+ extDeclAddrIter->second .getDefiningOp ());
1118+ }
1119+ }
1120+ mlir::OpBuilder::InsertPoint ip;
1121+ if (extDeclAlloca)
1122+ ip = {extDeclAlloca->getBlock (), extDeclAlloca->getIterator ()};
1123+ return cgf.createMemTemp (ty, cgf.getLoc (m->getSourceRange ()),
1124+ cgf.getCounterRefTmpAsString (), /* alloca=*/ nullptr ,
1125+ ip);
1126+ }
1127+ case SD_Thread:
1128+ case SD_Static: {
1129+ cgf.cgm .errorNYI (
1130+ m->getSourceRange (),
1131+ " createReferenceTemporary: static/thread storage duration" );
1132+ return Address::invalid ();
1133+ }
1134+
1135+ case SD_Dynamic:
1136+ llvm_unreachable (" temporary can't have dynamic storage duration" );
1137+ }
1138+ llvm_unreachable (" unknown storage duration" );
1139+ }
1140+
1141+ static void pushTemporaryCleanup (CIRGenFunction &cgf,
1142+ const MaterializeTemporaryExpr *m,
1143+ const Expr *e, Address referenceTemporary) {
1144+ // Objective-C++ ARC:
1145+ // If we are binding a reference to a temporary that has ownership, we
1146+ // need to perform retain/release operations on the temporary.
1147+ //
1148+ // FIXME(ogcg): This should be looking at e, not m.
1149+ if (m->getType ().getObjCLifetime ()) {
1150+ cgf.cgm .errorNYI (e->getSourceRange (), " pushTemporaryCleanup: ObjCLifetime" );
1151+ return ;
1152+ }
1153+
1154+ clang::CXXDestructorDecl *referenceTemporaryDtor = nullptr ;
1155+ if (const clang::RecordType *rt = e->getType ()
1156+ ->getBaseElementTypeUnsafe ()
1157+ ->getAs <clang::RecordType>()) {
1158+ // Get the destructor for the reference temporary.
1159+ auto *classDecl = cast<clang::CXXRecordDecl>(rt->getDecl ());
1160+ if (!classDecl->hasTrivialDestructor ())
1161+ referenceTemporaryDtor = classDecl->getDestructor ();
1162+ }
1163+
1164+ if (!referenceTemporaryDtor)
1165+ return ;
1166+
1167+ // Call the destructor for the temporary.
1168+ switch (m->getStorageDuration ()) {
1169+ case SD_Static:
1170+ case SD_Thread:
1171+ cgf.cgm .errorNYI (e->getSourceRange (),
1172+ " pushTemporaryCleanup: static/thread storage duration" );
1173+ return ;
1174+
1175+ case SD_FullExpression:
1176+ cgf.pushDestroy (NormalAndEHCleanup, referenceTemporary, e->getType (),
1177+ CIRGenFunction::destroyCXXObject);
1178+ break ;
1179+
1180+ case SD_Automatic:
1181+ cgf.cgm .errorNYI (e->getSourceRange (),
1182+ " pushTemporaryCleanup: automatic storage duration" );
1183+ break ;
1184+
1185+ case SD_Dynamic:
1186+ llvm_unreachable (" temporary cannot have dynamic storage duration" );
1187+ }
1188+ }
1189+
1190+ LValue CIRGenFunction::emitMaterializeTemporaryExpr (
1191+ const MaterializeTemporaryExpr *m) {
1192+ const Expr *e = m->getSubExpr ();
1193+
1194+ assert ((!m->getExtendingDecl () || !isa<VarDecl>(m->getExtendingDecl ()) ||
1195+ !cast<VarDecl>(m->getExtendingDecl ())->isARCPseudoStrong ()) &&
1196+ " Reference should never be pseudo-strong!" );
1197+
1198+ // FIXME: ideally this would use emitAnyExprToMem, however, we cannot do so
1199+ // as that will cause the lifetime adjustment to be lost for ARC
1200+ auto ownership = m->getType ().getObjCLifetime ();
1201+ if (ownership != Qualifiers::OCL_None &&
1202+ ownership != Qualifiers::OCL_ExplicitNone) {
1203+ cgm.errorNYI (e->getSourceRange (),
1204+ " emitMaterializeTemporaryExpr: ObjCLifetime" );
1205+ return {};
1206+ }
1207+
1208+ SmallVector<const Expr *, 2 > commaLHSs;
1209+ SmallVector<SubobjectAdjustment, 2 > adjustments;
1210+ e = e->skipRValueSubobjectAdjustments (commaLHSs, adjustments);
1211+
1212+ for (const Expr *ignored : commaLHSs)
1213+ emitIgnoredExpr (ignored);
1214+
1215+ if (isa<OpaqueValueExpr>(e)) {
1216+ cgm.errorNYI (e->getSourceRange (),
1217+ " emitMaterializeTemporaryExpr: OpaqueValueExpr" );
1218+ return {};
1219+ }
1220+
1221+ // Create and initialize the reference temporary.
1222+ Address object = createReferenceTemporary (*this , m, e);
1223+
1224+ if (auto var =
1225+ mlir::dyn_cast<cir::GlobalOp>(object.getPointer ().getDefiningOp ())) {
1226+ // TODO(cir): add something akin to stripPointerCasts() to ptr above
1227+ cgm.errorNYI (e->getSourceRange (), " emitMaterializeTemporaryExpr: GlobalOp" );
1228+ return {};
1229+ } else {
1230+ assert (!cir::MissingFeatures::emitLifetimeMarkers ());
1231+ emitAnyExprToMem (e, object, Qualifiers (), /* isInitializer=*/ true );
1232+ }
1233+ pushTemporaryCleanup (*this , m, e, object);
1234+
1235+ // Perform derived-to-base casts and/or field accesses, to get from the
1236+ // temporary object we created (and, potentially, for which we extended
1237+ // the lifetime) to the subobject we're binding the reference to.
1238+ if (!adjustments.empty ()) {
1239+ cgm.errorNYI (e->getSourceRange (),
1240+ " emitMaterializeTemporaryExpr: Adjustments" );
1241+ return {};
1242+ }
1243+
1244+ return makeAddrLValue (object, m->getType (), AlignmentSource::Decl);
1245+ }
1246+
10991247LValue CIRGenFunction::emitCompoundLiteralLValue (const CompoundLiteralExpr *e) {
11001248 if (e->isFileScope ()) {
11011249 cgm.errorNYI (e->getSourceRange (), " emitCompoundLiteralLValue: FileScope" );
0 commit comments