[cfe] Add Class.isMacro

This adds support for detecting macro classes from .dill

TEST=pkg/front_end/testcases/macros/macro_class.dart

Change-Id: I8d45cafff1b4edaff7e090384be1a1cf9c8087ae
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/224948
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index c1a3b8a..eb36433 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -111,6 +111,8 @@
 
   bool get isAbstract;
 
+  bool get isMacro;
+
   bool get declaresConstConstructor;
 
   bool get isMixin;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index 0a5f4e1..9ccfd18 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -50,6 +50,9 @@
   DillLibraryBuilder get library => super.library as DillLibraryBuilder;
 
   @override
+  bool get isMacro => cls.isMacro;
+
+  @override
   List<TypeVariableBuilder>? get typeVariables {
     List<TypeVariableBuilder>? typeVariables = super.typeVariables;
     if (typeVariables == null && cls.typeParameters.isNotEmpty) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index f9033bb..6c5157d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -100,6 +100,7 @@
 
   final IndexedClass? referencesFromIndexed;
 
+  @override
   final bool isMacro;
 
   SourceClassBuilder(
@@ -242,6 +243,7 @@
     // TODO(ahe): If `cls.supertype` is null, and this isn't Object, report a
     // compile-time error.
     cls.isAbstract = isAbstract;
+    cls.isMacro = isMacro;
     if (interfaceBuilders != null) {
       for (int i = 0; i < interfaceBuilders!.length; ++i) {
         interfaceBuilders![i] = checkSupertype(interfaceBuilders![i]);
diff --git a/pkg/front_end/testcases/macros/macro_class.dart.strong.expect b/pkg/front_end/testcases/macros/macro_class.dart.strong.expect
index 31fac3d..d2dba25 100644
--- a/pkg/front_end/testcases/macros/macro_class.dart.strong.expect
+++ b/pkg/front_end/testcases/macros/macro_class.dart.strong.expect
@@ -9,22 +9,22 @@
 }
 abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
 }
-class Class1 extends core::Object {
+macro class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
     : super core::Object::•()
     ;
 }
-abstract class Class2 extends core::Object {
+abstract macro class Class2 extends core::Object {
   synthetic constructor •() → self::Class2
     : super core::Object::•()
     ;
 }
-class Class3 = self::Super with self::Mixin {
+macro class Class3 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class3
     : super self::Super::•()
     ;
 }
-abstract class Class4 = self::Super with self::Mixin {
+abstract macro class Class4 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class4
     : super self::Super::•()
     ;
diff --git a/pkg/front_end/testcases/macros/macro_class.dart.strong.transformed.expect b/pkg/front_end/testcases/macros/macro_class.dart.strong.transformed.expect
index 1213172..d100b6c 100644
--- a/pkg/front_end/testcases/macros/macro_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/macros/macro_class.dart.strong.transformed.expect
@@ -9,22 +9,22 @@
 }
 abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
 }
-class Class1 extends core::Object {
+macro class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
     : super core::Object::•()
     ;
 }
-abstract class Class2 extends core::Object {
+abstract macro class Class2 extends core::Object {
   synthetic constructor •() → self::Class2
     : super core::Object::•()
     ;
 }
-class Class3 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+macro class Class3 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Class3
     : super self::Super::•()
     ;
 }
-abstract class Class4 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+abstract macro class Class4 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Class4
     : super self::Super::•()
     ;
diff --git a/pkg/front_end/testcases/macros/macro_class.dart.weak.expect b/pkg/front_end/testcases/macros/macro_class.dart.weak.expect
index 31fac3d..d2dba25 100644
--- a/pkg/front_end/testcases/macros/macro_class.dart.weak.expect
+++ b/pkg/front_end/testcases/macros/macro_class.dart.weak.expect
@@ -9,22 +9,22 @@
 }
 abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
 }
-class Class1 extends core::Object {
+macro class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
     : super core::Object::•()
     ;
 }
-abstract class Class2 extends core::Object {
+abstract macro class Class2 extends core::Object {
   synthetic constructor •() → self::Class2
     : super core::Object::•()
     ;
 }
-class Class3 = self::Super with self::Mixin {
+macro class Class3 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class3
     : super self::Super::•()
     ;
 }
-abstract class Class4 = self::Super with self::Mixin {
+abstract macro class Class4 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class4
     : super self::Super::•()
     ;
diff --git a/pkg/front_end/testcases/macros/macro_class.dart.weak.modular.expect b/pkg/front_end/testcases/macros/macro_class.dart.weak.modular.expect
index 31fac3d..d2dba25 100644
--- a/pkg/front_end/testcases/macros/macro_class.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/macros/macro_class.dart.weak.modular.expect
@@ -9,22 +9,22 @@
 }
 abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
 }
-class Class1 extends core::Object {
+macro class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
     : super core::Object::•()
     ;
 }
-abstract class Class2 extends core::Object {
+abstract macro class Class2 extends core::Object {
   synthetic constructor •() → self::Class2
     : super core::Object::•()
     ;
 }
-class Class3 = self::Super with self::Mixin {
+macro class Class3 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class3
     : super self::Super::•()
     ;
 }
-abstract class Class4 = self::Super with self::Mixin {
+abstract macro class Class4 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class4
     : super self::Super::•()
     ;
diff --git a/pkg/front_end/testcases/macros/macro_class.dart.weak.outline.expect b/pkg/front_end/testcases/macros/macro_class.dart.weak.outline.expect
index 982b26e..ecf4712 100644
--- a/pkg/front_end/testcases/macros/macro_class.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/macros/macro_class.dart.weak.outline.expect
@@ -8,20 +8,20 @@
 }
 abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
 }
-class Class1 extends core::Object {
+macro class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
     ;
 }
-abstract class Class2 extends core::Object {
+abstract macro class Class2 extends core::Object {
   synthetic constructor •() → self::Class2
     ;
 }
-class Class3 = self::Super with self::Mixin {
+macro class Class3 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class3
     : super self::Super::•()
     ;
 }
-abstract class Class4 = self::Super with self::Mixin {
+abstract macro class Class4 = self::Super with self::Mixin {
   synthetic constructor •() → self::Class4
     : super self::Super::•()
     ;
diff --git a/pkg/front_end/testcases/macros/macro_class.dart.weak.transformed.expect b/pkg/front_end/testcases/macros/macro_class.dart.weak.transformed.expect
index 1213172..d100b6c 100644
--- a/pkg/front_end/testcases/macros/macro_class.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/macros/macro_class.dart.weak.transformed.expect
@@ -9,22 +9,22 @@
 }
 abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
 }
-class Class1 extends core::Object {
+macro class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
     : super core::Object::•()
     ;
 }
-abstract class Class2 extends core::Object {
+abstract macro class Class2 extends core::Object {
   synthetic constructor •() → self::Class2
     : super core::Object::•()
     ;
 }
-class Class3 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+macro class Class3 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Class3
     : super self::Super::•()
     ;
 }
-abstract class Class4 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+abstract macro class Class4 extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
   synthetic constructor •() → self::Class4
     : super self::Super::•()
     ;
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index e710da2..b75aba6 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 74;
+  UInt32 formatVersion = 75;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -316,7 +316,7 @@
   FileOffset fileOffset; // Offset of the name of the class.
   FileOffset fileEndOffset;
   Byte flags (isAbstract, isEnum, isAnonymousMixin, isEliminatedMixin,
-              isMixinDeclaration, hasConstConstructor);
+              isMixinDeclaration, hasConstConstructor, isMacro);
   StringReference name;
   List<Expression> annotations;
   List<TypeParameter> typeParameters;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 38e5cfc..99a2f86 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1013,6 +1013,7 @@
   static const int FlagEliminatedMixin = 1 << 3;
   static const int FlagMixinDeclaration = 1 << 4;
   static const int FlagHasConstConstructor = 1 << 5;
+  static const int FlagMacro = 1 << 6;
 
   int flags = 0;
 
@@ -1029,6 +1030,13 @@
     flags = value ? (flags | FlagEnum) : (flags & ~FlagEnum);
   }
 
+  /// Whether this class is a macro class.
+  bool get isMacro => flags & FlagMacro != 0;
+
+  void set isMacro(bool value) {
+    flags = value ? (flags | FlagMacro) : (flags & ~FlagMacro);
+  }
+
   /// Whether this class is a synthetic implementation created for each
   /// mixed-in class. For example the following code:
   /// class Z extends A with B, C, D {}
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 859ed11..ceaae4a 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -176,7 +176,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 74;
+  static const int BinaryFormatVersion = 75;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 6a24e52..4f718b9 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1294,6 +1294,7 @@
     writeAnnotationList(node.annotations);
     writeIndentation();
     writeModifier(node.isAbstract, 'abstract');
+    writeModifier(node.isMacro, 'macro');
     writeWord('class');
     writeWord(getClassName(node));
     writeTypeParameterList(node.typeParameters);
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 2ee98c3..0a38ec2 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -2601,6 +2601,7 @@
   Class.FlagEliminatedMixin: "eliminated-mixin",
   Class.FlagMixinDeclaration: "mixin-declaration",
   Class.FlagHasConstConstructor: "has-const-constructor",
+  Class.FlagMacro: "macro",
 };
 
 class ClassFlagTagger implements Tagger<int> {
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index cfe75b0..35b2647 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -716,6 +716,7 @@
     kIsEliminatedMixin = 1 << 3,
     kFlagMixinDeclaration = 1 << 4,
     kHasConstConstructor = 1 << 5,
+    kIsMacro = 1 << 6,
   };
 
   explicit ClassHelper(KernelReaderHelper* helper)
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 46d20ec..891a2b7 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,8 +20,8 @@
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
 
 // Both version numbers are inclusive.
-static const uint32_t kMinSupportedKernelFormatVersion = 74;
-static const uint32_t kMaxSupportedKernelFormatVersion = 74;
+static const uint32_t kMinSupportedKernelFormatVersion = 75;
+static const uint32_t kMaxSupportedKernelFormatVersion = 75;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \