evelez7 updated this revision to Diff 552155. evelez7 marked an inline comment as done. evelez7 added a comment.
Move DetermineParentDecl to determineParentRecord in APIVisitor as a private method. Easier to just let it fetch the record for us and return nullptr if the parent is the translation unit. Also we don't have to cast the Decls to their most derived form for the USR. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D158239/new/ https://reviews.llvm.org/D158239 Files: clang/include/clang/ExtractAPI/API.h clang/include/clang/ExtractAPI/DeclarationFragments.h clang/include/clang/ExtractAPI/ExtractAPIVisitor.h clang/include/clang/ExtractAPI/Serialization/SerializerBase.h clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h clang/lib/ExtractAPI/API.cpp clang/lib/ExtractAPI/DeclarationFragments.cpp clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp clang/test/ExtractAPI/namespace.cpp clang/test/ExtractAPI/nested_namespaces.cpp
Index: clang/test/ExtractAPI/nested_namespaces.cpp =================================================================== --- /dev/null +++ clang/test/ExtractAPI/nested_namespaces.cpp @@ -0,0 +1,164 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ +// RUN: %t/reference.output.json.in >> %t/reference.output.json +// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \ +// RUN: -x c++-header %t/input.h -o %t/output.json -verify + +// Generator version is not consistent across test runs, normalize it. +// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ +// RUN: %t/output.json >> %t/output-normalized.json +// RUN: diff %t/reference.output.json %t/output-normalized.json + +//--- input.h +namespace Foo { + namespace Bar { } +} + +/// expected-no-diagnostics + +//--- reference.output.json.in +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 5, + "patch": 3 + }, + "generator": "?" + }, + "module": { + "name": "", + "platform": { + "architecture": "arm64", + "operatingSystem": { + "minimumVersion": { + "major": 11, + "minor": 0, + "patch": 0 + }, + "name": "macosx" + }, + "vendor": "apple" + } + }, + "relationships": [ + { + "kind": "memberOf", + "source": "c:@N@Foo@N@Bar", + "target": "c:@N@Foo", + "targetFallback": "Foo" + } + ], + "symbols": [ + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "namespace" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Foo" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@N@Foo" + }, + "kind": { + "displayName": "Namespace", + "identifier": "c++.namespace" + }, + "location": { + "position": { + "character": 11, + "line": 1 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Foo" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Foo" + } + ], + "title": "Foo" + }, + "pathComponents": [ + "Foo" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "namespace" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Bar" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@N@Foo@N@Bar" + }, + "kind": { + "displayName": "Namespace", + "identifier": "c++.namespace" + }, + "location": { + "position": { + "character": 13, + "line": 2 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Bar" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Bar" + } + ], + "title": "Bar" + }, + "pathComponents": [ + "Foo", + "Bar" + ] + } + ] +} Index: clang/test/ExtractAPI/namespace.cpp =================================================================== --- /dev/null +++ clang/test/ExtractAPI/namespace.cpp @@ -0,0 +1,164 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ +// RUN: %t/reference.output.json.in >> %t/reference.output.json +// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \ +// RUN: -x c++-header %t/input.h -o %t/output.json -verify + +// Generator version is not consistent across test runs, normalize it. +// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ +// RUN: %t/output.json >> %t/output-normalized.json +// RUN: diff %t/reference.output.json %t/output-normalized.json + +//--- input.h +namespace Foo { + class Bar { }; +} + +/// expected-no-diagnostics + +//--- reference.output.json.in +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 5, + "patch": 3 + }, + "generator": "?" + }, + "module": { + "name": "", + "platform": { + "architecture": "arm64", + "operatingSystem": { + "minimumVersion": { + "major": 11, + "minor": 0, + "patch": 0 + }, + "name": "macosx" + }, + "vendor": "apple" + } + }, + "relationships": [ + { + "kind": "memberOf", + "source": "c:@N@Foo@S@Bar", + "target": "c:@N@Foo", + "targetFallback": "Foo" + } + ], + "symbols": [ + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "namespace" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Foo" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@N@Foo" + }, + "kind": { + "displayName": "Namespace", + "identifier": "c++.namespace" + }, + "location": { + "position": { + "character": 11, + "line": 1 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Foo" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Foo" + } + ], + "title": "Foo" + }, + "pathComponents": [ + "Foo" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "class" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Bar" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@N@Foo@S@Bar" + }, + "kind": { + "displayName": "Class", + "identifier": "c++.class" + }, + "location": { + "position": { + "character": 9, + "line": 2 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Bar" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Bar" + } + ], + "title": "Bar" + }, + "pathComponents": [ + "Foo", + "Bar" + ] + } + ] +} Index: clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp =================================================================== --- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -351,6 +351,10 @@ case APIRecord::RK_Unknown: llvm_unreachable("Records should have an explicit kind"); break; + case APIRecord::RK_Namespace: + Kind["identifier"] = AddLangPrefix("namespace"); + Kind["displayName"] = "Namespace"; + break; case APIRecord::RK_GlobalFunction: Kind["identifier"] = AddLangPrefix("func"); Kind["displayName"] = "Function"; @@ -821,6 +825,17 @@ Relationships.emplace_back(std::move(Relationship)); } +void SymbolGraphSerializer::visitNamespaceRecord( + const NamespaceRecord &Record) { + auto Namespace = serializeAPIRecord(Record); + if (!Namespace) + return; + Symbols.emplace_back(std::move(*Namespace)); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + void SymbolGraphSerializer::visitGlobalFunctionRecord( const GlobalFunctionRecord &Record) { auto Obj = serializeAPIRecord(Record); @@ -874,6 +889,9 @@ Symbols.emplace_back(std::move(*Class)); for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); } void SymbolGraphSerializer::visitClassTemplateRecord( @@ -885,6 +903,9 @@ Symbols.emplace_back(std::move(*Class)); for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); } void SymbolGraphSerializer::visitClassTemplateSpecializationRecord( @@ -897,6 +918,9 @@ for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); } void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord( @@ -909,6 +933,9 @@ for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); } void SymbolGraphSerializer::visitCXXInstanceMethodRecord( Index: clang/lib/ExtractAPI/DeclarationFragments.cpp =================================================================== --- clang/lib/ExtractAPI/DeclarationFragments.cpp +++ clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -423,6 +423,16 @@ return QualsFragments.appendSpace().append(std::move(TypeFragments)); } +DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace( + const NamespaceDecl *Decl) { + DeclarationFragments Fragments; + Fragments.append("namespace", DeclarationFragments::FragmentKind::Keyword); + if (!Decl->isAnonymousNamespace()) + Fragments.appendSpace().append( + Decl->getName(), DeclarationFragments::FragmentKind::Identifier); + return Fragments.append(";", DeclarationFragments::FragmentKind::Text); +} + DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { DeclarationFragments Fragments; Index: clang/lib/ExtractAPI/API.cpp =================================================================== --- clang/lib/ExtractAPI/API.cpp +++ clang/lib/ExtractAPI/API.cpp @@ -44,6 +44,22 @@ } // namespace +NamespaceRecord * +APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR, + PresumedLoc Loc, AvailabilitySet Availability, + LinkageInfo Linkage, const DocComment &Comment, + DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader) { + auto *Record = addTopLevelRecord( + USRBasedLookupTable, Namespaces, USR, Name, Loc, std::move(Availability), + Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader); + + if (Parent) + Record->ParentInformation = APIRecord::HierarchyInformation( + Parent->USR, Parent->Name, Parent->getKind(), Parent); + return Record; +} + GlobalVariableRecord * APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availabilities, LinkageInfo Linkage, @@ -200,47 +216,65 @@ } CXXClassRecord * -APISet::addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilitySet Availabilities, const DocComment &Comment, - DeclarationFragments Declaration, +APISet::addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR, + PresumedLoc Loc, AvailabilitySet Availabilities, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, APIRecord::RecordKind Kind, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, CXXClasses, USR, Name, Loc, - std::move(Availabilities), Comment, Declaration, - SubHeading, Kind, IsFromSystemHeader); + AccessControl Access, bool IsFromSystemHeader) { + auto *Record = + addTopLevelRecord(USRBasedLookupTable, CXXClasses, USR, Name, Loc, + std::move(Availabilities), Comment, Declaration, + SubHeading, Kind, Access, IsFromSystemHeader); + if (Parent) + Record->ParentInformation = APIRecord::HierarchyInformation( + Parent->USR, Parent->Name, Parent->getKind(), Parent); + return Record; } ClassTemplateRecord *APISet::addClassTemplate( - StringRef Name, StringRef USR, PresumedLoc Loc, + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - Template Template, bool IsFromSystemHeader) { - - return addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Template, IsFromSystemHeader); + Template Template, AccessControl Access, bool IsFromSystemHeader) { + auto *Record = + addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc, + std::move(Availability), Comment, Declaration, + SubHeading, Template, Access, IsFromSystemHeader); + if (Parent) + Record->ParentInformation = APIRecord::HierarchyInformation( + Parent->USR, Parent->Name, Parent->getKind(), Parent); + return Record; } ClassTemplateSpecializationRecord *APISet::addClassTemplateSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, - USR, Name, Loc, std::move(Availability), Comment, - Declaration, SubHeading, IsFromSystemHeader); + AccessControl Access, bool IsFromSystemHeader) { + auto *Record = + addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, USR, + Name, Loc, std::move(Availability), Comment, + Declaration, SubHeading, Access, IsFromSystemHeader); + if (Parent) + Record->ParentInformation = APIRecord::HierarchyInformation( + Parent->USR, Parent->Name, Parent->getKind(), Parent); + return Record; } ClassTemplatePartialSpecializationRecord * APISet::addClassTemplatePartialSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - Template Template, bool IsFromSystemHeader) { - return addTopLevelRecord(USRBasedLookupTable, - ClassTemplatePartialSpecializations, USR, Name, Loc, - std::move(Availability), Comment, Declaration, - SubHeading, Template, IsFromSystemHeader); + Template Template, AccessControl Access, bool IsFromSystemHeader) { + auto *Record = addTopLevelRecord( + USRBasedLookupTable, ClassTemplatePartialSpecializations, USR, Name, Loc, + std::move(Availability), Comment, Declaration, SubHeading, Template, + Access, IsFromSystemHeader); + if (Parent) + Record->ParentInformation = APIRecord::HierarchyInformation( + Parent->USR, Parent->Name, Parent->getKind(), Parent); + return Record; } GlobalVariableTemplateSpecializationRecord * Index: clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h =================================================================== --- clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -152,6 +152,8 @@ SymbolGraphSerializerOption Options; public: + void visitNamespaceRecord(const NamespaceRecord &Record); + /// Visit a global function record. void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record); Index: clang/include/clang/ExtractAPI/Serialization/SerializerBase.h =================================================================== --- clang/include/clang/ExtractAPI/Serialization/SerializerBase.h +++ clang/include/clang/ExtractAPI/Serialization/SerializerBase.h @@ -23,6 +23,8 @@ template <typename Derived> class APISetVisitor { public: void traverseAPISet() { + getDerived()->traverseNamespaces(); + getDerived()->traverseGlobalVariableRecords(); getDerived()->traverseGlobalFunctionRecords(); @@ -74,6 +76,11 @@ getDerived()->traverseTypedefRecords(); } + void traverseNamespaces() { + for (const auto &Namespace : API.getNamespaces()) + getDerived()->visitNamespaceRecord(*Namespace.second); + } + void traverseGlobalFunctionRecords() { for (const auto &GlobalFunction : API.getGlobalFunctions()) getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second); @@ -213,6 +220,8 @@ getDerived()->visitTypedefRecord(*Typedef.second); } + void visitNamespaceRecord(const NamespaceRecord &Record){}; + /// Visit a global function record. void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){}; Index: clang/include/clang/ExtractAPI/ExtractAPIVisitor.h =================================================================== --- clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -74,6 +74,10 @@ bool WalkUpFromFunctionTemplateDecl(const FunctionTemplateDecl *Decl); + bool WalkUpFromNamespaceDecl(const NamespaceDecl *Decl); + + bool VisitNamespaceDecl(const NamespaceDecl *Decl); + bool VisitRecordDecl(const RecordDecl *Decl); bool VisitCXXRecordDecl(const CXXRecordDecl *Decl); @@ -187,6 +191,17 @@ } return Bases; } + + APIRecord *determineParentRecord(const DeclContext *Context) { + SmallString<128> ParentUSR; + if (Context->getDeclKind() == Decl::TranslationUnit) + return nullptr; + + index::generateUSRForDecl(dyn_cast<Decl>(Context), ParentUSR); + + APIRecord *Parent = API.findRecordForUSR(ParentUSR); + return Parent; + } }; template <typename T> @@ -447,6 +462,44 @@ return true; } +template <typename Derived> +bool ExtractAPIVisitorBase<Derived>::WalkUpFromNamespaceDecl( + const NamespaceDecl *Decl) { + getDerivedExtractAPIVisitor().VisitNamespaceDecl(Decl); + return true; +} + +template <typename Derived> +bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl( + const NamespaceDecl *Decl) { + + if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) + return true; + if (Decl->isAnonymousNamespace()) + return true; + StringRef Name = Decl->getName(); + StringRef USR = API.recordUSR(Decl); + LinkageInfo Linkage = Decl->getLinkageAndVisibility(); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); + DocComment Comment; + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) + Comment = RawComment->getFormattedLines(Context.getSourceManager(), + Context.getDiagnostics()); + + // Build declaration fragments and sub-heading for the struct. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForNamespace(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); + API.addNamespace(Parent, Name, USR, Loc, AvailabilitySet(Decl), Linkage, + Comment, Declaration, SubHeading, isInSystemHeader(Decl)); + + return true; +} + template <typename Derived> bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) { if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) @@ -512,7 +565,9 @@ Kind = APIRecord::RecordKind::RK_Struct; else Kind = APIRecord::RecordKind::RK_CXXClass; + auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); + APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); CXXClassRecord *CXXClassRecord; if (Decl->getDescribedClassTemplate()) { // Inject template fragments before class fragments. @@ -521,12 +576,13 @@ DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( Decl->getDescribedClassTemplate())); CXXClassRecord = API.addClassTemplate( - Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading, - Template(Decl->getDescribedClassTemplate()), isInSystemHeader(Decl)); + Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, + SubHeading, Template(Decl->getDescribedClassTemplate()), Access, + isInSystemHeader(Decl)); } else - CXXClassRecord = - API.addCXXClass(Name, USR, Loc, AvailabilitySet(Decl), Comment, - Declaration, SubHeading, Kind, isInSystemHeader(Decl)); + CXXClassRecord = API.addCXXClass( + Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, + SubHeading, Kind, Access, isInSystemHeader(Decl)); CXXClassRecord->Bases = getBases(Decl); @@ -708,8 +764,10 @@ DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); + APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); auto *ClassTemplateSpecializationRecord = API.addClassTemplateSpecialization( - Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading, + Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, + SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl), isInSystemHeader(Decl)); ClassTemplateSpecializationRecord->Bases = getBases(Decl); @@ -738,10 +796,13 @@ DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); + APIRecord *Parent = determineParentRecord(Decl->getDeclContext()); auto *ClassTemplatePartialSpecRecord = API.addClassTemplatePartialSpecialization( - Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, - SubHeading, Template(Decl), isInSystemHeader(Decl)); + Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, + SubHeading, Template(Decl), + DeclarationFragmentsBuilder::getAccessControl(Decl), + isInSystemHeader(Decl)); ClassTemplatePartialSpecRecord->Bases = getBases(Decl); Index: clang/include/clang/ExtractAPI/DeclarationFragments.h =================================================================== --- clang/include/clang/ExtractAPI/DeclarationFragments.h +++ clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -257,17 +257,19 @@ static AccessControl getAccessControl(const Decl *Decl) { switch (Decl->getAccess()) { case AS_public: + case AS_none: return AccessControl("public"); case AS_private: return AccessControl("private"); case AS_protected: return AccessControl("protected"); - case AS_none: - return AccessControl("none"); } llvm_unreachable("Unhandled access control"); } + static DeclarationFragments + getFragmentsForNamespace(const NamespaceDecl *Decl); + /// Build DeclarationFragments for a variable declaration VarDecl. static DeclarationFragments getFragmentsForVar(const VarDecl *); @@ -334,8 +336,8 @@ static DeclarationFragments getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl); - static DeclarationFragments getFragmentsForFunctionTemplateSpecialization( - const FunctionDecl *Decl); + static DeclarationFragments + getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl); /// Build DeclarationFragments for an Objective-C category declaration /// ObjCCategoryDecl. Index: clang/include/clang/ExtractAPI/API.h =================================================================== --- clang/include/clang/ExtractAPI/API.h +++ clang/include/clang/ExtractAPI/API.h @@ -157,6 +157,7 @@ /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) enum RecordKind { RK_Unknown, + RK_Namespace, RK_GlobalFunction, RK_GlobalFunctionTemplate, RK_GlobalFunctionTemplateSpecialization, @@ -267,6 +268,20 @@ virtual ~APIRecord() = 0; }; +struct NamespaceRecord : APIRecord { + NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + AvailabilitySet Availabilities, LinkageInfo Linkage, + const DocComment &Comment, DeclarationFragments Declaration, + DeclarationFragments SubHeading, bool IsFromSystemHeader) + : APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availabilities), + Linkage, Comment, Declaration, SubHeading, + IsFromSystemHeader) {} + + static bool classof(const APIRecord *Record) { + return Record->getKind() == RK_Namespace; + } +}; + /// This holds information associated with global functions. struct GlobalFunctionRecord : APIRecord { FunctionSignature Signature; @@ -900,15 +915,17 @@ SmallVector<std::unique_ptr<CXXFieldRecord>> Fields; SmallVector<std::unique_ptr<CXXMethodRecord>> Methods; SmallVector<SymbolReference> Bases; + AccessControl Access; CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, RecordKind Kind, - bool IsFromSystemHeader) + AccessControl Access, bool IsFromSystemHeader) : APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), LinkageInfo::none(), Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + IsFromSystemHeader), + Access(Access) {} static bool classof(const APIRecord *Record) { return (Record->getKind() == RK_CXXClass); @@ -925,9 +942,9 @@ AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, Template Template, - bool IsFromSystemHeader) + AccessControl Access, bool IsFromSystemHeader) : CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment, - Declaration, SubHeading, RK_ClassTemplate, + Declaration, SubHeading, RK_ClassTemplate, Access, IsFromSystemHeader), Templ(Template) {} @@ -937,16 +954,14 @@ }; struct ClassTemplateSpecializationRecord : CXXClassRecord { - ClassTemplateSpecializationRecord(StringRef USR, StringRef Name, - PresumedLoc Loc, - AvailabilitySet Availabilities, - const DocComment &Comment, - DeclarationFragments Declaration, - DeclarationFragments SubHeading, - bool IsFromSystemHeader) + ClassTemplateSpecializationRecord( + StringRef USR, StringRef Name, PresumedLoc Loc, + AvailabilitySet Availabilities, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, + AccessControl Access, bool IsFromSystemHeader) : CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment, Declaration, SubHeading, RK_ClassTemplateSpecialization, - IsFromSystemHeader) {} + Access, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { return Record->getKind() == RK_ClassTemplateSpecialization; @@ -959,10 +974,10 @@ StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - Template Template, bool IsFromSystemHeader) + Template Template, AccessControl Access, bool IsFromSystemHeader) : CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment, Declaration, SubHeading, RK_ClassTemplateSpecialization, - IsFromSystemHeader), + Access, IsFromSystemHeader), Templ(Template) {} static bool classof(const APIRecord *Record) { @@ -1138,6 +1153,13 @@ : public std::true_type {}; template <> struct has_access<CXXFieldTemplateRecord> : public std::true_type {}; +template <> struct has_access<CXXClassRecord> : public std::true_type {}; +template <> struct has_access<ClassTemplateRecord> : public std::true_type {}; +template <> +struct has_access<ClassTemplateSpecializationRecord> : public std::true_type {}; +template <> +struct has_access<ClassTemplatePartialSpecializationRecord> + : public std::true_type {}; template <typename RecordTy> struct has_template : public std::false_type {}; template <> struct has_template<ClassTemplateRecord> : public std::true_type {}; @@ -1160,6 +1182,13 @@ /// APISet holds the set of API records collected from given inputs. class APISet { public: + NamespaceRecord *addNamespace(APIRecord *Parent, StringRef Name, + StringRef USR, PresumedLoc Loc, + AvailabilitySet Availability, + LinkageInfo Linkage, const DocComment &Comment, + DeclarationFragments Declaration, + DeclarationFragments SubHeading, + bool IsFromSystemHeaderg); /// Create and add a global variable record into the API set. /// /// Note: the caller is responsible for keeping the StringRef \p Name and @@ -1277,31 +1306,33 @@ DeclarationFragments Declaration, DeclarationFragments SubHeading, AccessControl Access, Template Template, bool IsFromSystemHeader); - CXXClassRecord * - addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilitySet Availability, const DocComment &Comment, - DeclarationFragments Declaration, DeclarationFragments SubHeading, - APIRecord::RecordKind Kind, bool IsFromSystemHeader); + CXXClassRecord *addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR, + PresumedLoc Loc, AvailabilitySet Availability, + const DocComment &Comment, + DeclarationFragments Declaration, + DeclarationFragments SubHeading, + APIRecord::RecordKind Kind, AccessControl Access, + bool IsFromSystemHeader); ClassTemplateRecord * - addClassTemplate(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilitySet Availability, const DocComment &Comment, - DeclarationFragments Declaration, + addClassTemplate(APIRecord *Parent, StringRef Name, StringRef USR, + PresumedLoc Loc, AvailabilitySet Availability, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, Template Template, - bool IsFromSystemHeader); + AccessControl Access, bool IsFromSystemHeader); ClassTemplateSpecializationRecord *addClassTemplateSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - bool IsFromSystemHeader); + AccessControl Access, bool IsFromSystemHeader); ClassTemplatePartialSpecializationRecord * addClassTemplatePartialSpecialization( - StringRef Name, StringRef USR, PresumedLoc Loc, + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - Template Template, bool IsFromSystemHeader); + Template Template, AccessControl Access, bool IsFromSystemHeader); GlobalVariableTemplateSpecializationRecord * addGlobalVariableTemplateSpecialization( @@ -1476,6 +1507,7 @@ /// Get the language used by the APIs. Language getLanguage() const { return Lang; } + const RecordMap<NamespaceRecord> &getNamespaces() const { return Namespaces; } const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const { return GlobalFunctions; } @@ -1589,6 +1621,7 @@ const Language Lang; llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable; + RecordMap<NamespaceRecord> Namespaces; RecordMap<GlobalFunctionRecord> GlobalFunctions; RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates; RecordMap<GlobalFunctionTemplateSpecializationRecord>
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits