https://github.com/DougGregor created 
https://github.com/llvm/llvm-project/pull/110768

It is common practice in C to declare anonymous tags that are immediately given 
a typedef name, e.g.,

    typedef enum { ... } MyType;

At present, one can only express API notes on the typedef. However, that 
excludes the possibility of tag-specific notes like EnumExtensibility. For 
these anonymous declarations, process API notes using the typedef name as the 
tag name, so that one can add API notes to `MyType` via the `Tags` section.

>From d4d03b059d46b386648781ea0eeea17dfcca7c38 Mon Sep 17 00:00:00 2001
From: Doug Gregor <dgre...@apple.com>
Date: Tue, 12 Dec 2023 14:09:28 -0800
Subject: [PATCH] Allow tag-based API notes on anonymous tag decls with typedef
 names

It is common practice in C to declare anonymous tags that are
immediately given a typedef name, e.g.,

    typedef enum { ... } MyType;

At present, one can only express API notes on the typedef. However, that
excludes the possibility of tag-specific notes like EnumExtensibility.
For these anonymous declarations, process API notes using the typedef
name as the tag name, so that one can add API notes to `MyType` via
the `Tags` section.
---
 clang/lib/Sema/SemaAPINotes.cpp                        | 10 +++++++++-
 clang/lib/Sema/SemaDecl.cpp                            |  3 +++
 .../SimpleKit.framework/Headers/SimpleKit.apinotes     |  2 ++
 .../Frameworks/SimpleKit.framework/Headers/SimpleKit.h |  4 ++++
 clang/test/APINotes/types.m                            |  3 +++
 clang/test/APINotes/yaml-roundtrip-2.test              |  2 +-
 6 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp
index d0236d08c98e68..ec43a0def9c1e6 100644
--- a/clang/lib/Sema/SemaAPINotes.cpp
+++ b/clang/lib/Sema/SemaAPINotes.cpp
@@ -913,7 +913,15 @@ void Sema::ProcessAPINotes(Decl *D) {
 
     // Tags
     if (auto Tag = dyn_cast<TagDecl>(D)) {
-      std::string LookupName = Tag->getName().str();
+      // Determine the name of the entity to search for. If this is an
+      // anonymous tag that gets its linked name from a typedef, look for the
+      // typedef name. This allows tag-specific information to be added
+      // to the declaration.
+      std::string LookupName;
+      if (auto typedefName = Tag->getTypedefNameForAnonDecl())
+        LookupName = typedefName->getName().str();
+      else
+        LookupName = Tag->getName().str();
 
       // Use the source location to discern if this Tag is an OPTIONS macro.
       // For now we would like to limit this trick of looking up the APINote 
tag
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0e536f71a2f70d..92c85313d67cdd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4974,6 +4974,9 @@ void Sema::setTagNameForLinkagePurposes(TagDecl 
*TagFromDeclSpec,
 
   // Otherwise, set this as the anon-decl typedef for the tag.
   TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD);
+
+  // Now that we have a name for the tag, process API notes again.
+  ProcessAPINotes(TagFromDeclSpec);
 }
 
 static unsigned GetDiagnosticTypeSpecifierID(const DeclSpec &DS) {
diff --git 
a/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.apinotes
 
b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.apinotes
index ef6e44c51c21c7..f51811354eb00b 100644
--- 
a/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.apinotes
+++ 
b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.apinotes
@@ -46,3 +46,5 @@ Tags:
     SwiftName:       SuccessfullyRenamedA
   - Name:            RenamedAgainInAPINotesB
     SwiftName:       SuccessfullyRenamedB
+  - Name:            AnonEnumWithTypedefName
+    SwiftName:       SuccessfullyRenamedC
diff --git 
a/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.h 
b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.h
index bd73926e9d6af4..7342c3f83141bb 100644
--- 
a/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.h
+++ 
b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Headers/SimpleKit.h
@@ -27,3 +27,7 @@ void *getCFAuditedToNone_DUMP(void);
 - (id)getOwnedToUnowned __attribute__((__ns_returns_retained__));
 - (id)getUnownedToOwned __attribute__((__ns_returns_not_retained__));
 @end
+
+typedef enum {
+  kConstantInAnonEnum
+} AnonEnumWithTypedefName;
diff --git a/clang/test/APINotes/types.m b/clang/test/APINotes/types.m
index 133d504713d76c..752f1026432844 100644
--- a/clang/test/APINotes/types.m
+++ b/clang/test/APINotes/types.m
@@ -7,6 +7,9 @@
 
 // CHECK: struct __attribute__((swift_name("SuccessfullyRenamedA"))) 
RenamedAgainInAPINotesA {
 // CHECK: struct __attribute__((swift_name("SuccessfullyRenamedB"))) 
RenamedAgainInAPINotesB {
+// CHECK: typedef enum __attribute__((swift_name("SuccessfullyRenamedC"))) {
+// CHECK-NEXT: kConstantInAnonEnum
+// CHECK-NEXT: } AnonEnumWithTypedefName
 
 void test(OverriddenTypes *overridden) {
   int *ip1 = global_int_ptr; // expected-warning{{incompatible pointer types 
initializing 'int *' with an expression of type 'double (*)(int, int)'}}
diff --git a/clang/test/APINotes/yaml-roundtrip-2.test 
b/clang/test/APINotes/yaml-roundtrip-2.test
index b0b777b595060d..63717bda7c0991 100644
--- a/clang/test/APINotes/yaml-roundtrip-2.test
+++ b/clang/test/APINotes/yaml-roundtrip-2.test
@@ -7,5 +7,5 @@ REQUIRES: shell
 
 We expect only the document markers to be emitted
 
-CHECK: 50d
+CHECK: 52d
 CHECK: 1d

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to