llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Hunter Baker (literally-anything)

<details>
<summary>Changes</summary>

This adds support for applying arbitrary Swift attributes to declarations using 
apinotes. For example:
```yaml
# Mark safe globals as nonisolated to make them accessible in Swift 6
Globals:
- Name: globalVariable
  SwiftAttributes:
  - "nonisolated(unsafe)"

# Apply Swift macros to C declarations on import
Functions:
- Name: cFunction
  SwiftAttributes:
  - "@<!-- -->MyModule.GenerateWrapper"
```
This fixes several cases where you would still need to modify the module 
headers to apply Swift attributes.

---
Full diff: https://github.com/llvm/llvm-project/pull/180382.diff


12 Files Affected:

- (modified) clang/docs/APINotes.rst (+20) 
- (modified) clang/include/clang/APINotes/Types.h (+9-1) 
- (modified) clang/lib/APINotes/APINotesFormat.h (+1-1) 
- (modified) clang/lib/APINotes/APINotesReader.cpp (+19) 
- (modified) clang/lib/APINotes/APINotesTypes.cpp (+7) 
- (modified) clang/lib/APINotes/APINotesWriter.cpp (+22-1) 
- (modified) clang/lib/APINotes/APINotesYAMLCompiler.cpp (+34) 
- (modified) clang/lib/Sema/SemaAPINotes.cpp (+5) 
- (added) clang/test/APINotes/Inputs/Headers/SwiftAttributes.apinotes (+24) 
- (added) clang/test/APINotes/Inputs/Headers/SwiftAttributes.h (+11) 
- (modified) clang/test/APINotes/Inputs/Headers/module.modulemap (+4) 
- (added) clang/test/APINotes/swift-attributes.cpp (+35) 


``````````diff
diff --git a/clang/docs/APINotes.rst b/clang/docs/APINotes.rst
index e142cfa62e5a2..4909555476772 100644
--- a/clang/docs/APINotes.rst
+++ b/clang/docs/APINotes.rst
@@ -243,6 +243,26 @@ declaration kind), all of which are optional:
         - Name: size
           SwiftSafety: safe
 
+:SwiftAttributes:
+
+  Attach arbitrary Swift attributes to a declaration.
+  This is equivalent to applying the `swift_attr("")` attribute in the header.
+
+  ::
+
+    # Mark safe globals as nonisolated to make them accessible in Swift 6
+    Globals:
+    - Name: globalVariable
+      SwiftAttributes:
+      - "nonisolated(unsafe)"
+    
+    # Apply Swift macros to C declarations on import
+    Functions:
+    - Name: cFunction
+      SwiftAttributes:
+      - "@MyModule.GenerateWrapper"
+  
+
 :Availability, AvailabilityMsg:
 
   A value of "nonswift" is equivalent to ``NS_SWIFT_UNAVAILABLE``. A value of
diff --git a/clang/include/clang/APINotes/Types.h 
b/clang/include/clang/APINotes/Types.h
index fb2b91a3e1750..ca5b35954d027 100644
--- a/clang/include/clang/APINotes/Types.h
+++ b/clang/include/clang/APINotes/Types.h
@@ -83,6 +83,9 @@ class CommonEntityInfo {
   /// Swift name of this entity.
   std::string SwiftName;
 
+  /// Swift attributes to apply to this entity.
+  std::vector<std::string> SwiftAttributes;
+
   CommonEntityInfo()
       : Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
         SwiftPrivate(0), SwiftSafetyAudited(0), SwiftSafety(0) {}
@@ -133,6 +136,9 @@ class CommonEntityInfo {
     if (SwiftName.empty())
       SwiftName = RHS.SwiftName;
 
+    // Merge SwiftAttributes
+    SwiftAttributes.insert(SwiftAttributes.end(), RHS.SwiftAttributes.begin(), 
RHS.SwiftAttributes.end());
+
     return *this;
   }
 
@@ -147,7 +153,9 @@ inline bool operator==(const CommonEntityInfo &LHS,
          LHS.SwiftPrivateSpecified == RHS.SwiftPrivateSpecified &&
          LHS.SwiftPrivate == RHS.SwiftPrivate &&
          LHS.SwiftSafetyAudited == RHS.SwiftSafetyAudited &&
-         LHS.SwiftSafety == RHS.SwiftSafety && LHS.SwiftName == RHS.SwiftName;
+         LHS.SwiftSafety == RHS.SwiftSafety &&
+         LHS.SwiftName == RHS.SwiftName &&
+         LHS.SwiftAttributes == RHS.SwiftAttributes;
 }
 
 inline bool operator!=(const CommonEntityInfo &LHS,
diff --git a/clang/lib/APINotes/APINotesFormat.h 
b/clang/lib/APINotes/APINotesFormat.h
index bb423ccb2bfaf..db57c764dddb0 100644
--- a/clang/lib/APINotes/APINotesFormat.h
+++ b/clang/lib/APINotes/APINotesFormat.h
@@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
 /// API notes file minor version number.
 ///
 /// When the format changes IN ANY WAY, this number should be incremented.
-const uint16_t VERSION_MINOR = 38; // SwiftSafety
+const uint16_t VERSION_MINOR = 39; // SwiftAttributes
 
 const uint8_t kSwiftConforms = 1;
 const uint8_t kSwiftDoesNotConform = 2;
diff --git a/clang/lib/APINotes/APINotesReader.cpp 
b/clang/lib/APINotes/APINotesReader.cpp
index 7f9bb5f12cda7..97043460c2203 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -92,6 +92,16 @@ class VersionedTableInfo {
   }
 };
 
+/// Read serialized Attribute from a SwiftAttributes sequence.
+void ReadSwiftAttribute(const uint8_t *&Data, std::string &Attribute) {
+  unsigned AttributeLength =
+      endian::readNext<uint16_t, llvm::endianness::little>(Data);
+  Attribute =
+      std::string(reinterpret_cast<const char *>(Data),
+                  reinterpret_cast<const char *>(Data) + AttributeLength);
+  Data += AttributeLength;
+}
+
 /// Read serialized CommonEntityInfo.
 void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {
   uint8_t EncodedBits = *Data++;
@@ -116,6 +126,15 @@ void ReadCommonEntityInfo(const uint8_t *&Data, 
CommonEntityInfo &Info) {
       std::string(reinterpret_cast<const char *>(Data),
                   reinterpret_cast<const char *>(Data) + SwiftNameLength);
   Data += SwiftNameLength;
+
+  unsigned NumSwiftAttributes =
+      endian::readNext<uint16_t, llvm::endianness::little>(Data);
+  while (NumSwiftAttributes > 0) {
+    std::string Attribute;
+    ReadSwiftAttribute(Data, Attribute);
+    Info.SwiftAttributes.push_back(Attribute);
+    --NumSwiftAttributes;
+  }
 }
 
 /// Read serialized CommonTypeInfo.
diff --git a/clang/lib/APINotes/APINotesTypes.cpp 
b/clang/lib/APINotes/APINotesTypes.cpp
index bff4be104c6c8..2a6e620fa902a 100644
--- a/clang/lib/APINotes/APINotesTypes.cpp
+++ b/clang/lib/APINotes/APINotesTypes.cpp
@@ -35,6 +35,13 @@ LLVM_DUMP_METHOD void 
CommonEntityInfo::dump(llvm::raw_ostream &OS) const {
   }
   if (!SwiftName.empty())
     OS << "Swift Name: " << SwiftName << ' ';
+  if (!SwiftAttributes.empty()) {
+    OS << "Swift Attrs: [";
+    for (const std::string &attr : SwiftAttributes) {
+      OS << '\"' << attr << "\", ";
+    }
+    OS << "] ";
+  }
   OS << '\n';
 }
 
diff --git a/clang/lib/APINotes/APINotesWriter.cpp 
b/clang/lib/APINotes/APINotesWriter.cpp
index 47ed93a567c0e..82ffb65e39ec6 100644
--- a/clang/lib/APINotes/APINotesWriter.cpp
+++ b/clang/lib/APINotes/APINotesWriter.cpp
@@ -502,6 +502,13 @@ class VersionedTableInfo {
   }
 };
 
+/// Emit a serialized representation of the Attribute from the SwifrAttributes 
sequence.
+void emitSwiftAttribute(raw_ostream &OS, const std::string &Attribute) {
+  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
+  writer.write<uint16_t>(Attribute.size());
+  OS.write(Attribute.c_str(), Attribute.size());
+}
+
 /// Emit a serialized representation of the common entity information.
 void emitCommonEntityInfo(raw_ostream &OS, const CommonEntityInfo &CEI) {
   llvm::support::endian::Writer writer(OS, llvm::endianness::little);
@@ -530,12 +537,26 @@ void emitCommonEntityInfo(raw_ostream &OS, const 
CommonEntityInfo &CEI) {
 
   writer.write<uint16_t>(CEI.SwiftName.size());
   OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
+
+  writer.write<uint16_t>(CEI.SwiftAttributes.size());
+  for (const auto &Attribute : CEI.SwiftAttributes)
+    emitSwiftAttribute(OS, Attribute);
+}
+
+/// Retrieve the serialized size of the given an Attribute in a 
SwiftAttributes sequence,
+/// for use in on-disk hash tables.
+unsigned getSwiftAttributeSize(const std::string &Attribute) {
+  return sizeof(uint16_t) + Attribute.size(); // length and contents
 }
 
 /// Retrieve the serialized size of the given CommonEntityInfo, for use in
 /// on-disk hash tables.
 unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) {
-  return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
+  unsigned size = 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
+  size += sizeof(uint16_t); // SwiftAttributes length
+  for (const auto &Attribute : CEI.SwiftAttributes)
+    size += getSwiftAttributeSize(Attribute);
+  return size;
 }
 
 // Retrieve the serialized size of the given CommonTypeInfo, for use
diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp 
b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index 3be528feb325e..8283e7ceef1e2 100644
--- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -79,6 +79,10 @@ template <> struct ScalarEnumerationTraits<MethodKind> {
 } // namespace yaml
 } // namespace llvm
 
+namespace {
+typedef std::vector<StringRef> SwiftAttributeSeq;
+} // namespace
+
 namespace {
 struct Param {
   int Position;
@@ -176,6 +180,7 @@ struct Method {
   StringRef ResultType;
   StringRef SwiftReturnOwnership;
   SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 
 typedef std::vector<Method> MethodsSeq;
@@ -213,6 +218,7 @@ template <> struct MappingTraits<Method> {
     IO.mapOptional("SwiftReturnOwnership", M.SwiftReturnOwnership,
                    StringRef(""));
     IO.mapOptional("SwiftSafety", M.SafetyKind, SwiftSafetyKind::None);
+    IO.mapOptional("SwiftAttributes", M.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -229,6 +235,7 @@ struct Property {
   std::optional<bool> SwiftImportAsAccessors;
   StringRef Type;
   SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 
 typedef std::vector<Property> PropertiesSeq;
@@ -251,6 +258,7 @@ template <> struct MappingTraits<Property> {
     IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors);
     IO.mapOptional("Type", P.Type, StringRef(""));
     IO.mapOptional("SwiftSafety", P.SafetyKind, SwiftSafetyKind::None);
+    IO.mapOptional("SwiftAttributes", P.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -271,6 +279,7 @@ struct Class {
   MethodsSeq Methods;
   PropertiesSeq Properties;
   SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 
 typedef std::vector<Class> ClassesSeq;
@@ -297,6 +306,7 @@ template <> struct MappingTraits<Class> {
     IO.mapOptional("Methods", C.Methods);
     IO.mapOptional("Properties", C.Properties);
     IO.mapOptional("SwiftSafety", C.SafetyKind, SwiftSafetyKind::None);
+    IO.mapOptional("SwiftAttributes", C.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -316,6 +326,7 @@ struct Function {
   StringRef ResultType;
   StringRef SwiftReturnOwnership;
   SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 
 typedef std::vector<Function> FunctionsSeq;
@@ -341,6 +352,7 @@ template <> struct MappingTraits<Function> {
     IO.mapOptional("SwiftReturnOwnership", F.SwiftReturnOwnership,
                    StringRef(""));
     IO.mapOptional("SwiftSafety", F.SafetyKind, SwiftSafetyKind::None);
+    IO.mapOptional("SwiftAttributes", F.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -355,6 +367,7 @@ struct GlobalVariable {
   StringRef SwiftName;
   StringRef Type;
   SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 
 typedef std::vector<GlobalVariable> GlobalVariablesSeq;
@@ -375,6 +388,7 @@ template <> struct MappingTraits<GlobalVariable> {
     IO.mapOptional("SwiftName", GV.SwiftName, StringRef(""));
     IO.mapOptional("Type", GV.Type, StringRef(""));
     IO.mapOptional("SwiftSafety", GV.SafetyKind, SwiftSafetyKind::None);
+    IO.mapOptional("SwiftAttributes", GV.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -449,6 +463,7 @@ struct Field {
   StringRef SwiftName;
   StringRef Type;
   SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 
 typedef std::vector<Field> FieldsSeq;
@@ -469,6 +484,7 @@ template <> struct MappingTraits<Field> {
     IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
     IO.mapOptional("Type", F.Type, StringRef(""));
     IO.mapOptional("SwiftSafety", F.SafetyKind, SwiftSafetyKind::None);
+    IO.mapOptional("SwiftAttributes", F.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -497,6 +513,7 @@ struct Tag {
   std::optional<bool> SwiftCopyable;
   std::optional<bool> SwiftEscapable;
   SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
   FunctionsSeq Methods;
   FieldsSeq Fields;
 
@@ -543,6 +560,7 @@ template <> struct MappingTraits<Tag> {
     IO.mapOptional("Fields", T.Fields);
     IO.mapOptional("Tags", T.Tags);
     IO.mapOptional("SwiftSafety", T.SafetyKind, SwiftSafetyKind::None);
+    IO.mapOptional("SwiftAttributes", T.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -559,6 +577,7 @@ struct Typedef {
   std::optional<SwiftNewTypeKind> SwiftType;
   std::optional<std::string> SwiftConformance;
   const SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 
 typedef std::vector<Typedef> TypedefsSeq;
@@ -588,6 +607,7 @@ template <> struct MappingTraits<Typedef> {
     IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
     IO.mapOptional("SwiftWrapper", T.SwiftType);
     IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
+    IO.mapOptional("SwiftAttributes", T.SwiftAttributes, SwiftAttributeSeq());
   }
 };
 } // namespace yaml
@@ -632,6 +652,7 @@ struct Namespace {
   std::optional<bool> SwiftPrivate;
   TopLevelItems Items;
   const SwiftSafetyKind SafetyKind = SwiftSafetyKind::None;
+  SwiftAttributeSeq SwiftAttributes;
 };
 } // namespace
 
@@ -647,6 +668,7 @@ template <> struct MappingTraits<Namespace> {
     IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
     IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
     IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
+    IO.mapOptional("SwiftAttributes", T.SwiftAttributes, SwiftAttributeSeq());
     mapTopLevelItems(IO, T.Items);
   }
 };
@@ -777,6 +799,15 @@ class YAMLConverter {
     }
   }
 
+  void convertSwiftAttributes(const SwiftAttributeSeq &SwiftAttributes,
+                              CommonEntityInfo &OutInfo) {
+    // Convert StringRef attributes to std::vector<std::string> in 
CommonEntityInfo
+    OutInfo.SwiftAttributes.reserve(SwiftAttributes.size());
+    for (const StringRef &A : SwiftAttributes) {
+      OutInfo.SwiftAttributes.emplace_back(A);
+    }
+  }
+
   void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo,
                      std::optional<ParamInfo> &thisOrSelf) {
     for (const auto &P : Params) {
@@ -830,6 +861,7 @@ class YAMLConverter {
     if (Common.SafetyKind != SwiftSafetyKind::None)
       Info.setSwiftSafety(Common.SafetyKind);
     Info.SwiftName = std::string(Common.SwiftName);
+    convertSwiftAttributes(Common.SwiftAttributes, Info);
   }
 
   /// Convert the common parts of a type entity from YAML.
@@ -893,6 +925,7 @@ class YAMLConverter {
     convertAvailability(Entity.Availability, VI, Entity.Name);
     VI.setSwiftPrivate(Entity.SwiftPrivate);
     VI.SwiftName = std::string(Entity.SwiftName);
+    convertSwiftAttributes(Entity.SwiftAttributes, VI);
     if (Entity.Nullability)
       VI.setNullabilityAudited(*Entity.Nullability);
     VI.setType(std::string(Entity.Type));
@@ -991,6 +1024,7 @@ class YAMLConverter {
     if (Function.SafetyKind != SwiftSafetyKind::None)
       FI.setSwiftSafety(Function.SafetyKind);
     FI.SwiftName = std::string(Function.SwiftName);
+    convertSwiftAttributes(Function.SwiftAttributes, FI);
     std::optional<ParamInfo> This;
     convertParams(Function.Params, FI, This);
     if constexpr (std::is_same_v<FuncOrMethodInfo, CXXMethodInfo>)
diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index 059eb0dd767b7..bf18f12ee203e 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -335,6 +335,11 @@ static void ProcessAPINotes(Sema &S, Decl *D,
                             ASTAllocateString(S.Context, Info.SwiftName));
         });
   }
+
+  // swift_attr
+  for (const std::string& swiftAttrName : Info.SwiftAttributes) {
+    D->addAttr(SwiftAttrAttr::Create(S.Context, swiftAttrName));
+  }
 }
 
 static void ProcessAPINotes(Sema &S, Decl *D,
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftAttributes.apinotes 
b/clang/test/APINotes/Inputs/Headers/SwiftAttributes.apinotes
new file mode 100644
index 0000000000000..926ff7c879433
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/SwiftAttributes.apinotes
@@ -0,0 +1,24 @@
+Name: SwiftAttributes
+Tags:
+- Name: IntWrapperStruct
+  SwiftAttributes: ["some Swift struct attribute"]
+  Fields:
+  - Name: value
+    SwiftAttributes: ["some Swift field attribute"]
+  Methods:
+  - Name: do_something
+    SwiftAttributes: ["some Swift struct method attribute"]
+- Name: some_ns
+  SwiftAttributes: ["some Swift namespace attribute"]
+Functions:
+- Name: some_operation
+  SwiftAttributes: [
+    "some Swift function attribute",
+    "some other Swift function attribute"
+  ]
+Globals:
+- Name: global_int
+  SwiftAttributes: ["some Swift global variable attribute"]
+Typedefs:
+- Name: int_typedef
+  SwiftAttributes: ["some Swift typedef attribute"]
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftAttributes.h 
b/clang/test/APINotes/Inputs/Headers/SwiftAttributes.h
new file mode 100644
index 0000000000000..c251f0527c41e
--- /dev/null
+++ b/clang/test/APINotes/Inputs/Headers/SwiftAttributes.h
@@ -0,0 +1,11 @@
+struct IntWrapperStruct {
+  int value;
+
+  void do_something();
+};
+
+void some_operation(IntWrapperStruct &);
+
+int global_int = 123;
+
+typedef int int_typedef;
diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap 
b/clang/test/APINotes/Inputs/Headers/module.modulemap
index bedb7d505f794..2c0939277f4e3 100644
--- a/clang/test/APINotes/Inputs/Headers/module.modulemap
+++ b/clang/test/APINotes/Inputs/Headers/module.modulemap
@@ -61,3 +61,7 @@ module SwiftImportAs {
 module SwiftReturnOwnershipForObjC {
   header "SwiftReturnOwnershipForObjC.h"
 }
+
+module SwiftAttributes {
+  header "SwiftAttributes.h"
+}
diff --git a/clang/test/APINotes/swift-attributes.cpp 
b/clang/test/APINotes/swift-attributes.cpp
new file mode 100644
index 0000000000000..0d65336415604
--- /dev/null
+++ b/clang/test/APINotes/swift-attributes.cpp
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/SwiftAttributes -fdisable-module-hash 
-fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks 
%s -x c++
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/SwiftAttributes -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter IntWrapperStruct -x c++ | FileCheck 
--check-prefix=CHECK-STRUCT %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/SwiftAttributes -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter IntWrapperStruct::value -x c++ | FileCheck 
--check-prefix=CHECK-FIELD %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/SwiftAttributes -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter IntWrapperStruct::do_something -x c++ | FileCheck 
--check-prefix=CHECK-METHOD %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/SwiftAttributes -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter some_operation -x c++ | FileCheck --check-prefix=CHECK-FUNC %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/SwiftAttributes -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter global_int -x c++ | FileCheck --check-prefix=CHECK-VAR %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps 
-fmodules-cache-path=%t/ModulesCache/SwiftAttributes -fdisable-module-hash 
-fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump 
-ast-dump-filter int_typedef -x c++ | FileCheck --check-prefix=CHECK-TYPEDEF %s
+
+#include "SwiftAttributes.h"
+
+// CHECK-STRUCT: Dumping IntWrapperStruct:
+// CHECK-STRUCT-NEXT: CXXRecordDecl {{.+}} struct IntWrapperStruct
+// CHECK-STRUCT: SwiftAttrAttr {{.+}} <<invalid sloc>> "some Swift struct 
attribute"
+
+// CHECK-FIELD: Dumping IntWrapperStruct::value:
+// CHECK-FIELD-NEXT: FieldDecl {{.+}} value
+// CHECK-FIELD: SwiftAttrAttr {{.+}} <<invalid sloc>> "some Swift field 
attribute"
+
+// CHECK-METHOD: Dumping IntWrapperStruct::do_something:
+// CHECK-METHOD-NEXT: CXXMethodDecl {{.+}} do_something
+// CHECK-METHOD: SwiftAttrAttr {{.+}} <<invalid sloc>> "some Swift struct 
method attribute"
+
+// CHECK-FUNC: Dumping some_operation:
+// CHECK-FUNC-NEXT: FunctionDecl {{.+}} some_operation
+// CHECK-FUNC: SwiftAttrAttr {{.+}} <<invalid sloc>> "some Swift function 
attribute"
+// CHECK-FUNC: SwiftAttrAttr {{.+}} <<invalid sloc>> "some other Swift 
function attribute"
+
+// CHECK-VAR: Dumping global_int:
+// CHECK-VAR-NEXT: VarDecl {{.+}} global_int
+// CHECK-VAR: SwiftAttrAttr {{.+}} <<invalid sloc>> "some Swift global 
variable attribute"
+
+// CHECK-TYPEDEF: Dumping int_typedef:
+// CHECK-TYPEDEF-NEXT: TypedefDecl {{.+}} int_typedef
+// CHECK-TYPEDEF: SwiftAttrAttr {{.+}} <<invalid sloc>> "some Swift typedef 
attribute"

``````````

</details>


https://github.com/llvm/llvm-project/pull/180382
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to