Skip to content

Commit bba1432

Browse files
authored
Merge pull request swiftlang#76364 from DougGregor/apply-macro-to-imported
Allow attached macros to be applied to imported C declarations
2 parents cda4dc5 + f53670b commit bba1432

17 files changed

+358
-5
lines changed

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
230230
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
231231
EXPERIMENTAL_FEATURE(CodeItemMacros, false)
232232
EXPERIMENTAL_FEATURE(PreambleMacros, false)
233+
EXPERIMENTAL_FEATURE(MacrosOnImports, true)
233234
EXPERIMENTAL_FEATURE(TupleConformances, false)
234235
EXPERIMENTAL_FEATURE(FullTypedThrows, false)
235236
EXPERIMENTAL_FEATURE(SameElementRequirements, false)

include/swift/Frontend/FrontendOptions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ enum class IntermoduleDepTrackingMode;
3838
/// Options for controlling the behavior of the frontend.
3939
class FrontendOptions {
4040
friend class ArgsToFrontendOptionsConverter;
41+
public:
4142

4243
/// A list of arbitrary modules to import and make implicitly visible.
4344
std::vector<std::pair<std::string, bool /*testable*/>>
4445
ImplicitImportModuleNames;
4546

46-
public:
4747
FrontendInputsAndOutputs InputsAndOutputs;
4848

4949
void forAllOutputPaths(const InputFile &input,

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ UNINTERESTING_FEATURE(Embedded)
121121
UNINTERESTING_FEATURE(Volatile)
122122
UNINTERESTING_FEATURE(SuppressedAssociatedTypes)
123123
UNINTERESTING_FEATURE(StructLetDestructuring)
124+
UNINTERESTING_FEATURE(MacrosOnImports)
124125

125126
static bool usesFeatureNonescapableTypes(Decl *decl) {
126127
auto containsNonEscapable =

lib/AST/NameLookup.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "swift/Basic/SourceManager.h"
4141
#include "swift/Basic/Statistic.h"
4242
#include "swift/ClangImporter/ClangImporterRequests.h"
43+
#include "swift/ClangImporter/ClangModule.h"
4344
#include "swift/Parse/Lexer.h"
4445
#include "swift/Strings.h"
4546
#include "clang/AST/DeclObjC.h"
@@ -1718,6 +1719,15 @@ SmallVector<MacroDecl *, 1> namelookup::lookupMacros(DeclContext *dc,
17181719
ctx.evaluator, UnqualifiedLookupRequest{moduleLookupDesc}, {});
17191720
auto foundTypeDecl = moduleLookup.getSingleTypeResult();
17201721
auto *moduleDecl = dyn_cast_or_null<ModuleDecl>(foundTypeDecl);
1722+
1723+
// When resolving macro names for imported entities, we look for any
1724+
// loaded module.
1725+
if (!moduleDecl && isa<ClangModuleUnit>(moduleScopeDC) &&
1726+
ctx.LangOpts.hasFeature(Feature::MacrosOnImports)) {
1727+
moduleDecl = ctx.getLoadedModule(moduleName.getBaseIdentifier());
1728+
moduleScopeDC = moduleDecl;
1729+
}
1730+
17211731
if (!moduleDecl)
17221732
return {};
17231733

lib/ClangImporter/ClangImporter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,11 @@ void importer::getNormalInvocationArguments(
683683
if (LangOpts.hasFeature(Feature::SendingArgsAndResults))
684684
invocationArgStrs.push_back("-D__SWIFT_ATTR_SUPPORTS_SENDING=1");
685685

686+
// Indicate that the compiler will respect macros applied to imported
687+
// declarations via '__attribute__((swift_attr("@...")))'.
688+
if (LangOpts.hasFeature(Feature::MacrosOnImports))
689+
invocationArgStrs.push_back("-D__SWIFT_ATTR_SUPPORTS_MACROS=1");
690+
686691
if (searchPathOpts.getSDKPath().empty()) {
687692
invocationArgStrs.push_back("-Xclang");
688693
invocationArgStrs.push_back("-nostdsysteminc");
@@ -4717,6 +4722,17 @@ bool ClangImporter::Implementation::lookupValue(SwiftLookupTable &table,
47174722
}
47184723
}
47194724

4725+
// Visit auxiliary declarations to check for name matches.
4726+
decl->visitAuxiliaryDecls([&](Decl *aux) {
4727+
if (auto auxValue = dyn_cast<ValueDecl>(aux)) {
4728+
if (auxValue->getName().matchesRef(name) &&
4729+
auxValue->getDeclContext()->isModuleScopeContext()) {
4730+
consumer.foundDecl(auxValue, DeclVisibilityKind::VisibleAtTopLevel);
4731+
anyMatching = true;
4732+
}
4733+
}
4734+
});
4735+
47204736
// If we have a declaration and nothing matched so far, try the names used
47214737
// in other versions of Swift.
47224738
if (auto clangDecl = entry.dyn_cast<clang::NamedDecl *>()) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9669,6 +9669,13 @@ bool ClangImporter::Implementation::addMemberAndAlternatesToExtension(
96699669
if (!isa<AccessorDecl>(alternate))
96709670
ext->addMember(alternate);
96719671
}
9672+
9673+
member->visitAuxiliaryDecls([&](Decl *aux) {
9674+
if (auto auxValue = dyn_cast<ValueDecl>(aux)) {
9675+
ext->addMember(auxValue);
9676+
}
9677+
});
9678+
96729679
return true;
96739680
}
96749681

@@ -9741,6 +9748,16 @@ void ClangImporter::Implementation::insertMembersAndAlternates(
97419748
}
97429749
}
97439750

9751+
// If there are auxiliary declarations (e.g., produced by macros), load
9752+
// those.
9753+
member->visitAuxiliaryDecls([&](Decl *aux) {
9754+
if (auto auxValue = dyn_cast<ValueDecl>(aux)) {
9755+
if (auxValue->getDeclContext() == expectedDC &&
9756+
knownAlternateMembers.insert(auxValue).second)
9757+
members.push_back(auxValue);
9758+
}
9759+
});
9760+
97449761
// If this declaration shouldn't be visible, don't add it to
97459762
// the list.
97469763
if (shouldSuppressDeclImport(nd))

lib/Sema/TypeCheckDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3350,6 +3350,7 @@ SourceLoc PrettyPrintDeclRequest::evaluate(Evaluator &eval, const Decl *decl) co
33503350
getBufferAccessLevel(decl),
33513351
ctx.TypeCheckerOpts.PrintFullConvention);
33523352
decl->print(printer, options);
3353+
33533354
// Close all of the enclosing types.
33543355
for (const auto & enclosingType: enclosingTypes) {
33553356
(void)enclosingType;
@@ -3381,5 +3382,11 @@ SourceLoc PrettyPrintDeclRequest::evaluate(Evaluator &eval, const Decl *decl) co
33813382
}
33823383
);
33833384

3385+
// Add a source file for the buffer.
3386+
auto moduleDecl = decl->getDeclContext()->getParentModule();
3387+
auto sourceFile = new (ctx) SourceFile(
3388+
*moduleDecl, SourceFileKind::Library, bufferID);
3389+
sourceFile->setImports({ });
3390+
33843391
return memBufferStartLoc.getAdvancedLoc(targetDeclOffsetInBuffer);
33853392
}

lib/Sema/TypeCheckMacros.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/ASTContext.h"
2424
#include "swift/AST/ASTMangler.h"
2525
#include "swift/AST/ASTNode.h"
26+
#include "swift/AST/ASTPrinter.h"
2627
#include "swift/AST/DiagnosticsFrontend.h"
2728
#include "swift/AST/Expr.h"
2829
#include "swift/AST/FreestandingMacroExpansion.h"
@@ -39,6 +40,7 @@
3940
#include "swift/Basic/Lazy.h"
4041
#include "swift/Basic/SourceManager.h"
4142
#include "swift/Basic/StringExtras.h"
43+
#include "swift/ClangImporter/ClangModule.h"
4244
#include "swift/Bridging/ASTGen.h"
4345
#include "swift/Bridging/Macros.h"
4446
#include "swift/Demangling/Demangler.h"
@@ -1021,7 +1023,10 @@ createMacroSourceFile(std::unique_ptr<llvm::MemoryBuffer> buffer,
10211023
auto macroSourceFile = new (ctx) SourceFile(
10221024
*dc->getParentModule(), SourceFileKind::MacroExpansion, macroBufferID,
10231025
/*parsingOpts=*/{}, /*isPrimary=*/false);
1024-
macroSourceFile->setImports(dc->getParentSourceFile()->getImports());
1026+
if (auto parentSourceFile = dc->getParentSourceFile())
1027+
macroSourceFile->setImports(parentSourceFile->getImports());
1028+
else if (isa<ClangModuleUnit>(dc->getModuleScopeContext()))
1029+
macroSourceFile->setImports({});
10251030
return macroSourceFile;
10261031
}
10271032

@@ -1346,8 +1351,17 @@ static SourceFile *evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo,
13461351
if (!attrSourceFile)
13471352
return nullptr;
13481353

1349-
auto declSourceFile =
1350-
moduleDecl->getSourceFileContainingLocation(attachedTo->getStartLoc());
1354+
// If the declaration has no source location and comes from a Clang module,
1355+
// pretty-print the declaration and use that location.
1356+
SourceLoc attachedToLoc = attachedTo->getLoc();
1357+
if (attachedToLoc.isInvalid() &&
1358+
isa<ClangModuleUnit>(dc->getModuleScopeContext())) {
1359+
attachedToLoc = evaluateOrDefault(
1360+
ctx.evaluator, PrettyPrintDeclRequest{attachedTo}, SourceLoc());
1361+
}
1362+
1363+
SourceFile *declSourceFile =
1364+
moduleDecl->getSourceFileContainingLocation(attachedToLoc);
13511365
if (!declSourceFile)
13521366
return nullptr;
13531367

@@ -1486,13 +1500,18 @@ static SourceFile *evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo,
14861500
if (auto var = dyn_cast<VarDecl>(attachedTo))
14871501
searchDecl = var->getParentPatternBinding();
14881502

1503+
auto startLoc = searchDecl->getStartLoc();
1504+
if (startLoc.isInvalid() && isa<ClangModuleUnit>(dc->getModuleScopeContext())) {
1505+
startLoc = attachedToLoc;
1506+
}
1507+
14891508
BridgedStringRef evaluatedSourceOut{nullptr, 0};
14901509
assert(!externalDef.isError());
14911510
swift_Macros_expandAttachedMacro(
14921511
&ctx.Diags, externalDef.get(), discriminator->c_str(),
14931512
extendedType.c_str(), conformanceList.c_str(), getRawMacroRole(role),
14941513
astGenAttrSourceFile, attr->AtLoc.getOpaquePointerValue(),
1495-
astGenDeclSourceFile, searchDecl->getStartLoc().getOpaquePointerValue(),
1514+
astGenDeclSourceFile, startLoc.getOpaquePointerValue(),
14961515
astGenParentDeclSourceFile, parentDeclLoc, &evaluatedSourceOut);
14971516
if (!evaluatedSourceOut.unbridged().data())
14981517
return nullptr;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#if __SWIFT_ATTR_SUPPORTS_MACROS
2+
#define ADD_ASYNC __attribute__((swift_attr("@macro_library.AddAsync")))
3+
#else
4+
#define ADD_ASYNC
5+
#endif
6+
7+
void async_divide(double x, double y, void (* _Nonnull completionHandler)(double x)) ADD_ASYNC;
8+
9+
typedef struct SlowComputer {
10+
} SlowComputer;
11+
12+
void computer_divide(const SlowComputer *computer, double x, double y, void (* _Nonnull completionHandler)(double x))
13+
ADD_ASYNC
14+
__attribute__((swift_name("SlowComputer.divide(self:_:_:completionHandler:)")));
15+
16+
17+
#if __OBJC__
18+
@import Foundation;
19+
20+
@interface Computer: NSObject
21+
-(void)multiply:(double)x by:(double)y afterDone:(void (^ _Nonnull)(double x))afterDone
22+
ADD_ASYNC
23+
__attribute__((swift_async(none)));
24+
@end
25+
#endif

test/Inputs/clang-importer-sdk/usr/include/module.modulemap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,7 @@ module IncompleteTypes {
153153
header "IncompleteTypes.h"
154154
export *
155155
}
156+
157+
module CompletionHandlerGlobals {
158+
header "completion_handler_globals.h"
159+
}

0 commit comments

Comments
 (0)