diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index d0236d08c98e..ec43a0def9c1 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(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 e4c45cbc09e0..add28b370bcf 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 ef6e44c51c21..f51811354eb0 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 bd73926e9d6a..7342c3f83141 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 133d504713d7..752f10264328 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 b0b777b59506..63717bda7c09 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