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:
parent
f2eeb3dc7b
commit
694fd1f297
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -46,3 +46,5 @@ Tags:
|
||||
SwiftName: SuccessfullyRenamedA
|
||||
- Name: RenamedAgainInAPINotesB
|
||||
SwiftName: SuccessfullyRenamedB
|
||||
- Name: AnonEnumWithTypedefName
|
||||
SwiftName: SuccessfullyRenamedC
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)'}}
|
||||
|
||||
@ -7,5 +7,5 @@ REQUIRES: shell
|
||||
|
||||
We expect only the document markers to be emitted
|
||||
|
||||
CHECK: 50d
|
||||
CHECK: 52d
|
||||
CHECK: 1d
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user