From ecc33865b935f6abf1ab00c63e4bf6d117dbdaec Mon Sep 17 00:00:00 2001 From: Richard Wei Date: Thu, 23 Feb 2023 04:37:10 +0800 Subject: [PATCH] [Macros] Fix `MacroDecl` serialization crash with custom parameter attributes Type-check `MacroDecl`'s parameter list so that custom attributes on parameters will have a type. Fixes a serialization crash. --- include/swift/AST/Decl.h | 3 +++ lib/Sema/TypeCheckAccess.cpp | 5 ++++- lib/Sema/TypeCheckDeclPrimary.cpp | 2 ++ test/Serialization/Inputs/def_macros.swift | 7 +++++++ test/Serialization/macros.swift | 8 ++++++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index ac66c697cf879..9d67bbd738daa 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -8418,6 +8418,9 @@ class MacroDecl : public GenericContext, public ValueDecl { /// Retrieve the definition of this macro. MacroDefinition getDefinition() const; + /// Retrieve the parameter list of this macro. + ParameterList *getParameterList() const { return parameterList; } + /// Retrieve the builtin macro kind for this macro, or \c None if it is a /// user-defined macro with no special semantics. Optional getBuiltinKind() const; diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index dcdd0912b338c..89014f5986622 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1174,7 +1174,6 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, UNINTERESTING(Destructor) // Always correct. UNINTERESTING(Accessor) // Handled by the Var or Subscript. UNINTERESTING(OpaqueType) // Handled by the Var or Subscript. - UNINTERESTING(Macro) /// If \p VD's layout is exposed by a @frozen struct or class, return said /// struct or class. @@ -1569,6 +1568,10 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, } } + void visitMacroDecl(MacroDecl *MD) { + // FIXME: Check access of macro generic parameters, parameters and result + } + void visitEnumElementDecl(EnumElementDecl *EED) { if (!EED->hasAssociatedValues()) return; diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index cd0f1f7f902b1..3767d3301f179 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -2019,6 +2019,8 @@ class DeclChecker : public DeclVisitor { if (!MD->getAttrs().hasAttribute(/*AllowInvalid*/ true)) MD->diagnose(diag::macro_without_role, MD->getName()); + TypeChecker::checkParameterList(MD->getParameterList(), MD); + // Check the macro definition. switch (auto macroDef = MD->getDefinition()) { case MacroDefinition::Kind::Undefined: diff --git a/test/Serialization/Inputs/def_macros.swift b/test/Serialization/Inputs/def_macros.swift index 1b62f9b15a506..1cad0b267d34a 100644 --- a/test/Serialization/Inputs/def_macros.swift +++ b/test/Serialization/Inputs/def_macros.swift @@ -24,3 +24,10 @@ public struct Base { public struct TestMacroArgTypechecking { public var value: Int } + +@resultBuilder +public struct Builder { + static func buildBlock(_: Int...) -> Void {} +} +@freestanding(expression) +public macro macroWithBuilderArgs(@Builder _: () -> Void) = #externalMacro(module: "A", type: "B") diff --git a/test/Serialization/macros.swift b/test/Serialization/macros.swift index 030f2e1c96451..e3595c970b773 100644 --- a/test/Serialization/macros.swift +++ b/test/Serialization/macros.swift @@ -5,6 +5,8 @@ // RUN: %target-build-swift -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/def_macro_plugin.swift -g -no-toolchain-stdlib-rpath // RUN: %target-swift-frontend -emit-module -o %t/def_macros.swiftmodule %S/Inputs/def_macros.swift -module-name def_macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir // RUN: %target-swift-frontend -typecheck -I%t -verify %s -verify-ignore-unknown -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir +// RUN: llvm-bcanalyzer %t/def_macros.swiftmodule | %FileCheck %s +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -module-to-print=def_macros -I %t -source-filename=%s | %FileCheck -check-prefix=CHECK-PRINT %s // REQUIRES: OS=macosx import def_macros @@ -19,3 +21,9 @@ func test(a: Int, b: Int) { struct TestStruct { @myWrapper var x: Int } + +// CHECK: MACRO_DECL + +// CHECK-NOT: UnknownCode + +// CHECK-PRINT-DAG: macro macroWithBuilderArgs(@Builder _: () -> Void)