@@ -476,6 +476,76 @@ ExpandPeerMacroRequest::evaluate(Evaluator &evaluator, Decl *decl) const {
476476 return decl->getASTContext ().AllocateCopy (bufferIDs);
477477}
478478
479+ // / Diagnose macro expansions that produce any of the following declarations:
480+ // / - Import declarations
481+ // / - Operator and precedence group declarations
482+ // / - Macro declarations
483+ // / - Extensions
484+ // / - Types with `@main` attributes
485+ // / - Top-level default literal type overrides
486+ // / - Value decls with names not covered by the macro declaration.
487+ static void validateMacroExpansion (SourceFile *expansionBuffer,
488+ MacroDecl *macro,
489+ ValueDecl *attachedTo,
490+ MacroRole role) {
491+ // Gather macro-introduced names
492+ llvm::SmallVector<DeclName, 2 > introducedNames;
493+ macro->getIntroducedNames (role, attachedTo, introducedNames);
494+
495+ llvm::SmallDenseSet<DeclName, 2 > coversName (introducedNames.begin (),
496+ introducedNames.end ());
497+
498+ for (auto *decl : expansionBuffer->getTopLevelDecls ()) {
499+ auto &ctx = decl->getASTContext ();
500+
501+ // Certain macro roles can generate special declarations.
502+ if ((isa<AccessorDecl>(decl) && role == MacroRole::Accessor) ||
503+ (isa<ExtensionDecl>(decl) && role == MacroRole::Conformance)) {
504+ continue ;
505+ }
506+
507+ // Diagnose invalid declaration kinds.
508+ if (isa<ImportDecl>(decl) ||
509+ isa<OperatorDecl>(decl) ||
510+ isa<PrecedenceGroupDecl>(decl) ||
511+ isa<MacroDecl>(decl) ||
512+ isa<ExtensionDecl>(decl)) {
513+ decl->diagnose (diag::invalid_decl_in_macro_expansion,
514+ decl->getDescriptiveKind ());
515+ }
516+
517+ // Diagnose `@main` types.
518+ if (auto *typeDecl = dyn_cast<TypeDecl>(decl)) {
519+ if (typeDecl->getAttrs ().hasAttribute <MainTypeAttr>()) {
520+ typeDecl->diagnose (diag::invalid_main_type_in_macro_expansion);
521+ }
522+ }
523+
524+ // Diagnose default literal type overrides.
525+ if (auto *typeAlias = dyn_cast<TypeAliasDecl>(decl)) {
526+ // TODO
527+ }
528+
529+ // Diagnose value decls with names not covered by the macro
530+ if (auto *value = dyn_cast<ValueDecl>(decl)) {
531+ auto baseName = value->getBaseName ();
532+ if (baseName.isSpecial ()) {
533+ baseName = ctx.getIdentifier (baseName.userFacingName ());
534+ }
535+
536+ // $-prefixed names are unique names. These are always allowed.
537+ if (baseName.getIdentifier ().hasDollarPrefix ()) {
538+ continue ;
539+ }
540+
541+ if (!coversName.count (baseName)) {
542+ value->diagnose (diag::invalid_macro_introduced_name,
543+ baseName, macro->getBaseName ());
544+ }
545+ }
546+ }
547+ }
548+
479549// / Determine whether the given source file is from an expansion of the given
480550// / macro.
481551static bool isFromExpansionOfMacro (SourceFile *sourceFile, MacroDecl *macro,
@@ -1102,6 +1172,8 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
11021172 /* parsingOpts=*/ {}, /* isPrimary=*/ false );
11031173 macroSourceFile->setImports (declSourceFile->getImports ());
11041174
1175+ validateMacroExpansion (macroSourceFile, macro,
1176+ dyn_cast<ValueDecl>(attachedTo), role);
11051177 return macroSourceFile;
11061178}
11071179
0 commit comments