@@ -338,6 +338,31 @@ bool ExpandMemberAttributeMacros::evaluate(Evaluator &evaluator,
338
338
return addedAttributes;
339
339
}
340
340
341
+ bool ExpandSynthesizedMemberMacroRequest::evaluate (Evaluator &evaluator,
342
+ Decl *decl) const {
343
+ auto &ctx = decl->getASTContext ();
344
+ auto *dc = decl->getInnermostDeclContext ();
345
+ bool synthesizedMembers = false ;
346
+
347
+ for (auto customAttrConst : decl->getSemanticAttrs ().getAttributes <CustomAttr>()) {
348
+ auto customAttr = const_cast <CustomAttr *>(customAttrConst);
349
+ auto *macroDecl = evaluateOrDefault (
350
+ ctx.evaluator ,
351
+ ResolveAttachedMacroRequest{customAttr, dc},
352
+ nullptr );
353
+
354
+ if (!macroDecl)
355
+ continue ;
356
+
357
+ if (!macroDecl->getMacroRoles ().contains (MacroRole::SynthesizedMembers))
358
+ continue ;
359
+
360
+ // Expand the synthesized members.
361
+ synthesizedMembers |= expandSynthesizedMembers (customAttr, macroDecl, decl);
362
+ }
363
+
364
+ return synthesizedMembers;
365
+ }
341
366
342
367
// / Determine whether the given source file is from an expansion of the given
343
368
// / macro.
@@ -1082,6 +1107,181 @@ bool swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member) {
1082
1107
return addedAttributes;
1083
1108
}
1084
1109
1110
+ bool swift::expandSynthesizedMembers (CustomAttr *attr, MacroDecl *macro,
1111
+ Decl *decl) {
1112
+ auto *dc = decl->getInnermostDeclContext ();
1113
+ ASTContext &ctx = dc->getASTContext ();
1114
+ SourceManager &sourceMgr = ctx.SourceMgr ;
1115
+ auto moduleDecl = dc->getParentModule ();
1116
+
1117
+ auto attrSourceFile =
1118
+ moduleDecl->getSourceFileContainingLocation (attr->AtLoc );
1119
+ if (!attrSourceFile)
1120
+ return false ;
1121
+
1122
+ auto declSourceFile =
1123
+ moduleDecl->getSourceFileContainingLocation (decl->getStartLoc ());
1124
+ if (!declSourceFile)
1125
+ return false ;
1126
+
1127
+ // Evaluate the macro.
1128
+ NullTerminatedStringRef evaluatedSource;
1129
+
1130
+ if (isFromExpansionOfMacro (attrSourceFile, macro) ||
1131
+ isFromExpansionOfMacro (declSourceFile, macro)) {
1132
+ decl->diagnose (diag::macro_recursive, macro->getName ());
1133
+ return false ;
1134
+ }
1135
+
1136
+ auto macroDef = macro->getDefinition ();
1137
+ switch (macroDef.kind ) {
1138
+ case MacroDefinition::Kind::Undefined:
1139
+ case MacroDefinition::Kind::Invalid:
1140
+ // Already diagnosed as an error elsewhere.
1141
+ return false ;
1142
+
1143
+ case MacroDefinition::Kind::Builtin: {
1144
+ switch (macroDef.getBuiltinKind ()) {
1145
+ case BuiltinMacroKind::ExternalMacro:
1146
+ // FIXME: Error here.
1147
+ return false ;
1148
+ }
1149
+ }
1150
+
1151
+ case MacroDefinition::Kind::External: {
1152
+ // Retrieve the external definition of the macro.
1153
+ auto external = macroDef.getExternalMacro ();
1154
+ ExternalMacroDefinitionRequest request{
1155
+ &ctx, external.moduleName , external.macroTypeName
1156
+ };
1157
+ auto externalDef = evaluateOrDefault (
1158
+ ctx.evaluator , request, ExternalMacroDefinition ()
1159
+ );
1160
+ if (!externalDef.opaqueHandle ) {
1161
+ decl->diagnose (diag::external_macro_not_found,
1162
+ external.moduleName .str (),
1163
+ external.macroTypeName .str (),
1164
+ macro->getName ()
1165
+ );
1166
+ macro->diagnose (diag::decl_declared_here, macro->getName ());
1167
+ return false ;
1168
+ }
1169
+
1170
+ // Make sure macros are enabled before we expand.
1171
+ if (!ctx.LangOpts .hasFeature (Feature::Macros)) {
1172
+ decl->diagnose (diag::macro_experimental);
1173
+ return false ;
1174
+ }
1175
+
1176
+ #if SWIFT_SWIFT_PARSER
1177
+ PrettyStackTraceDecl debugStack (" expanding attribute macro" , decl);
1178
+
1179
+ auto astGenAttrSourceFile = attrSourceFile->exportedSourceFile ;
1180
+ if (!astGenAttrSourceFile)
1181
+ return false ;
1182
+
1183
+ auto astGenDeclSourceFile = declSourceFile->exportedSourceFile ;
1184
+ if (!astGenDeclSourceFile)
1185
+ return false ;
1186
+
1187
+ const char *evaluatedSourceAddress;
1188
+ ptrdiff_t evaluatedSourceLength;
1189
+ swift_ASTGen_expandAttachedMacro (
1190
+ &ctx.Diags ,
1191
+ externalDef.opaqueHandle ,
1192
+ astGenAttrSourceFile, attr->AtLoc .getOpaquePointerValue (),
1193
+ astGenDeclSourceFile, decl->getStartLoc ().getOpaquePointerValue (),
1194
+ /* parentDeclSourceFile*/ nullptr , /* parentDeclLoc*/ nullptr ,
1195
+ &evaluatedSourceAddress, &evaluatedSourceLength);
1196
+ if (!evaluatedSourceAddress)
1197
+ return false ;
1198
+ evaluatedSource = NullTerminatedStringRef (evaluatedSourceAddress,
1199
+ (size_t )evaluatedSourceLength);
1200
+ break ;
1201
+ #else
1202
+ decl->diagnose (diag::macro_unsupported);
1203
+ return false ;
1204
+ #endif
1205
+ }
1206
+ }
1207
+
1208
+ // Figure out a reasonable name for the macro expansion buffer.
1209
+ std::string bufferName;
1210
+ {
1211
+ llvm::raw_string_ostream out (bufferName);
1212
+
1213
+ out << " macro:"
1214
+ << " @" << macro->getName ().getBaseName ();
1215
+ if (auto bufferID = declSourceFile->getBufferID ()) {
1216
+ unsigned startLine, startColumn;
1217
+ std::tie (startLine, startColumn) =
1218
+ sourceMgr.getLineAndColumnInBuffer (decl->getStartLoc (), *bufferID);
1219
+
1220
+ SourceLoc endLoc =
1221
+ Lexer::getLocForEndOfToken (sourceMgr, decl->getEndLoc ());
1222
+ unsigned endLine, endColumn;
1223
+ std::tie (endLine, endColumn) =
1224
+ sourceMgr.getLineAndColumnInBuffer (endLoc, *bufferID);
1225
+
1226
+ out << " :" << sourceMgr.getIdentifierForBuffer (*bufferID) << " :"
1227
+ << startLine << " :" << startColumn
1228
+ << " -" << endLine << " :" << endColumn;
1229
+ }
1230
+ }
1231
+
1232
+ // Dump macro expansions to standard output, if requested.
1233
+ if (ctx.LangOpts .DumpMacroExpansions ) {
1234
+ llvm::errs () << bufferName
1235
+ << " \n ------------------------------\n "
1236
+ << evaluatedSource
1237
+ << " \n ------------------------------\n " ;
1238
+ }
1239
+
1240
+ // Create a new source buffer with the contents of the expanded macro.
1241
+ auto macroBuffer =
1242
+ llvm::MemoryBuffer::getMemBufferCopy (evaluatedSource, bufferName);
1243
+ unsigned macroBufferID = sourceMgr.addNewSourceBuffer (std::move (macroBuffer));
1244
+ auto macroBufferRange = sourceMgr.getRangeForBuffer (macroBufferID);
1245
+ GeneratedSourceInfo sourceInfo{
1246
+ GeneratedSourceInfo::SynthesizedMemberMacroExpansion,
1247
+ decl->getEndLoc (),
1248
+ SourceRange (macroBufferRange.getStart (), macroBufferRange.getEnd ()),
1249
+ ASTNode (decl).getOpaqueValue (),
1250
+ dc,
1251
+ attr
1252
+ };
1253
+ sourceMgr.setGeneratedSourceInfo (macroBufferID, sourceInfo);
1254
+ free ((void *)evaluatedSource.data ());
1255
+
1256
+ // Create a source file to hold the macro buffer. This is automatically
1257
+ // registered with the enclosing module.
1258
+ auto macroSourceFile = new (ctx) SourceFile (
1259
+ *dc->getParentModule (), SourceFileKind::MacroExpansion, macroBufferID,
1260
+ /* parsingOpts=*/ {}, /* isPrimary=*/ false );
1261
+ macroSourceFile->setImports (declSourceFile->getImports ());
1262
+
1263
+ PrettyStackTraceDecl debugStack (
1264
+ " type checking expanded declaration macro" , decl);
1265
+
1266
+ bool synthesizedMembers = false ;
1267
+ auto topLevelDecls = macroSourceFile->getTopLevelDecls ();
1268
+ for (auto member : topLevelDecls) {
1269
+ member->setDeclContext (decl->getInnermostDeclContext ());
1270
+ member->setImplicit ();
1271
+
1272
+ if (auto *nominal = dyn_cast<NominalTypeDecl>(decl)) {
1273
+ nominal->addMember (member);
1274
+ } else if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
1275
+ extension->addMember (member);
1276
+ }
1277
+
1278
+ TypeChecker::typeCheckDecl (member);
1279
+ synthesizedMembers = true ;
1280
+ }
1281
+
1282
+ return synthesizedMembers;
1283
+ }
1284
+
1085
1285
MacroDecl *
1086
1286
ResolveAttachedMacroRequest::evaluate (Evaluator &evaluator,
1087
1287
CustomAttr *attr,
0 commit comments