Skip to content

Commit 2d8697d

Browse files
evelez7daniel-grumberg
authored andcommitted
[clang][ExtractAPI] Add support for namespaces
Serialize namespaces, nested namespaces, and class relationships inside them. Depends on D157076 Reviewed By: dang Differential Revision: https://reviews.llvm.org/D158239
1 parent 6deff88 commit 2d8697d

File tree

10 files changed

+567
-61
lines changed

10 files changed

+567
-61
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ struct APIRecord {
157157
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
158158
enum RecordKind {
159159
RK_Unknown,
160+
RK_Namespace,
160161
RK_GlobalFunction,
161162
RK_GlobalFunctionTemplate,
162163
RK_GlobalFunctionTemplateSpecialization,
@@ -267,6 +268,20 @@ struct APIRecord {
267268
virtual ~APIRecord() = 0;
268269
};
269270

271+
struct NamespaceRecord : APIRecord {
272+
NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
273+
AvailabilitySet Availabilities, LinkageInfo Linkage,
274+
const DocComment &Comment, DeclarationFragments Declaration,
275+
DeclarationFragments SubHeading, bool IsFromSystemHeader)
276+
: APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availabilities),
277+
Linkage, Comment, Declaration, SubHeading,
278+
IsFromSystemHeader) {}
279+
280+
static bool classof(const APIRecord *Record) {
281+
return Record->getKind() == RK_Namespace;
282+
}
283+
};
284+
270285
/// This holds information associated with global functions.
271286
struct GlobalFunctionRecord : APIRecord {
272287
FunctionSignature Signature;
@@ -900,15 +915,17 @@ struct CXXClassRecord : APIRecord {
900915
SmallVector<std::unique_ptr<CXXFieldRecord>> Fields;
901916
SmallVector<std::unique_ptr<CXXMethodRecord>> Methods;
902917
SmallVector<SymbolReference> Bases;
918+
AccessControl Access;
903919

904920
CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
905921
AvailabilitySet Availabilities, const DocComment &Comment,
906922
DeclarationFragments Declaration,
907923
DeclarationFragments SubHeading, RecordKind Kind,
908-
bool IsFromSystemHeader)
924+
AccessControl Access, bool IsFromSystemHeader)
909925
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
910926
LinkageInfo::none(), Comment, Declaration, SubHeading,
911-
IsFromSystemHeader) {}
927+
IsFromSystemHeader),
928+
Access(Access) {}
912929

913930
static bool classof(const APIRecord *Record) {
914931
return (Record->getKind() == RK_CXXClass);
@@ -925,9 +942,9 @@ struct ClassTemplateRecord : CXXClassRecord {
925942
AvailabilitySet Availabilities, const DocComment &Comment,
926943
DeclarationFragments Declaration,
927944
DeclarationFragments SubHeading, Template Template,
928-
bool IsFromSystemHeader)
945+
AccessControl Access, bool IsFromSystemHeader)
929946
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
930-
Declaration, SubHeading, RK_ClassTemplate,
947+
Declaration, SubHeading, RK_ClassTemplate, Access,
931948
IsFromSystemHeader),
932949
Templ(Template) {}
933950

@@ -937,16 +954,14 @@ struct ClassTemplateRecord : CXXClassRecord {
937954
};
938955

939956
struct ClassTemplateSpecializationRecord : CXXClassRecord {
940-
ClassTemplateSpecializationRecord(StringRef USR, StringRef Name,
941-
PresumedLoc Loc,
942-
AvailabilitySet Availabilities,
943-
const DocComment &Comment,
944-
DeclarationFragments Declaration,
945-
DeclarationFragments SubHeading,
946-
bool IsFromSystemHeader)
957+
ClassTemplateSpecializationRecord(
958+
StringRef USR, StringRef Name, PresumedLoc Loc,
959+
AvailabilitySet Availabilities, const DocComment &Comment,
960+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
961+
AccessControl Access, bool IsFromSystemHeader)
947962
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
948963
Declaration, SubHeading, RK_ClassTemplateSpecialization,
949-
IsFromSystemHeader) {}
964+
Access, IsFromSystemHeader) {}
950965

951966
static bool classof(const APIRecord *Record) {
952967
return Record->getKind() == RK_ClassTemplateSpecialization;
@@ -959,10 +974,10 @@ struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
959974
StringRef USR, StringRef Name, PresumedLoc Loc,
960975
AvailabilitySet Availabilities, const DocComment &Comment,
961976
DeclarationFragments Declaration, DeclarationFragments SubHeading,
962-
Template Template, bool IsFromSystemHeader)
977+
Template Template, AccessControl Access, bool IsFromSystemHeader)
963978
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
964979
Declaration, SubHeading, RK_ClassTemplateSpecialization,
965-
IsFromSystemHeader),
980+
Access, IsFromSystemHeader),
966981
Templ(Template) {}
967982

968983
static bool classof(const APIRecord *Record) {
@@ -1132,6 +1147,13 @@ struct has_access<CXXMethodTemplateSpecializationRecord>
11321147
: public std::true_type {};
11331148
template <>
11341149
struct has_access<CXXFieldTemplateRecord> : public std::true_type {};
1150+
template <> struct has_access<CXXClassRecord> : public std::true_type {};
1151+
template <> struct has_access<ClassTemplateRecord> : public std::true_type {};
1152+
template <>
1153+
struct has_access<ClassTemplateSpecializationRecord> : public std::true_type {};
1154+
template <>
1155+
struct has_access<ClassTemplatePartialSpecializationRecord>
1156+
: public std::true_type {};
11351157

11361158
template <typename RecordTy> struct has_template : public std::false_type {};
11371159
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
@@ -1161,6 +1183,13 @@ struct has_function_signature<GlobalFunctionTemplateSpecializationRecord>
11611183
/// APISet holds the set of API records collected from given inputs.
11621184
class APISet {
11631185
public:
1186+
NamespaceRecord *addNamespace(APIRecord *Parent, StringRef Name,
1187+
StringRef USR, PresumedLoc Loc,
1188+
AvailabilitySet Availability,
1189+
LinkageInfo Linkage, const DocComment &Comment,
1190+
DeclarationFragments Declaration,
1191+
DeclarationFragments SubHeading,
1192+
bool IsFromSystemHeaderg);
11641193
/// Create and add a global variable record into the API set.
11651194
///
11661195
/// Note: the caller is responsible for keeping the StringRef \p Name and
@@ -1278,31 +1307,33 @@ class APISet {
12781307
DeclarationFragments Declaration, DeclarationFragments SubHeading,
12791308
AccessControl Access, Template Template, bool IsFromSystemHeader);
12801309

1281-
CXXClassRecord *
1282-
addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc,
1283-
AvailabilitySet Availability, const DocComment &Comment,
1284-
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1285-
APIRecord::RecordKind Kind, bool IsFromSystemHeader);
1310+
CXXClassRecord *addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
1311+
PresumedLoc Loc, AvailabilitySet Availability,
1312+
const DocComment &Comment,
1313+
DeclarationFragments Declaration,
1314+
DeclarationFragments SubHeading,
1315+
APIRecord::RecordKind Kind, AccessControl Access,
1316+
bool IsFromSystemHeader);
12861317

12871318
ClassTemplateRecord *
1288-
addClassTemplate(StringRef Name, StringRef USR, PresumedLoc Loc,
1289-
AvailabilitySet Availability, const DocComment &Comment,
1290-
DeclarationFragments Declaration,
1319+
addClassTemplate(APIRecord *Parent, StringRef Name, StringRef USR,
1320+
PresumedLoc Loc, AvailabilitySet Availability,
1321+
const DocComment &Comment, DeclarationFragments Declaration,
12911322
DeclarationFragments SubHeading, Template Template,
1292-
bool IsFromSystemHeader);
1323+
AccessControl Access, bool IsFromSystemHeader);
12931324

12941325
ClassTemplateSpecializationRecord *addClassTemplateSpecialization(
1295-
StringRef Name, StringRef USR, PresumedLoc Loc,
1326+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
12961327
AvailabilitySet Availability, const DocComment &Comment,
12971328
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1298-
bool IsFromSystemHeader);
1329+
AccessControl Access, bool IsFromSystemHeader);
12991330

13001331
ClassTemplatePartialSpecializationRecord *
13011332
addClassTemplatePartialSpecialization(
1302-
StringRef Name, StringRef USR, PresumedLoc Loc,
1333+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
13031334
AvailabilitySet Availability, const DocComment &Comment,
13041335
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1305-
Template Template, bool IsFromSystemHeader);
1336+
Template Template, AccessControl Access, bool IsFromSystemHeader);
13061337

13071338
GlobalVariableTemplateSpecializationRecord *
13081339
addGlobalVariableTemplateSpecialization(
@@ -1477,6 +1508,7 @@ class APISet {
14771508
/// Get the language used by the APIs.
14781509
Language getLanguage() const { return Lang; }
14791510

1511+
const RecordMap<NamespaceRecord> &getNamespaces() const { return Namespaces; }
14801512
const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
14811513
return GlobalFunctions;
14821514
}
@@ -1590,6 +1622,7 @@ class APISet {
15901622
const Language Lang;
15911623

15921624
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
1625+
RecordMap<NamespaceRecord> Namespaces;
15931626
RecordMap<GlobalFunctionRecord> GlobalFunctions;
15941627
RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
15951628
RecordMap<GlobalFunctionTemplateSpecializationRecord>

clang/include/clang/ExtractAPI/DeclarationFragments.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,17 +258,19 @@ class DeclarationFragmentsBuilder {
258258
static AccessControl getAccessControl(const Decl *Decl) {
259259
switch (Decl->getAccess()) {
260260
case AS_public:
261+
case AS_none:
261262
return AccessControl("public");
262263
case AS_private:
263264
return AccessControl("private");
264265
case AS_protected:
265266
return AccessControl("protected");
266-
case AS_none:
267-
return AccessControl("none");
268267
}
269268
llvm_unreachable("Unhandled access control");
270269
}
271270

271+
static DeclarationFragments
272+
getFragmentsForNamespace(const NamespaceDecl *Decl);
273+
272274
/// Build DeclarationFragments for a variable declaration VarDecl.
273275
static DeclarationFragments getFragmentsForVar(const VarDecl *);
274276

clang/include/clang/ExtractAPI/ExtractAPIVisitor.h

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
7474

7575
bool WalkUpFromFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
7676

77+
bool WalkUpFromNamespaceDecl(const NamespaceDecl *Decl);
78+
79+
bool VisitNamespaceDecl(const NamespaceDecl *Decl);
80+
7781
bool VisitRecordDecl(const RecordDecl *Decl);
7882

7983
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
@@ -187,6 +191,17 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
187191
}
188192
return Bases;
189193
}
194+
195+
APIRecord *determineParentRecord(const DeclContext *Context) {
196+
SmallString<128> ParentUSR;
197+
if (Context->getDeclKind() == Decl::TranslationUnit)
198+
return nullptr;
199+
200+
index::generateUSRForDecl(dyn_cast<Decl>(Context), ParentUSR);
201+
202+
APIRecord *Parent = API.findRecordForUSR(ParentUSR);
203+
return Parent;
204+
}
190205
};
191206

192207
template <typename T>
@@ -447,6 +462,44 @@ bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionTemplateDecl(
447462
return true;
448463
}
449464

465+
template <typename Derived>
466+
bool ExtractAPIVisitorBase<Derived>::WalkUpFromNamespaceDecl(
467+
const NamespaceDecl *Decl) {
468+
getDerivedExtractAPIVisitor().VisitNamespaceDecl(Decl);
469+
return true;
470+
}
471+
472+
template <typename Derived>
473+
bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl(
474+
const NamespaceDecl *Decl) {
475+
476+
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
477+
return true;
478+
if (Decl->isAnonymousNamespace())
479+
return true;
480+
StringRef Name = Decl->getName();
481+
StringRef USR = API.recordUSR(Decl);
482+
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
483+
PresumedLoc Loc =
484+
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
485+
DocComment Comment;
486+
if (auto *RawComment =
487+
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
488+
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
489+
Context.getDiagnostics());
490+
491+
// Build declaration fragments and sub-heading for the struct.
492+
DeclarationFragments Declaration =
493+
DeclarationFragmentsBuilder::getFragmentsForNamespace(Decl);
494+
DeclarationFragments SubHeading =
495+
DeclarationFragmentsBuilder::getSubHeading(Decl);
496+
APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
497+
API.addNamespace(Parent, Name, USR, Loc, AvailabilitySet(Decl), Linkage,
498+
Comment, Declaration, SubHeading, isInSystemHeader(Decl));
499+
500+
return true;
501+
}
502+
450503
template <typename Derived>
451504
bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
452505
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
@@ -512,7 +565,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
512565
Kind = APIRecord::RecordKind::RK_Struct;
513566
else
514567
Kind = APIRecord::RecordKind::RK_CXXClass;
568+
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
515569

570+
APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
516571
CXXClassRecord *CXXClassRecord;
517572
if (Decl->getDescribedClassTemplate()) {
518573
// Inject template fragments before class fragments.
@@ -521,12 +576,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
521576
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
522577
Decl->getDescribedClassTemplate()));
523578
CXXClassRecord = API.addClassTemplate(
524-
Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading,
525-
Template(Decl->getDescribedClassTemplate()), isInSystemHeader(Decl));
579+
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
580+
SubHeading, Template(Decl->getDescribedClassTemplate()), Access,
581+
isInSystemHeader(Decl));
526582
} else
527-
CXXClassRecord =
528-
API.addCXXClass(Name, USR, Loc, AvailabilitySet(Decl), Comment,
529-
Declaration, SubHeading, Kind, isInSystemHeader(Decl));
583+
CXXClassRecord = API.addCXXClass(
584+
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
585+
SubHeading, Kind, Access, isInSystemHeader(Decl));
530586

531587
CXXClassRecord->Bases = getBases(Decl);
532588

@@ -708,8 +764,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
708764
DeclarationFragments SubHeading =
709765
DeclarationFragmentsBuilder::getSubHeading(Decl);
710766

767+
APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
711768
auto *ClassTemplateSpecializationRecord = API.addClassTemplateSpecialization(
712-
Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading,
769+
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
770+
SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl),
713771
isInSystemHeader(Decl));
714772

715773
ClassTemplateSpecializationRecord->Bases = getBases(Decl);
@@ -738,10 +796,13 @@ bool ExtractAPIVisitorBase<Derived>::
738796
DeclarationFragments SubHeading =
739797
DeclarationFragmentsBuilder::getSubHeading(Decl);
740798

799+
APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
741800
auto *ClassTemplatePartialSpecRecord =
742801
API.addClassTemplatePartialSpecialization(
743-
Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
744-
SubHeading, Template(Decl), isInSystemHeader(Decl));
802+
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
803+
SubHeading, Template(Decl),
804+
DeclarationFragmentsBuilder::getAccessControl(Decl),
805+
isInSystemHeader(Decl));
745806

746807
ClassTemplatePartialSpecRecord->Bases = getBases(Decl);
747808

clang/include/clang/ExtractAPI/Serialization/SerializerBase.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ namespace extractapi {
2323
template <typename Derived> class APISetVisitor {
2424
public:
2525
void traverseAPISet() {
26+
getDerived()->traverseNamespaces();
27+
2628
getDerived()->traverseGlobalVariableRecords();
2729

2830
getDerived()->traverseGlobalFunctionRecords();
@@ -74,6 +76,11 @@ template <typename Derived> class APISetVisitor {
7476
getDerived()->traverseTypedefRecords();
7577
}
7678

79+
void traverseNamespaces() {
80+
for (const auto &Namespace : API.getNamespaces())
81+
getDerived()->visitNamespaceRecord(*Namespace.second);
82+
}
83+
7784
void traverseGlobalFunctionRecords() {
7885
for (const auto &GlobalFunction : API.getGlobalFunctions())
7986
getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second);
@@ -213,6 +220,8 @@ template <typename Derived> class APISetVisitor {
213220
getDerived()->visitTypedefRecord(*Typedef.second);
214221
}
215222

223+
void visitNamespaceRecord(const NamespaceRecord &Record){};
224+
216225
/// Visit a global function record.
217226
void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){};
218227

clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
152152
SymbolGraphSerializerOption Options;
153153

154154
public:
155+
void visitNamespaceRecord(const NamespaceRecord &Record);
156+
155157
/// Visit a global function record.
156158
void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record);
157159

0 commit comments

Comments
 (0)