-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Macros] Freestanding macro expansions in code blocks #63217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
283c5cd
dd876f4
41f1170
0fc4648
b6552ed
373bc85
f030142
7d5878f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,6 +76,34 @@ void ASTScope::dumpOneScopeMapLocation(std::pair<unsigned, unsigned> lineCol) { | |
impl->dumpOneScopeMapLocation(lineCol); | ||
} | ||
|
||
bool ASTScope::isLocWithinMacroDeclOrTopLevelMacroExpansionDeclScope( | ||
SourceFile *sf, SourceLoc loc) { | ||
// The innermost scope containing the loc. | ||
auto *innermostScope = sf->getScope().impl->findInnermostEnclosingScope( | ||
loc, nullptr); | ||
auto isMDOrTopLevelMED = [&](const ASTScopeImpl *scope) -> bool { | ||
if (auto *decl = scope->getDeclIfAny().getPtrOrNull()) { | ||
if (auto *med = dyn_cast<MacroExpansionDecl>(decl)) { | ||
if (med->getDeclContext()->getContextKind() == | ||
DeclContextKind::FileUnit) | ||
return true; | ||
} else if (auto *md = dyn_cast<MacroDecl>(decl)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why check for a macro declaration here? It's only macro expansions that we need to worry about, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When we populate |
||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
// Climb up the tree until we find a matching scope. | ||
const ASTScopeImpl *scope = innermostScope; | ||
while (!isMDOrTopLevelMED(scope)) { | ||
auto *parentScope = scope->getLookupParent().getPtrOrNull(); | ||
if (!parentScope || parentScope == scope) | ||
return false; | ||
scope = parentScope; | ||
} | ||
return true; | ||
} | ||
|
||
#pragma mark ASTScopeImpl | ||
|
||
|
||
|
@@ -151,6 +179,7 @@ DEFINE_GET_CLASS_NAME(DifferentiableAttributeScope) | |
DEFINE_GET_CLASS_NAME(SubscriptDeclScope) | ||
DEFINE_GET_CLASS_NAME(EnumElementScope) | ||
DEFINE_GET_CLASS_NAME(MacroDeclScope) | ||
DEFINE_GET_CLASS_NAME(MacroExpansionDeclScope) | ||
DEFINE_GET_CLASS_NAME(IfStmtScope) | ||
DEFINE_GET_CLASS_NAME(WhileStmtScope) | ||
DEFINE_GET_CLASS_NAME(GuardStmtScope) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Brace statements imply a nested scope, which probably isn't what we want semantically. Can this become an
ArrayRef<ASTNode>
to mimic the[CodeBlockItemSyntax]
we recently agreed upon for the macro implementation interface?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. I was relying on
BraceStmt
merely as a convenient container, and theBraceStmt
was never visited as a child ofMacroExpransionDecl
; ASTWalker directly walks theBraceStmt
's children instead. I think it's better thanArrayRef<ASTNode>
because we can distinguish betweennullptr
(expansion failure) and an empty list from the return ofswift::expandFreestandingMacro()
. Otherwise I would need to make it return abool
and produce indirect results into aASTNode
vector. Thoughts?