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