Skip to content

Commit 2bcbe40

Browse files
[clang][ExtractAPI] Fix handling of anonymous TagDecls (#87772)
This changes the handling of anonymous TagDecls to the following rules: - If the TagDecl is embedded in the declaration for some VarDecl (this is the only possibility for RecordDecls), then pretend the child decls belong to the VarDecl - If it's an EnumDecl proceed as we did previously, i.e., embed it in the enclosing DeclContext. Additionally this fixes a few issues with declaration fragments not consistently including "{ ... }" for anonymous TagDecls. To make testing these additions easier this patch fixes some text declaration fragments merging issues and updates tests accordingly. rdar://121436298
1 parent d3f6c2c commit 2bcbe40

File tree

14 files changed

+444
-569
lines changed

14 files changed

+444
-569
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 91 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,20 @@ struct APIRecord {
208208
RK_ClassTemplate,
209209
RK_ClassTemplateSpecialization,
210210
RK_ClassTemplatePartialSpecialization,
211-
RK_LastRecordContext,
212-
RK_GlobalFunction,
213-
RK_GlobalFunctionTemplate,
214-
RK_GlobalFunctionTemplateSpecialization,
211+
RK_StructField,
212+
RK_UnionField,
213+
RK_CXXField,
214+
RK_StaticField,
215+
RK_CXXFieldTemplate,
215216
RK_GlobalVariable,
216217
RK_GlobalVariableTemplate,
217218
RK_GlobalVariableTemplateSpecialization,
218219
RK_GlobalVariableTemplatePartialSpecialization,
220+
RK_LastRecordContext,
221+
RK_GlobalFunction,
222+
RK_GlobalFunctionTemplate,
223+
RK_GlobalFunctionTemplateSpecialization,
219224
RK_EnumConstant,
220-
RK_StructField,
221-
RK_UnionField,
222-
RK_StaticField,
223-
RK_CXXField,
224-
RK_CXXFieldTemplate,
225225
RK_Concept,
226226
RK_CXXStaticMethod,
227227
RK_CXXInstanceMethod,
@@ -321,6 +321,10 @@ class RecordContext {
321321

322322
RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}
323323

324+
/// Append \p Other children chain into ours and empty out Other's record
325+
/// chain.
326+
void stealRecordChain(RecordContext &Other);
327+
324328
APIRecord::RecordKind getKind() const { return Kind; }
325329

326330
struct record_iterator {
@@ -370,6 +374,7 @@ class RecordContext {
370374
APIRecord::RecordKind Kind;
371375
mutable APIRecord *First = nullptr;
372376
mutable APIRecord *Last = nullptr;
377+
bool IsWellFormed() const;
373378

374379
protected:
375380
friend class APISet;
@@ -475,31 +480,36 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
475480
};
476481

477482
/// This holds information associated with global functions.
478-
struct GlobalVariableRecord : APIRecord {
483+
struct GlobalVariableRecord : APIRecord, RecordContext {
479484
GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
480485
PresumedLoc Loc, AvailabilityInfo Availability,
481486
LinkageInfo Linkage, const DocComment &Comment,
482487
DeclarationFragments Declaration,
483488
DeclarationFragments SubHeading, bool IsFromSystemHeader)
484489
: APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
485490
std::move(Availability), Linkage, Comment, Declaration,
486-
SubHeading, IsFromSystemHeader) {}
491+
SubHeading, IsFromSystemHeader),
492+
RecordContext(RK_GlobalVariable) {}
487493

488494
GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
489-
SymbolReference Parent,
490-
491-
PresumedLoc Loc, AvailabilityInfo Availability,
492-
LinkageInfo Linkage, const DocComment &Comment,
495+
SymbolReference Parent, PresumedLoc Loc,
496+
AvailabilityInfo Availability, LinkageInfo Linkage,
497+
const DocComment &Comment,
493498
DeclarationFragments Declaration,
494499
DeclarationFragments SubHeading, bool IsFromSystemHeader)
495500
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
496501
Linkage, Comment, Declaration, SubHeading,
497-
IsFromSystemHeader) {}
502+
IsFromSystemHeader),
503+
RecordContext(Kind) {}
498504

499505
static bool classof(const APIRecord *Record) {
500506
return classofKind(Record->getKind());
501507
}
502-
static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; }
508+
static bool classofKind(RecordKind K) {
509+
return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
510+
K == RK_GlobalVariableTemplateSpecialization ||
511+
K == RK_GlobalVariableTemplatePartialSpecialization;
512+
}
503513

504514
private:
505515
virtual void anchor();
@@ -591,36 +601,64 @@ struct EnumConstantRecord : APIRecord {
591601
virtual void anchor();
592602
};
593603

604+
struct TagRecord : APIRecord, RecordContext {
605+
TagRecord(RecordKind Kind, StringRef USR, StringRef Name,
606+
SymbolReference Parent, PresumedLoc Loc,
607+
AvailabilityInfo Availability, const DocComment &Comment,
608+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
609+
bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator,
610+
AccessControl Access = AccessControl())
611+
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
612+
LinkageInfo::none(), Comment, Declaration, SubHeading,
613+
IsFromSystemHeader, std::move(Access)),
614+
RecordContext(Kind),
615+
IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){};
616+
617+
static bool classof(const APIRecord *Record) {
618+
return classofKind(Record->getKind());
619+
}
620+
static bool classofKind(RecordKind K) {
621+
return K == RK_Struct || K == RK_Union || K == RK_Enum;
622+
}
623+
624+
bool IsEmbeddedInVarDeclarator;
625+
626+
virtual ~TagRecord() = 0;
627+
};
628+
594629
/// This holds information associated with enums.
595-
struct EnumRecord : APIRecord, RecordContext {
630+
struct EnumRecord : TagRecord {
596631
EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
597632
PresumedLoc Loc, AvailabilityInfo Availability,
598633
const DocComment &Comment, DeclarationFragments Declaration,
599-
DeclarationFragments SubHeading, bool IsFromSystemHeader)
600-
: APIRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
601-
LinkageInfo::none(), Comment, Declaration, SubHeading,
602-
IsFromSystemHeader),
603-
RecordContext(RK_Enum) {}
634+
DeclarationFragments SubHeading, bool IsFromSystemHeader,
635+
bool IsEmbeddedInVarDeclarator,
636+
AccessControl Access = AccessControl())
637+
: TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
638+
Comment, Declaration, SubHeading, IsFromSystemHeader,
639+
IsEmbeddedInVarDeclarator, std::move(Access)) {}
604640

605641
static bool classof(const APIRecord *Record) {
606642
return classofKind(Record->getKind());
607643
}
644+
608645
static bool classofKind(RecordKind K) { return K == RK_Enum; }
609646

610647
private:
611648
virtual void anchor();
612649
};
613650

614651
/// This holds information associated with struct or union fields fields.
615-
struct RecordFieldRecord : APIRecord {
652+
struct RecordFieldRecord : APIRecord, RecordContext {
616653
RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
617654
SymbolReference Parent, PresumedLoc Loc,
618655
AvailabilityInfo Availability, const DocComment &Comment,
619656
DeclarationFragments Declaration,
620657
DeclarationFragments SubHeading, bool IsFromSystemHeader)
621658
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
622659
LinkageInfo::none(), Comment, Declaration, SubHeading,
623-
IsFromSystemHeader) {}
660+
IsFromSystemHeader),
661+
RecordContext(Kind) {}
624662

625663
static bool classof(const APIRecord *Record) {
626664
return classofKind(Record->getKind());
@@ -633,16 +671,17 @@ struct RecordFieldRecord : APIRecord {
633671
};
634672

635673
/// This holds information associated with structs and unions.
636-
struct RecordRecord : APIRecord, RecordContext {
674+
struct RecordRecord : TagRecord {
637675
RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
638676
SymbolReference Parent, PresumedLoc Loc,
639677
AvailabilityInfo Availability, const DocComment &Comment,
640678
DeclarationFragments Declaration,
641-
DeclarationFragments SubHeading, bool IsFromSystemHeader)
642-
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
643-
LinkageInfo::none(), Comment, Declaration, SubHeading,
644-
IsFromSystemHeader),
645-
RecordContext(Kind) {}
679+
DeclarationFragments SubHeading, bool IsFromSystemHeader,
680+
bool IsEmbeddedInVarDeclarator,
681+
AccessControl Access = AccessControl())
682+
: TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
683+
Comment, Declaration, SubHeading, IsFromSystemHeader,
684+
IsEmbeddedInVarDeclarator, std::move(Access)) {}
646685

647686
static bool classof(const APIRecord *Record) {
648687
return classofKind(Record->getKind());
@@ -651,6 +690,8 @@ struct RecordRecord : APIRecord, RecordContext {
651690
return K == RK_Struct || K == RK_Union;
652691
}
653692

693+
bool isAnonymousWithNoTypedef() { return Name.empty(); }
694+
654695
virtual ~RecordRecord() = 0;
655696
};
656697

@@ -676,9 +717,11 @@ struct StructRecord : RecordRecord {
676717
StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
677718
PresumedLoc Loc, AvailabilityInfo Availability,
678719
const DocComment &Comment, DeclarationFragments Declaration,
679-
DeclarationFragments SubHeading, bool IsFromSystemHeader)
720+
DeclarationFragments SubHeading, bool IsFromSystemHeader,
721+
bool IsEmbeddedInVarDeclarator)
680722
: RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
681-
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
723+
Comment, Declaration, SubHeading, IsFromSystemHeader,
724+
IsEmbeddedInVarDeclarator) {}
682725

683726
static bool classof(const APIRecord *Record) {
684727
return classofKind(Record->getKind());
@@ -711,9 +754,11 @@ struct UnionRecord : RecordRecord {
711754
UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
712755
PresumedLoc Loc, AvailabilityInfo Availability,
713756
const DocComment &Comment, DeclarationFragments Declaration,
714-
DeclarationFragments SubHeading, bool IsFromSystemHeader)
757+
DeclarationFragments SubHeading, bool IsFromSystemHeader,
758+
bool IsEmbeddedInVarDeclarator)
715759
: RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
716-
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
760+
Comment, Declaration, SubHeading, IsFromSystemHeader,
761+
IsEmbeddedInVarDeclarator) {}
717762

718763
static bool classof(const APIRecord *Record) {
719764
return classofKind(Record->getKind());
@@ -724,15 +769,16 @@ struct UnionRecord : RecordRecord {
724769
virtual void anchor();
725770
};
726771

727-
struct CXXFieldRecord : APIRecord {
772+
struct CXXFieldRecord : APIRecord, RecordContext {
728773
CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
729774
PresumedLoc Loc, AvailabilityInfo Availability,
730775
const DocComment &Comment, DeclarationFragments Declaration,
731776
DeclarationFragments SubHeading, AccessControl Access,
732777
bool IsFromSystemHeader)
733778
: APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
734779
LinkageInfo::none(), Comment, Declaration, SubHeading,
735-
IsFromSystemHeader, std::move(Access)) {}
780+
IsFromSystemHeader, std::move(Access)),
781+
RecordContext(RK_CXXField) {}
736782

737783
CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
738784
SymbolReference Parent, PresumedLoc Loc,
@@ -742,7 +788,8 @@ struct CXXFieldRecord : APIRecord {
742788
bool IsFromSystemHeader)
743789
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
744790
LinkageInfo::none(), Comment, Declaration, SubHeading,
745-
IsFromSystemHeader, std::move(Access)) {}
791+
IsFromSystemHeader, std::move(Access)),
792+
RecordContext(Kind) {}
746793

747794
static bool classof(const APIRecord *Record) {
748795
return classofKind(Record->getKind());
@@ -1118,18 +1165,18 @@ struct ObjCContainerRecord : APIRecord, RecordContext {
11181165
virtual ~ObjCContainerRecord() = 0;
11191166
};
11201167

1121-
struct CXXClassRecord : APIRecord, RecordContext {
1168+
struct CXXClassRecord : RecordRecord {
11221169
SmallVector<SymbolReference> Bases;
11231170

11241171
CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
11251172
PresumedLoc Loc, AvailabilityInfo Availability,
11261173
const DocComment &Comment, DeclarationFragments Declaration,
11271174
DeclarationFragments SubHeading, RecordKind Kind,
1128-
AccessControl Access, bool IsFromSystemHeader)
1129-
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1130-
LinkageInfo::none(), Comment, Declaration, SubHeading,
1131-
IsFromSystemHeader, std::move(Access)),
1132-
RecordContext(Kind) {}
1175+
AccessControl Access, bool IsFromSystemHeader,
1176+
bool IsEmbeddedInVarDeclarator = false)
1177+
: RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1178+
Comment, Declaration, SubHeading, IsFromSystemHeader,
1179+
IsEmbeddedInVarDeclarator, std::move(Access)) {}
11331180

11341181
static bool classof(const APIRecord *Record) {
11351182
return classofKind(Record->getKind());

clang/include/clang/ExtractAPI/APIRecords.inc

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord,
3535
CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord,
3636
GlobalVariableRecord,
3737
RK_GlobalVariableTemplatePartialSpecialization)
38+
ABSTRACT_RECORD(TagRecord, APIRecord)
3839
CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant)
39-
CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum)
40+
CONCRETE_RECORD(EnumRecord, TagRecord, RK_Enum)
4041
ABSTRACT_RECORD(RecordFieldRecord, APIRecord)
41-
ABSTRACT_RECORD(RecordRecord, APIRecord)
42+
ABSTRACT_RECORD(RecordRecord, TagRecord)
4243
CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField)
4344
CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct)
4445
CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField)
@@ -99,5 +100,16 @@ RECORD_CONTEXT(ClassTemplateSpecializationRecord,
99100
RK_ClassTemplateSpecialization)
100101
RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord,
101102
RK_ClassTemplatePartialSpecialization)
103+
RECORD_CONTEXT(StructFieldRecord, RK_StructField)
104+
RECORD_CONTEXT(UnionFieldRecord, RK_UnionField)
105+
RECORD_CONTEXT(CXXFieldRecord, RK_CXXField)
106+
RECORD_CONTEXT(StaticFieldRecord, RK_StaticField)
107+
RECORD_CONTEXT(CXXFieldTemplateRecord, RK_CXXFieldTemplate)
108+
RECORD_CONTEXT(GlobalVariableRecord, RK_GlobalVariable)
109+
RECORD_CONTEXT(GlobalVariableTemplateRecord, RK_GlobalVariableTemplate)
110+
RECORD_CONTEXT(GlobalVariableTemplateSpecializationRecord,
111+
RK_GlobalVariableTemplateSpecialization)
112+
RECORD_CONTEXT(GlobalVariableTemplatePartialSpecializationRecord,
113+
RK_GlobalVariableTemplatePartialSpecialization)
102114

103115
#undef RECORD_CONTEXT

0 commit comments

Comments
 (0)