Skip to content

[Macro] Omnibus pull request with macro improvements #62768

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
merged 19 commits into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0407610
[Macros] Don't parse the macro expansion buffer twice.
DougGregor Dec 22, 2022
bdc01ea
[Macros] Handle macro argument lists in diagnostics
DougGregor Dec 22, 2022
af49a90
Customize diagnostic text for extra/missing/mislabeled arguments for …
DougGregor Dec 22, 2022
4ed393d
[Macros] Add a test of a variadic "print" macro.
DougGregor Dec 22, 2022
806b5a8
[Macros] Diagnose errors where a macro is used without the '#'.
DougGregor Dec 23, 2022
36dd677
[Macros] Don't stop lookup early if we found a macro.
DougGregor Dec 23, 2022
6bad02c
[Macros] Implement overloading rules
DougGregor Dec 23, 2022
71ca9c8
[Macros] Diagnose when we forget to provide macro arguments.
DougGregor Dec 24, 2022
6bb9cb8
[Macros] Always parse macro expansions, diagnose later
DougGregor Dec 24, 2022
222bc03
[Macros] Prevent recursive expansion of macros.
DougGregor Dec 24, 2022
bbb5c7a
[Macros] Allow enums and classes/actors to be macro definitions, too
DougGregor Dec 24, 2022
1b14b5d
Fixup some test cases
DougGregor Dec 24, 2022
271048c
[Macros] Fix diagnostic location
DougGregor Dec 25, 2022
8cbae04
One last little test fix
DougGregor Dec 25, 2022
76e0d5e
[Macro] API digester support for macro declarations
DougGregor Jan 3, 2023
49b42b4
Handle indexing of macros
DougGregor Jan 3, 2023
7000969
Introduce and use `#externalMacro` for externally-defined macros.
DougGregor Jan 3, 2023
0868889
Add new source file Macros.swift
DougGregor Jan 3, 2023
5936b7b
Add test that started crashing with my initial rework of closure disc…
DougGregor Jan 3, 2023
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
8 changes: 8 additions & 0 deletions include/swift/APIDigester/ModuleAnalyzerNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,13 @@ class SDKNodeDeclVar : public SDKNodeDecl {
void addAccessor(SDKNode* AC);
};

class SDKNodeDeclMacro : public SDKNodeDecl {
public:
SDKNodeDeclMacro(SDKNodeInitInfo Info);
static bool classof(const SDKNode *N);
SDKNodeType *getType() const;
};

class SDKNodeDeclAbstractFunc : public SDKNodeDecl {
bool IsThrowing;
bool ReqNewWitnessTableEntry;
Expand Down Expand Up @@ -796,6 +803,7 @@ class SwiftDeclCollector: public VisibleDeclConsumer {
SDKNode *constructSubscriptDeclNode(SubscriptDecl *SD);
SDKNode *constructAssociatedTypeNode(AssociatedTypeDecl *ATD);
SDKNode *constructTypeAliasNode(TypeAliasDecl *TAD);
SDKNode *constructMacroNode(MacroDecl *MAD);
SDKNode *constructVarNode(ValueDecl *VD);
SDKNode *constructExternalExtensionNode(NominalTypeDecl *NTD,
ArrayRef<ExtensionDecl*> AllExts);
Expand Down
31 changes: 16 additions & 15 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace swift {
struct ASTNode;
class ASTPrinter;
class ASTWalker;
enum class BuiltinMacroKind: uint8_t;
class ConstructorDecl;
class DestructorDecl;
class DiagnosticEngine;
Expand All @@ -79,6 +80,7 @@ namespace swift {
class GenericSignature;
class GenericTypeParamDecl;
class GenericTypeParamType;
class MacroDefinition;
class ModuleDecl;
class NamedPattern;
class EnumCaseDecl;
Expand Down Expand Up @@ -255,6 +257,9 @@ struct OverloadSignature {
/// Whether this is a type alias.
unsigned IsTypeAlias : 1;

/// Whether this is a macro.
unsigned IsMacro : 1;

/// Whether this signature is part of a protocol extension.
unsigned InProtocolExtension : 1;

Expand Down Expand Up @@ -8341,27 +8346,16 @@ class MacroDecl : public GenericContext, public ValueDecl {
/// The result type.
TypeLoc resultType;

/// The module name for the external macro definition.
Identifier externalModuleName;

/// The location of the module name for the external macro definition.
SourceLoc externalModuleNameLoc;

/// The type name for the external macro definition.
Identifier externalMacroTypeName;

/// The location of the type name for the external macro definition.
SourceLoc externalMacroTypeNameLoc;
/// The macro definition, which should always be a
/// \c MacroExpansionExpr in well-formed code.
Expr *definition;

MacroDecl(SourceLoc macroLoc, DeclName name, SourceLoc nameLoc,
GenericParamList *genericParams,
ParameterList *parameterList,
SourceLoc arrowOrColonLoc,
TypeRepr *resultType,
Identifier externalModuleName,
SourceLoc externalModuleNameLoc,
Identifier externalMacroTypeName,
SourceLoc externalMacroTypeNameLoc,
Expr *definition,
DeclContext *parent);

SourceRange getSourceRange() const;
Expand All @@ -8372,6 +8366,13 @@ class MacroDecl : public GenericContext, public ValueDecl {
/// Determine the contexts in which this macro can be applied.
MacroContexts getMacroContexts() const;

/// Retrieve the definition of this macro.
MacroDefinition getDefinition() const;

/// Retrieve the builtin macro kind for this macro, or \c None if it is a
/// user-defined macro with no special semantics.
Optional<BuiltinMacroKind> getBuiltinKind() const;

static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsCommon.def
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ ERROR(unknown_attribute,none,
//------------------------------------------------------------------------------
NOTE(in_macro_expansion,none,
"in expansion of macro %0 here", (DeclName))
ERROR(macro_experimental,none,
"macros are an experimental feature that is not enabled", ())

//------------------------------------------------------------------------------
// MARK: bridged diagnostics
Expand Down
19 changes: 5 additions & 14 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1329,9 +1329,6 @@ ERROR(expected_rsquare_array_expr,PointsToFirstBadToken,
// Object literal expressions
ERROR(expected_arg_list_in_object_literal,PointsToFirstBadToken,
"expected argument list in object literal", ())
ERROR(legacy_object_literal,none,
"'%select{|[}0#%1(...)%select{|#]}0' has been renamed to '#%2(...)'",
(bool, StringRef, StringRef))

// Unknown pound expression.
ERROR(unknown_pound_expr,none,
Expand Down Expand Up @@ -1999,18 +1996,12 @@ ERROR(expected_lparen_macro,PointsToFirstBadToken,
"expected '(' for macro parameters or ':' for a value-like macro", ())
ERROR(expected_type_macro_result,PointsToFirstBadToken,
"expected macro result type", ())
ERROR(macro_decl_expected_equal,PointsToFirstBadToken,
"expected '=' to introduce external macro name", ())
ERROR(macro_decl_expected_macro_module,PointsToFirstBadToken,
"expected external macro name", ())
ERROR(macro_decl_expected_period,PointsToFirstBadToken,
"expected '.' between external macro module and type name", ())
ERROR(macro_decl_expected_macro_type,PointsToFirstBadToken,
"expected external macro type name", ())

ERROR(macro_expansion_expr_expected_macro_identifier,none,
ERROR(macro_decl_expected_macro_definition,PointsToFirstBadToken,
"expected macro definition following '=''", ())

ERROR(macro_expansion_expr_expected_macro_identifier,PointsToFirstBadToken,
"expected a macro identifier for a pound literal expression", ())
ERROR(macro_expansion_decl_expected_macro_identifier,none,
ERROR(macro_expansion_decl_expected_macro_identifier,PointsToFirstBadToken,
"expected a macro identifier for a pound literal declaration", ())

ERROR(parser_round_trip_error,none,
Expand Down
59 changes: 44 additions & 15 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1271,15 +1271,18 @@ ERROR(missing_init_on_metatype_initialization,none,
"initializing from a metatype value must reference 'init' explicitly",
())
ERROR(extra_argument_labels,none,
"extraneous argument label%select{|s}0 '%1' in %select{call|subscript}2",
(bool, StringRef, bool))
"extraneous argument label%select{|s}0 '%1' in "
"%select{call|subscript|macro expansion}2",
(bool, StringRef, unsigned))
ERROR(missing_argument_labels,none,
"missing argument label%select{|s}0 '%1' in %select{call|subscript}2",
(bool, StringRef, bool))
"missing argument label%select{|s}0 '%1' in "
"%select{call|subscript|macro expansion}2",
(bool, StringRef, unsigned))
ERROR(wrong_argument_labels,none,
"incorrect argument label%select{|s}0 in %select{call|subscript}3 "
"incorrect argument label%select{|s}0 in "
"%select{call|subscript|macro expansion}3 "
"(have '%1', expected '%2')",
(bool, StringRef, StringRef, bool))
(bool, StringRef, StringRef, unsigned))
ERROR(argument_out_of_order_named_named,none,
"argument %0 must precede argument %1", (Identifier, Identifier))
ERROR(argument_out_of_order_named_unnamed,none,
Expand Down Expand Up @@ -1313,22 +1316,29 @@ ERROR(instance_member_in_default_parameter,none,
"cannot use instance member %0 as a default parameter", (DeclNameRef))

ERROR(missing_argument_named,none,
"missing argument for parameter %0 in call", (Identifier))
"missing argument for parameter %0 in "
"%select{call|subscript|macro expansion}1", (Identifier, unsigned))
ERROR(missing_argument_positional,none,
"missing argument for parameter #%0 in call", (unsigned))
"missing argument for parameter #%0 in "
"%select{call|subscript|macro expansion}1", (unsigned, unsigned))
ERROR(missing_arguments_in_call,none,
"missing arguments for parameters %0 in call", (StringRef))
"missing arguments for parameters %0 in "
"%select{call|subscript|macro expansion}1", (StringRef, unsigned))
ERROR(extra_argument_named,none,
"extra argument %0 in call", (Identifier))
"extra argument %0 in %select{call|subscript|macro expansion}1",
(Identifier, unsigned))
ERROR(extra_argument_positional,none,
"extra argument in call", ())
"extra argument in %select{call|subscript|macro expansion}0",
(unsigned))
ERROR(extra_arguments_in_call,none,
"extra %select{arguments|trailing closures}0 at positions %1 in call",
(bool, StringRef))
ERROR(extra_argument_to_nullary_call,none,
"argument passed to call that takes no arguments", ())
"argument passed to %select{call|subscript|macro expansion}0 "
"that takes no arguments", (unsigned))
ERROR(extra_trailing_closure_in_call,none,
"extra trailing closure passed in call", ())
"extra trailing closure passed in "
"%select{call|subscript|macro expansion}0", (unsigned))
ERROR(trailing_closure_bad_param,none,
"trailing closure passed to parameter of type %0 that does not "
"accept a closure", (Type))
Expand Down Expand Up @@ -6752,8 +6762,7 @@ ERROR(experimental_no_metadata_feature_can_only_be_used_when_enabled,
ERROR(expected_macro_expansion_expr,PointsToFirstBadToken,
"expected macro expansion to produce an expression", ())
ERROR(macro_undefined,PointsToFirstBadToken,
"macro %0 is undefined; use `-load-plugin-library` to specify dynamic "
"libraries that contain this macro", (Identifier))
"no macro named %0", (Identifier))
ERROR(external_macro_not_found,none,
"external macro implementation type '%0.%1' could not be found for "
"macro %2; the type must be public and provided via "
Expand Down Expand Up @@ -6784,6 +6793,26 @@ ERROR(macro_in_nested,none,
ERROR(macro_without_context,none,
"macro %0 must declare its applicable contexts (e.g., '@expression')",
(DeclName))
ERROR(macro_expansion_missing_pound,none,
"expansion of macro %0 requires leading '#'", (DeclName))
ERROR(macro_expansion_missing_arguments,none,
"expansion of macro %0 requires arguments", (DeclName))
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,
"argument to `#externalMacro` must be a string literal naming "
"the external macro's %select{module|type}", (unsigned))

//------------------------------------------------------------------------------
// MARK: Move Only Errors
Expand Down
101 changes: 67 additions & 34 deletions include/swift/AST/MacroDefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,64 +22,97 @@

namespace swift {

/// A reference to an external macro definition that is understood by ASTGen.
struct ExternalMacroDefinition {
/// ASTGen's notion of an macro definition, which is opaque to the C++ part
/// of the compiler.
void *opaqueHandle = nullptr;
};

/// A reference to an external macro.
struct ExternalMacroReference {
Identifier moduleName;
Identifier macroTypeName;
};

/// Describes the known kinds of builtin macros.
enum class BuiltinMacroKind: uint8_t {
/// #externalMacro, which references an external macro.
ExternalMacro,
};

/// Provides the definition of a macro.
class MacroDefinition {
public:
/// Describes a missing macro definition.
struct MissingDefinition {
Identifier externalModuleName;
Identifier externalMacroTypeName;
};

/// Describes how the macro is implemented.
enum class ImplementationKind: uint8_t {
enum class Kind: uint8_t {
/// The macro has a definition, but it is invalid, so the macro cannot be
/// expanded.
Invalid,

/// The macro has no definition.
Undefined,

/// The macro has a definition, but it could not be found.
Missing,
/// An externally-provided macro definition.
External,

/// The macro is in the same process as the compiler, whether built-in or
/// loaded via a compiler plugin.
InProcess,
/// A builtin macro definition, which has a separate builtin kind.
Builtin,
};

ImplementationKind implKind;
Kind kind;

private:
void *opaqueHandle;
union Data {
ExternalMacroReference external;
BuiltinMacroKind builtin;

MacroDefinition(ImplementationKind implKind, void *opaqueHandle)
: implKind(implKind), opaqueHandle(opaqueHandle) { }
Data() : builtin(BuiltinMacroKind::ExternalMacro) { }
} data;

MacroDefinition(Kind kind) : kind(kind) { }

MacroDefinition(ExternalMacroReference external) : kind(Kind::External) {
data.external = external;
}

MacroDefinition(BuiltinMacroKind builtinKind) : kind(Kind::Builtin) {
data.builtin = builtinKind;
}

public:
static MacroDefinition forInvalid() {
return MacroDefinition(Kind::Invalid);
}

static MacroDefinition forUndefined() {
return MacroDefinition{
ImplementationKind::Undefined, nullptr
};
return MacroDefinition(Kind::Undefined);
}

static MacroDefinition forMissing(
ASTContext &ctx,
Identifier externalModuleName,
Identifier externalMacroTypeName
);
static MacroDefinition forExternal(
Identifier moduleName,
Identifier macroTypeName
) {
return MacroDefinition(ExternalMacroReference{moduleName, macroTypeName});
}

static MacroDefinition forInProcess(void *opaqueHandle) {
return MacroDefinition{ImplementationKind::InProcess, opaqueHandle};
static MacroDefinition forBuiltin(BuiltinMacroKind builtinKind) {
return MacroDefinition(builtinKind);
}

/// Return the opaque handle for an in-process macro definition.
void *getInProcessOpaqueHandle() const {
assert(implKind == ImplementationKind::InProcess);
return opaqueHandle;
/// Retrieve the external macro being referenced.
ExternalMacroReference getExternalMacro() const {
assert(kind == Kind::External);
return data.external;
}

/// Return more information about a missing macro definition.
MissingDefinition *getMissingDefinition() const {
assert(implKind == ImplementationKind::Missing);
return static_cast<MissingDefinition *>(opaqueHandle);
/// Retrieve the builtin kind.
BuiltinMacroKind getBuiltinKind() const {
assert(kind == Kind::Builtin);
return data.builtin;
}

explicit operator bool() const { return kind != Kind::Invalid; }
};

}
Expand Down
Loading