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.
This commit is contained in:
Doug Gregor 2024-10-02 10:21:23 -07:00 committed by GitHub
parent f2eeb3dc7b
commit 694fd1f297
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 22 additions and 2 deletions

View File

@ -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

View File

@ -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) {

View File

@ -46,3 +46,5 @@ Tags:
SwiftName: SuccessfullyRenamedA
- Name: RenamedAgainInAPINotesB
SwiftName: SuccessfullyRenamedB
- Name: AnonEnumWithTypedefName
SwiftName: SuccessfullyRenamedC

View File

@ -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;

View File

@ -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)'}}

View File

@ -7,5 +7,5 @@ REQUIRES: shell
We expect only the document markers to be emitted
CHECK: 50d
CHECK: 52d
CHECK: 1d