Skip to content

Commit 08f034f

Browse files
committed
[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 62020a3 commit 08f034f

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,
@@ -271,6 +272,20 @@ struct APIRecord {
271272
virtual ~APIRecord() = 0;
272273
};
273274

275+
struct NamespaceRecord : APIRecord {
276+
NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
277+
AvailabilitySet Availabilities, LinkageInfo Linkage,
278+
const DocComment &Comment, DeclarationFragments Declaration,
279+
DeclarationFragments SubHeading, bool IsFromSystemHeader)
280+
: APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availabilities),
281+
Linkage, Comment, Declaration, SubHeading,
282+
IsFromSystemHeader) {}
283+
284+
static bool classof(const APIRecord *Record) {
285+
return Record->getKind() == RK_Namespace;
286+
}
287+
};
288+
274289
/// This holds information associated with global functions.
275290
struct GlobalFunctionRecord : APIRecord {
276291
FunctionSignature Signature;
@@ -904,15 +919,17 @@ struct CXXClassRecord : APIRecord {
904919
SmallVector<std::unique_ptr<CXXFieldRecord>> Fields;
905920
SmallVector<std::unique_ptr<CXXMethodRecord>> Methods;
906921
SmallVector<SymbolReference> Bases;
922+
AccessControl Access;
907923

908924
CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
909925
AvailabilitySet Availabilities, const DocComment &Comment,
910926
DeclarationFragments Declaration,
911927
DeclarationFragments SubHeading, RecordKind Kind,
912-
bool IsFromSystemHeader)
928+
AccessControl Access, bool IsFromSystemHeader)
913929
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
914930
LinkageInfo::none(), Comment, Declaration, SubHeading,
915-
IsFromSystemHeader) {}
931+
IsFromSystemHeader),
932+
Access(Access) {}
916933

917934
static bool classof(const APIRecord *Record) {
918935
return (Record->getKind() == RK_CXXClass);
@@ -929,9 +946,9 @@ struct ClassTemplateRecord : CXXClassRecord {
929946
AvailabilitySet Availabilities, const DocComment &Comment,
930947
DeclarationFragments Declaration,
931948
DeclarationFragments SubHeading, Template Template,
932-
bool IsFromSystemHeader)
949+
AccessControl Access, bool IsFromSystemHeader)
933950
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
934-
Declaration, SubHeading, RK_ClassTemplate,
951+
Declaration, SubHeading, RK_ClassTemplate, Access,
935952
IsFromSystemHeader),
936953
Templ(Template) {}
937954

@@ -941,16 +958,14 @@ struct ClassTemplateRecord : CXXClassRecord {
941958
};
942959

943960
struct ClassTemplateSpecializationRecord : CXXClassRecord {
944-
ClassTemplateSpecializationRecord(StringRef USR, StringRef Name,
945-
PresumedLoc Loc,
946-
AvailabilitySet Availabilities,
947-
const DocComment &Comment,
948-
DeclarationFragments Declaration,
949-
DeclarationFragments SubHeading,
950-
bool IsFromSystemHeader)
961+
ClassTemplateSpecializationRecord(
962+
StringRef USR, StringRef Name, PresumedLoc Loc,
963+
AvailabilitySet Availabilities, const DocComment &Comment,
964+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
965+
AccessControl Access, bool IsFromSystemHeader)
951966
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
952967
Declaration, SubHeading, RK_ClassTemplateSpecialization,
953-
IsFromSystemHeader) {}
968+
Access, IsFromSystemHeader) {}
954969

955970
static bool classof(const APIRecord *Record) {
956971
return Record->getKind() == RK_ClassTemplateSpecialization;
@@ -963,10 +978,10 @@ struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
963978
StringRef USR, StringRef Name, PresumedLoc Loc,
964979
AvailabilitySet Availabilities, const DocComment &Comment,
965980
DeclarationFragments Declaration, DeclarationFragments SubHeading,
966-
Template Template, bool IsFromSystemHeader)
981+
Template Template, AccessControl Access, bool IsFromSystemHeader)
967982
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
968983
Declaration, SubHeading, RK_ClassTemplateSpecialization,
969-
IsFromSystemHeader),
984+
Access, IsFromSystemHeader),
970985
Templ(Template) {}
971986

972987
static bool classof(const APIRecord *Record) {
@@ -1138,6 +1153,13 @@ struct has_access<CXXMethodTemplateSpecializationRecord>
11381153
: public std::true_type {};
11391154
template <>
11401155
struct has_access<CXXFieldTemplateRecord> : public std::true_type {};
1156+
template <> struct has_access<CXXClassRecord> : public std::true_type {};
1157+
template <> struct has_access<ClassTemplateRecord> : public std::true_type {};
1158+
template <>
1159+
struct has_access<ClassTemplateSpecializationRecord> : public std::true_type {};
1160+
template <>
1161+
struct has_access<ClassTemplatePartialSpecializationRecord>
1162+
: public std::true_type {};
11411163

11421164
template <typename RecordTy> struct has_template : public std::false_type {};
11431165
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
@@ -1167,6 +1189,13 @@ struct has_function_signature<GlobalFunctionTemplateSpecializationRecord>
11671189
/// APISet holds the set of API records collected from given inputs.
11681190
class APISet {
11691191
public:
1192+
NamespaceRecord *addNamespace(APIRecord *Parent, StringRef Name,
1193+
StringRef USR, PresumedLoc Loc,
1194+
AvailabilitySet Availability,
1195+
LinkageInfo Linkage, const DocComment &Comment,
1196+
DeclarationFragments Declaration,
1197+
DeclarationFragments SubHeading,
1198+
bool IsFromSystemHeaderg);
11701199
/// Create and add a global variable record into the API set.
11711200
///
11721201
/// Note: the caller is responsible for keeping the StringRef \p Name and
@@ -1284,31 +1313,33 @@ class APISet {
12841313
DeclarationFragments Declaration, DeclarationFragments SubHeading,
12851314
AccessControl Access, Template Template, bool IsFromSystemHeader);
12861315

1287-
CXXClassRecord *
1288-
addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc,
1289-
AvailabilitySet Availability, const DocComment &Comment,
1290-
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1291-
APIRecord::RecordKind Kind, bool IsFromSystemHeader);
1316+
CXXClassRecord *addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
1317+
PresumedLoc Loc, AvailabilitySet Availability,
1318+
const DocComment &Comment,
1319+
DeclarationFragments Declaration,
1320+
DeclarationFragments SubHeading,
1321+
APIRecord::RecordKind Kind, AccessControl Access,
1322+
bool IsFromSystemHeader);
12921323

12931324
ClassTemplateRecord *
1294-
addClassTemplate(StringRef Name, StringRef USR, PresumedLoc Loc,
1295-
AvailabilitySet Availability, const DocComment &Comment,
1296-
DeclarationFragments Declaration,
1325+
addClassTemplate(APIRecord *Parent, StringRef Name, StringRef USR,
1326+
PresumedLoc Loc, AvailabilitySet Availability,
1327+
const DocComment &Comment, DeclarationFragments Declaration,
12971328
DeclarationFragments SubHeading, Template Template,
1298-
bool IsFromSystemHeader);
1329+
AccessControl Access, bool IsFromSystemHeader);
12991330

13001331
ClassTemplateSpecializationRecord *addClassTemplateSpecialization(
1301-
StringRef Name, StringRef USR, PresumedLoc Loc,
1332+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
13021333
AvailabilitySet Availability, const DocComment &Comment,
13031334
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1304-
bool IsFromSystemHeader);
1335+
AccessControl Access, bool IsFromSystemHeader);
13051336

13061337
ClassTemplatePartialSpecializationRecord *
13071338
addClassTemplatePartialSpecialization(
1308-
StringRef Name, StringRef USR, PresumedLoc Loc,
1339+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
13091340
AvailabilitySet Availability, const DocComment &Comment,
13101341
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1311-
Template Template, bool IsFromSystemHeader);
1342+
Template Template, AccessControl Access, bool IsFromSystemHeader);
13121343

13131344
GlobalVariableTemplateSpecializationRecord *
13141345
addGlobalVariableTemplateSpecialization(
@@ -1483,6 +1514,7 @@ class APISet {
14831514
/// Get the language used by the APIs.
14841515
Language getLanguage() const { return Lang; }
14851516

1517+
const RecordMap<NamespaceRecord> &getNamespaces() const { return Namespaces; }
14861518
const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
14871519
return GlobalFunctions;
14881520
}
@@ -1596,6 +1628,7 @@ class APISet {
15961628
const Language Lang;
15971629

15981630
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
1631+
RecordMap<NamespaceRecord> Namespaces;
15991632
RecordMap<GlobalFunctionRecord> GlobalFunctions;
16001633
RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
16011634
RecordMap<GlobalFunctionTemplateSpecializationRecord>

clang/include/clang/ExtractAPI/DeclarationFragments.h

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

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

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();
@@ -76,6 +78,11 @@ template <typename Derived> class APISetVisitor {
7678
getDerived()->traverseTypedefRecords();
7779
}
7880

81+
void traverseNamespaces() {
82+
for (const auto &Namespace : API.getNamespaces())
83+
getDerived()->visitNamespaceRecord(*Namespace.second);
84+
}
85+
7986
void traverseGlobalFunctionRecords() {
8087
for (const auto &GlobalFunction : API.getGlobalFunctions())
8188
getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second);
@@ -220,6 +227,8 @@ template <typename Derived> class APISetVisitor {
220227
getDerived()->visitTypedefRecord(*Typedef.second);
221228
}
222229

230+
void visitNamespaceRecord(const NamespaceRecord &Record){};
231+
223232
/// Visit a global function record.
224233
void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){};
225234

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
159159
llvm::StringSet<> visitedCategories;
160160

161161
public:
162+
void visitNamespaceRecord(const NamespaceRecord &Record);
163+
162164
/// Visit a global function record.
163165
void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record);
164166

0 commit comments

Comments
 (0)