@@ -42,6 +42,16 @@ extern "C" ptrdiff_t swift_ASTGen_evaluateMacro(
42
42
const void *sourceLocation,
43
43
const char **evaluatedSource, ptrdiff_t *evaluatedSourceLength);
44
44
45
+ extern " C" ptrdiff_t swift_ASTGen_expandAttachedMacro (
46
+ void *diagEngine, void *macro,
47
+ void *customAttrSourceFile,
48
+ const void *customAttrSourceLocation,
49
+ void *declarationSourceFile,
50
+ const void *declarationSourceLocation,
51
+ const char **evaluatedSource,
52
+ ptrdiff_t *evaluatedSourceLength
53
+ );
54
+
45
55
// / Produce the mangled name for the nominal type descriptor of a type
46
56
// / referenced by its module and type name.
47
57
static std::string mangledNameForTypeMetadataAccessor (
@@ -662,3 +672,193 @@ bool swift::expandFreestandingDeclarationMacro(
662
672
}
663
673
return true ;
664
674
}
675
+
676
+ void swift::expandAccessors (
677
+ AbstractStorageDecl *storage, CustomAttr *attr, MacroDecl *macro
678
+ ) {
679
+ auto *dc = storage->getInnermostDeclContext ();
680
+ ASTContext &ctx = dc->getASTContext ();
681
+ SourceManager &sourceMgr = ctx.SourceMgr ;
682
+
683
+ auto moduleDecl = dc->getParentModule ();
684
+
685
+ auto attrSourceFile =
686
+ moduleDecl->getSourceFileContainingLocation (attr->AtLoc );
687
+ if (!attrSourceFile)
688
+ return ;
689
+
690
+ auto declSourceFile =
691
+ moduleDecl->getSourceFileContainingLocation (storage->getStartLoc ());
692
+ if (!declSourceFile)
693
+ return ;
694
+
695
+ // Evaluate the macro.
696
+ NullTerminatedStringRef evaluatedSource;
697
+
698
+ if (isFromExpansionOfMacro (attrSourceFile, macro) ||
699
+ isFromExpansionOfMacro (declSourceFile, macro)) {
700
+ storage->diagnose (diag::macro_recursive, macro->getName ());
701
+ return ;
702
+ }
703
+
704
+ auto macroDef = macro->getDefinition ();
705
+ switch (macroDef.kind ) {
706
+ case MacroDefinition::Kind::Undefined:
707
+ case MacroDefinition::Kind::Invalid:
708
+ // Already diagnosed as an error elsewhere.
709
+ return ;
710
+
711
+ case MacroDefinition::Kind::Builtin: {
712
+ switch (macroDef.getBuiltinKind ()) {
713
+ case BuiltinMacroKind::ExternalMacro:
714
+ // FIXME: Error here.
715
+ return ;
716
+ }
717
+ }
718
+
719
+ case MacroDefinition::Kind::External: {
720
+ // Retrieve the external definition of the macro.
721
+ auto external = macroDef.getExternalMacro ();
722
+ ExternalMacroDefinitionRequest request{
723
+ &ctx, external.moduleName , external.macroTypeName
724
+ };
725
+ auto externalDef = evaluateOrDefault (
726
+ ctx.evaluator , request, ExternalMacroDefinition ()
727
+ );
728
+ if (!externalDef.opaqueHandle ) {
729
+ storage->diagnose (diag::external_macro_not_found,
730
+ external.moduleName .str (),
731
+ external.macroTypeName .str (),
732
+ macro->getName ()
733
+ );
734
+ macro->diagnose (diag::decl_declared_here, macro->getName ());
735
+ return ;
736
+ }
737
+
738
+ // Make sure macros are enabled before we expand.
739
+ if (!ctx.LangOpts .hasFeature (Feature::Macros)) {
740
+ storage->diagnose (diag::macro_experimental);
741
+ return ;
742
+ }
743
+
744
+ #if SWIFT_SWIFT_PARSER
745
+ PrettyStackTraceDecl debugStack (" expanding accessor macro" , storage);
746
+
747
+ auto astGenAttrSourceFile = attrSourceFile->exportedSourceFile ;
748
+ if (!astGenAttrSourceFile)
749
+ return ;
750
+
751
+ auto astGenDeclSourceFile = declSourceFile->exportedSourceFile ;
752
+ if (!astGenDeclSourceFile)
753
+ return ;
754
+
755
+ Decl *searchDecl = storage;
756
+ if (auto var = dyn_cast<VarDecl>(storage))
757
+ searchDecl = var->getParentPatternBinding ();
758
+
759
+ const char *evaluatedSourceAddress;
760
+ ptrdiff_t evaluatedSourceLength;
761
+ swift_ASTGen_expandAttachedMacro (
762
+ &ctx.Diags ,
763
+ externalDef.opaqueHandle ,
764
+ astGenAttrSourceFile, attr->AtLoc .getOpaquePointerValue (),
765
+ astGenDeclSourceFile, searchDecl->getStartLoc ().getOpaquePointerValue (),
766
+ &evaluatedSourceAddress, &evaluatedSourceLength);
767
+ if (!evaluatedSourceAddress)
768
+ return ;
769
+ evaluatedSource = NullTerminatedStringRef (evaluatedSourceAddress,
770
+ (size_t )evaluatedSourceLength);
771
+ break ;
772
+ #else
773
+ med->diagnose (diag::macro_unsupported);
774
+ return false ;
775
+ #endif
776
+ }
777
+ }
778
+
779
+ // Figure out a reasonable name for the macro expansion buffer.
780
+ std::string bufferName;
781
+ {
782
+ llvm::raw_string_ostream out (bufferName);
783
+
784
+ out << " macro:" << storage->getName ()
785
+ << " @" << macro->getName ().getBaseName ();
786
+ if (auto bufferID = declSourceFile->getBufferID ()) {
787
+ unsigned startLine, startColumn;
788
+ std::tie (startLine, startColumn) =
789
+ sourceMgr.getLineAndColumnInBuffer (storage->getStartLoc (), *bufferID);
790
+
791
+ SourceLoc endLoc =
792
+ Lexer::getLocForEndOfToken (sourceMgr, storage->getEndLoc ());
793
+ unsigned endLine, endColumn;
794
+ std::tie (endLine, endColumn) =
795
+ sourceMgr.getLineAndColumnInBuffer (endLoc, *bufferID);
796
+
797
+ out << " :" << sourceMgr.getIdentifierForBuffer (*bufferID) << " :"
798
+ << startLine << " :" << startColumn
799
+ << " -" << endLine << " :" << endColumn;
800
+ }
801
+ }
802
+
803
+ // Dump macro expansions to standard output, if requested.
804
+ if (ctx.LangOpts .DumpMacroExpansions ) {
805
+ llvm::errs () << bufferName
806
+ << " \n ------------------------------\n "
807
+ << evaluatedSource
808
+ << " \n ------------------------------\n " ;
809
+ }
810
+
811
+ // Create a new source buffer with the contents of the expanded macro.
812
+ auto macroBuffer =
813
+ llvm::MemoryBuffer::getMemBufferCopy (evaluatedSource, bufferName);
814
+ unsigned macroBufferID = sourceMgr.addNewSourceBuffer (std::move (macroBuffer));
815
+ auto macroBufferRange = sourceMgr.getRangeForBuffer (macroBufferID);
816
+ GeneratedSourceInfo sourceInfo{
817
+ GeneratedSourceInfo::MacroExpansion,
818
+ storage->getEndLoc (),
819
+ SourceRange (macroBufferRange.getStart (), macroBufferRange.getEnd ()),
820
+ ASTNode (storage).getOpaqueValue (),
821
+ dc,
822
+ attr
823
+ };
824
+ sourceMgr.setGeneratedSourceInfo (macroBufferID, sourceInfo);
825
+ free ((void *)evaluatedSource.data ());
826
+
827
+ // Create a source file to hold the macro buffer. This is automatically
828
+ // registered with the enclosing module.
829
+ auto macroSourceFile = new (ctx) SourceFile (
830
+ *dc->getParentModule (), SourceFileKind::MacroExpansion, macroBufferID,
831
+ /* parsingOpts=*/ {}, /* isPrimary=*/ false );
832
+
833
+ PrettyStackTraceDecl debugStack (
834
+ " type checking expanded declaration macro" , storage);
835
+
836
+ // FIXME: getTopLevelItems() is going to have to figure out how to parse
837
+ // a sequence of accessor declarations. Specifically, we will have to
838
+ // encode enough information in the GeneratedSourceInfo to know that
839
+ // the "top level" here is really a set of accessor declarations, so we
840
+ // can parse those. Both parsers will need to do it this way. Alternatively,
841
+ // we can put some extra braces around things and use parseGetSet, but that
842
+ // doesn't feel quite right, because we might eventually allow additional
843
+ // accessors to be inserted for properties that already have accesssors.
844
+ // parseTopLevelItems is where things get interesting... hmmm...
845
+
846
+
847
+ #if false
848
+ // Retrieve the parsed declarations from the list of top-level items.
849
+ auto topLevelItems = macroSourceFile->getTopLevelItems ();
850
+ for (auto item : topLevelItems) {
851
+ auto *decl = item.dyn_cast <Decl *>();
852
+ if (!decl) {
853
+ ctx.Diags .diagnose (
854
+ macroBufferRange.getStart (), diag::expected_macro_expansion_decls);
855
+ return ;
856
+ }
857
+ decl->setDeclContext (dc);
858
+ TypeChecker::typeCheckDecl (decl);
859
+ results.push_back (decl);
860
+ }
861
+
862
+ #endif
863
+ return ;
864
+ }
0 commit comments