Skip to content

Name lookup and type checking fixes for freestanding declaration macros #64803

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions include/swift/AST/ASTScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,52 @@ class MacroDeclScope final : public ASTScopeImpl {

protected:
NullablePtr<const GenericParamList> genericParams() const override;
bool lookupLocalsOrMembers(DeclConsumer) const override;
};

/// The scope introduced for the definition of a macro, which follows the `=`.
class MacroDefinitionScope final : public ASTScopeImpl {
public:
Expr *const definition;

MacroDefinitionScope(Expr *definition) : definition(definition) {}

virtual ~MacroDefinitionScope() {}
SourceRange
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
std::string getClassName() const override;

private:
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

protected:
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
};

class MacroExpansionDeclScope final : public ASTScopeImpl {
public:
MacroExpansionDecl *const decl;

MacroExpansionDeclScope(MacroExpansionDecl *e) : decl(e) {}
virtual ~MacroExpansionDeclScope() {}

protected:
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
std::string getClassName() const override;
SourceRange
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
void printSpecifics(llvm::raw_ostream &out) const override;

public:
virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
Decl *getDecl() const { return decl; }
};

class AbstractStmtScope : public ASTScopeImpl {
Expand Down
10 changes: 10 additions & 0 deletions include/swift/AST/CASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedDiagnosticSeverity : long {

typedef void* BridgedDiagnostic;

typedef enum ENUM_EXTENSIBILITY_ATTR(open) BridgedMacroDefinitionKind : ptrdiff_t {
/// An expanded macro.
BridgedExpandedMacro = 0,
/// An external macro, spelled with either the old spelling (Module.Type)
/// or the new spelling `#externalMacro(module: "Module", type: "Type")`.
BridgedExternalMacro,
/// The builtin definition for "externalMacro".
BridgedBuiltinExternalMacro
} BridgedMacroDefinitionKind;

#ifdef __cplusplus
extern "C" {

Expand Down
49 changes: 37 additions & 12 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8538,8 +8538,13 @@ class MacroDecl : public GenericContext, public ValueDecl {
using Decl::getASTContext;
};

class MacroExpansionDecl : public Decl {
SourceLoc PoundLoc;
/// Information about a macro expansion that is common between macro
/// expansion declarations and expressions.
///
/// Instances of these types will be shared among paired macro expansion
/// declaration/expression nodes.
struct MacroExpansionInfo : ASTAllocated<MacroExpansionInfo> {
SourceLoc SigilLoc;
DeclNameRef MacroName;
DeclNameLoc MacroNameLoc;
SourceLoc LeftAngleLoc, RightAngleLoc;
Expand All @@ -8549,33 +8554,53 @@ class MacroExpansionDecl : public Decl {
/// The referenced macro.
ConcreteDeclRef macroRef;

MacroExpansionInfo(SourceLoc sigilLoc,
DeclNameRef macroName,
DeclNameLoc macroNameLoc,
SourceLoc leftAngleLoc, SourceLoc rightAngleLoc,
ArrayRef<TypeRepr *> genericArgs,
ArgumentList *argList)
: SigilLoc(sigilLoc), MacroName(macroName), MacroNameLoc(macroNameLoc),
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
GenericArgs(genericArgs), ArgList(argList) { }
};

class MacroExpansionDecl : public Decl {
MacroExpansionInfo *info;

public:
enum : unsigned { InvalidDiscriminator = 0xFFFF };

MacroExpansionDecl(DeclContext *dc, MacroExpansionInfo *info);

MacroExpansionDecl(DeclContext *dc, SourceLoc poundLoc, DeclNameRef macro,
DeclNameLoc macroLoc,
SourceLoc leftAngleLoc,
ArrayRef<TypeRepr *> genericArgs,
SourceLoc rightAngleLoc,
ArgumentList *args);

ArrayRef<TypeRepr *> getGenericArgs() const { return GenericArgs; }
ArrayRef<TypeRepr *> getGenericArgs() const {
return info->GenericArgs;
}

SourceRange getGenericArgsRange() const {
return SourceRange(LeftAngleLoc, RightAngleLoc);
return SourceRange(info->LeftAngleLoc, info->RightAngleLoc);
}

SourceRange getSourceRange() const;
SourceLoc getLocFromSource() const { return PoundLoc; }
SourceLoc getPoundLoc() const { return PoundLoc; }
DeclNameLoc getMacroNameLoc() const { return MacroNameLoc; }
DeclNameRef getMacroName() const { return MacroName; }
ArgumentList *getArgs() const { return ArgList; }
void setArgs(ArgumentList *args) { ArgList = args; }
SourceLoc getLocFromSource() const { return info->SigilLoc; }
SourceLoc getPoundLoc() const { return info->SigilLoc; }
DeclNameLoc getMacroNameLoc() const { return info->MacroNameLoc; }
DeclNameRef getMacroName() const { return info->MacroName; }
ArgumentList *getArgs() const { return info->ArgList; }
void setArgs(ArgumentList *args) { info->ArgList = args; }
using ExprOrStmtExpansionCallback = llvm::function_ref<void(ASTNode)>;
void forEachExpandedExprOrStmt(ExprOrStmtExpansionCallback) const;
ConcreteDeclRef getMacroRef() const { return macroRef; }
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
ConcreteDeclRef getMacroRef() const { return info->macroRef; }
void setMacroRef(ConcreteDeclRef ref) { info->macroRef = ref; }

MacroExpansionInfo *getExpansionInfo() const { return info; }

/// Returns a discriminator which determines this macro expansion's index
/// in the sequence of macro expansions within the current function.
Expand Down
7 changes: 0 additions & 7 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -6958,13 +6958,6 @@ ERROR(macro_unsupported,none,
"macros are not supported in this compiler", ())
ERROR(macro_recursive,none,
"recursive expansion of macro %0", (DeclName))
WARNING(macro_definition_old_style,none,
"external macro definitions are now written using #externalMacro", ())
WARNING(macro_definition_unknown_builtin,none,
"ignoring definition of unknown builtin macro %0", (Identifier))
ERROR(macro_definition_not_expansion,none,
"macro must itself be defined by a macro expansion such as "
"'#externalMacro(...)'", ())
ERROR(macro_definition_unsupported,none,
"macro definitions other than '#externalMacro(...)' are unsupported", ())
ERROR(external_macro_arg_not_type_name,none,
Expand Down
61 changes: 24 additions & 37 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -6189,22 +6189,24 @@ class TypeJoinExpr final : public Expr,
class MacroExpansionExpr final : public Expr {
private:
DeclContext *DC;
SourceLoc SigilLoc;
DeclNameRef MacroName;
DeclNameLoc MacroNameLoc;
SourceLoc LeftAngleLoc, RightAngleLoc;
ArrayRef<TypeRepr *> GenericArgs;
ArgumentList *ArgList;
MacroExpansionInfo *info;
Expr *Rewritten;
MacroRoles Roles;
MacroExpansionDecl *SubstituteDecl;

/// The referenced macro.
ConcreteDeclRef macroRef;

public:
enum : unsigned { InvalidDiscriminator = 0xFFFF };

explicit MacroExpansionExpr(DeclContext *dc, MacroExpansionInfo *info,
MacroRoles roles,
bool isImplicit = false,
Type ty = Type())
: Expr(ExprKind::MacroExpansion, isImplicit, ty),
DC(dc), info(info), Rewritten(nullptr), Roles(roles),
SubstituteDecl(nullptr) {
Bits.MacroExpansionExpr.Discriminator = InvalidDiscriminator;
}

explicit MacroExpansionExpr(DeclContext *dc,
SourceLoc sigilLoc, DeclNameRef macroName,
DeclNameLoc macroNameLoc,
Expand All @@ -6214,45 +6216,29 @@ class MacroExpansionExpr final : public Expr {
ArgumentList *argList,
MacroRoles roles,
bool isImplicit = false,
Type ty = Type())
: Expr(ExprKind::MacroExpansion, isImplicit, ty),
DC(dc), SigilLoc(sigilLoc),
MacroName(macroName), MacroNameLoc(macroNameLoc),
LeftAngleLoc(leftAngleLoc), RightAngleLoc(rightAngleLoc),
GenericArgs(genericArgs),
Rewritten(nullptr), Roles(roles), SubstituteDecl(nullptr) {
Bits.MacroExpansionExpr.Discriminator = InvalidDiscriminator;
Type ty = Type());

// Macro expansions always have an argument list. If one is not provided, create
// an implicit one.
if (argList) {
ArgList = argList;
} else {
ArgList = ArgumentList::createImplicit(dc->getASTContext(), {});
}
}

DeclNameRef getMacroName() const { return MacroName; }
DeclNameLoc getMacroNameLoc() const { return MacroNameLoc; }
DeclNameRef getMacroName() const { return info->MacroName; }
DeclNameLoc getMacroNameLoc() const { return info->MacroNameLoc; }

Expr *getRewritten() const { return Rewritten; }
void setRewritten(Expr *rewritten) { Rewritten = rewritten; }

ArrayRef<TypeRepr *> getGenericArgs() const { return GenericArgs; }
ArrayRef<TypeRepr *> getGenericArgs() const { return info->GenericArgs; }

SourceRange getGenericArgsRange() const {
return SourceRange(LeftAngleLoc, RightAngleLoc);
return SourceRange(info->LeftAngleLoc, info->RightAngleLoc);
}

ArgumentList *getArgs() const { return ArgList; }
void setArgs(ArgumentList *newArgs) { ArgList = newArgs; }
ArgumentList *getArgs() const { return info->ArgList; }
void setArgs(ArgumentList *newArgs) { info->ArgList = newArgs; }

MacroRoles getMacroRoles() const { return Roles; }

SourceLoc getLoc() const { return SigilLoc; }
SourceLoc getLoc() const { return info->SigilLoc; }

ConcreteDeclRef getMacroRef() const { return macroRef; }
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }
ConcreteDeclRef getMacroRef() const { return info->macroRef; }
void setMacroRef(ConcreteDeclRef ref) { info->macroRef = ref; }

DeclContext *getDeclContext() const { return DC; }
void setDeclContext(DeclContext *dc) { DC = dc; }
Expand All @@ -6275,11 +6261,12 @@ class MacroExpansionExpr final : public Expr {
Bits.MacroExpansionExpr.Discriminator = discriminator;
}

MacroExpansionInfo *getExpansionInfo() const { return info; }

SourceRange getSourceRange() const;

MacroExpansionDecl *createSubstituteDecl() const;
MacroExpansionDecl *createSubstituteDecl();
MacroExpansionDecl *getSubstituteDecl() const;
void setSubstituteDecl(MacroExpansionDecl *decl);

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MacroExpansion;
Expand Down
51 changes: 51 additions & 0 deletions include/swift/AST/MacroDefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

namespace swift {

class ASTContext;

/// A reference to an external macro definition that is understood by ASTGen.
struct ExternalMacroDefinition {
enum class PluginKind {
Expand All @@ -46,6 +48,35 @@ enum class BuiltinMacroKind: uint8_t {
ExternalMacro,
};

/// A single replacement
struct ExpandedMacroReplacement {
unsigned startOffset, endOffset;
unsigned parameterIndex;
};

/// An expansion of another macro.
class ExpandedMacroDefinition {
friend class MacroDefinition;

/// The expansion text, ASTContext-allocated.
StringRef expansionText;

/// The macro replacements, ASTContext-allocated.
ArrayRef<ExpandedMacroReplacement> replacements;

ExpandedMacroDefinition(
StringRef expansionText,
ArrayRef<ExpandedMacroReplacement> replacements
) : expansionText(expansionText), replacements(replacements) { }

public:
StringRef getExpansionText() const { return expansionText; }

ArrayRef<ExpandedMacroReplacement> getReplacements() const {
return replacements;
}
};

/// Provides the definition of a macro.
class MacroDefinition {
public:
Expand All @@ -63,6 +94,9 @@ class MacroDefinition {

/// A builtin macro definition, which has a separate builtin kind.
Builtin,

/// A macro that is defined as an expansion of another macro.
Expanded,
};

Kind kind;
Expand All @@ -71,6 +105,7 @@ class MacroDefinition {
union Data {
ExternalMacroReference external;
BuiltinMacroKind builtin;
ExpandedMacroDefinition expanded;

Data() : builtin(BuiltinMacroKind::ExternalMacro) { }
} data;
Expand All @@ -85,6 +120,10 @@ class MacroDefinition {
data.builtin = builtinKind;
}

MacroDefinition(ExpandedMacroDefinition expanded) : kind(Kind::Expanded) {
data.expanded = expanded;
}

public:
static MacroDefinition forInvalid() {
return MacroDefinition(Kind::Invalid);
Expand All @@ -105,6 +144,13 @@ class MacroDefinition {
return MacroDefinition(builtinKind);
}

/// Create a representation of an expanded macro definition.
static MacroDefinition forExpanded(
ASTContext &ctx,
StringRef expansionText,
ArrayRef<ExpandedMacroReplacement> replacements
);

/// Retrieve the external macro being referenced.
ExternalMacroReference getExternalMacro() const {
assert(kind == Kind::External);
Expand All @@ -117,6 +163,11 @@ class MacroDefinition {
return data.builtin;
}

ExpandedMacroDefinition getExpanded() const {
assert(kind == Kind::Expanded);
return data.expanded;
}

operator Kind() const { return kind; }
};

Expand Down
6 changes: 3 additions & 3 deletions include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ SUPPRESSIBLE_LANGUAGE_FEATURE(PrimaryAssociatedTypes2, 346, "Primary associated
SUPPRESSIBLE_LANGUAGE_FEATURE(UnavailableFromAsync, 0, "@_unavailableFromAsync", true)
SUPPRESSIBLE_LANGUAGE_FEATURE(NoAsyncAvailability, 340, "@available(*, noasync)", true)
LANGUAGE_FEATURE(BuiltinIntLiteralAccessors, 368, "Builtin.IntLiteral accessors", true)
LANGUAGE_FEATURE(Macros, 0, "Macros", true)
LANGUAGE_FEATURE(Macros, 0, "Macros", hasSwiftSwiftParser)
SUPPRESSIBLE_LANGUAGE_FEATURE(
FreestandingExpressionMacros, 382, "Expression macros",
true)
LANGUAGE_FEATURE(AttachedMacros, 389, "Attached macros", true)
hasSwiftSwiftParser)
LANGUAGE_FEATURE(AttachedMacros, 389, "Attached macros", hasSwiftSwiftParser)
LANGUAGE_FEATURE(MoveOnly, 390, "noncopyable types", true)

UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Basic/StringExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ class NullTerminatedStringRef {

/// Create a null-terminated string, copying \p Str into \p A .
template <typename Allocator>
NullTerminatedStringRef(StringRef Str, Allocator &A) : Ref("") {
NullTerminatedStringRef(StringRef Str, Allocator &A) : Ref() {
if (Str.empty())
return;

Expand Down
Loading