@@ -30,7 +30,7 @@ static void
3030populateParentNamespaces (llvm::SmallVector<Reference, 4 > &Namespaces,
3131 const T *D, bool &IsAnonymousNamespace);
3232
33- static void populateMemberTypeInfo (MemberTypeInfo &I, const FieldDecl *D);
33+ static void populateMemberTypeInfo (MemberTypeInfo &I, const Decl *D);
3434
3535// A function to extract the appropriate relative path for a given info's
3636// documentation. The path returned is a composite of the parent namespaces.
@@ -375,11 +375,11 @@ static AccessSpecifier getFinalAccessSpecifier(AccessSpecifier FirstAS,
375375// record, the access specification of the field depends on the inheritance mode
376376static void parseFields (RecordInfo &I, const RecordDecl *D, bool PublicOnly,
377377 AccessSpecifier Access = AccessSpecifier::AS_public) {
378+ auto &LO = D->getLangOpts ();
378379 for (const FieldDecl *F : D->fields ()) {
379380 if (!shouldSerializeInfo (PublicOnly, /* IsInAnonymousNamespace=*/ false , F))
380381 continue ;
381382
382- auto &LO = F->getLangOpts ();
383383 // Use getAccessUnsafe so that we just get the default AS_none if it's not
384384 // valid, as opposed to an assert.
385385 MemberTypeInfo &NewMember = I.Members .emplace_back (
@@ -388,6 +388,19 @@ static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly,
388388 getFinalAccessSpecifier (Access, F->getAccessUnsafe ()));
389389 populateMemberTypeInfo (NewMember, F);
390390 }
391+ const CXXRecordDecl *CPP = dyn_cast<CXXRecordDecl>(D);
392+ for (Decl *F : CPP->decls ()) {
393+ if (auto *VD = dyn_cast<VarDecl>(F)) {
394+ if (VD->isStaticDataMember ()) {
395+ MemberTypeInfo &NewMember = I.Members .emplace_back (
396+ getTypeInfoForType (VD->getTypeSourceInfo ()->getType (), LO),
397+ VD->getNameAsString (),
398+ getFinalAccessSpecifier (Access, F->getAccessUnsafe ()));
399+ NewMember.IsStatic = true ;
400+ populateMemberTypeInfo (NewMember, VD);
401+ }
402+ }
403+ }
391404}
392405
393406static void parseEnumerators (EnumInfo &I, const EnumDecl *D) {
@@ -568,7 +581,7 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
568581 }
569582}
570583
571- static void populateMemberTypeInfo (MemberTypeInfo &I, const FieldDecl *D) {
584+ static void populateMemberTypeInfo (MemberTypeInfo &I, const Decl *D) {
572585 assert (D && " Expect non-null FieldDecl in populateMemberTypeInfo" );
573586
574587 ASTContext& Context = D->getASTContext ();
@@ -619,6 +632,7 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
619632 continue ;
620633 FunctionInfo FI;
621634 FI.IsMethod = true ;
635+ FI.IsStatic = MD->isStatic ();
622636 // The seventh arg in populateFunctionInfo is a boolean passed by
623637 // reference, its value is not relevant in here so it's not used
624638 // anywhere besides the function call.
@@ -729,61 +743,6 @@ emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
729743 return {std::move (I), std::move (Parent)};
730744}
731745
732- std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
733- emitInfo (const VarDecl *D, const FullComment *FC, int LineNumber,
734- llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) {
735- auto I = std::make_unique<RecordInfo>();
736- bool IsInAnonymousNamespace = false ;
737- populateSymbolInfo (*I, D, FC, LineNumber, File, IsFileInRootDir,
738- IsInAnonymousNamespace);
739- if (!shouldSerializeInfo (PublicOnly, IsInAnonymousNamespace, D))
740- return {};
741-
742- I->Path = getInfoRelativePath (I->Namespace );
743-
744- PopulateTemplateParameters (I->Template , D);
745-
746- // Full and partial specializations.
747- if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
748- if (!I->Template )
749- I->Template .emplace ();
750- I->Template ->Specialization .emplace ();
751- auto &Specialization = *I->Template ->Specialization ;
752-
753- // What this is a specialization of.
754- auto SpecOf = CTSD->getSpecializedTemplateOrPartial ();
755- if (auto *CTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
756- Specialization.SpecializationOf = getUSRForDecl (CTD);
757- else if (auto *CTPSD =
758- dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
759- Specialization.SpecializationOf = getUSRForDecl (CTPSD);
760-
761- // Parameters to the specilization. For partial specializations, get the
762- // parameters "as written" from the ClassTemplatePartialSpecializationDecl
763- // because the non-explicit template parameters will have generated internal
764- // placeholder names rather than the names the user typed that match the
765- // template parameters.
766- if (const ClassTemplatePartialSpecializationDecl *CTPSD =
767- dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
768- if (const ASTTemplateArgumentListInfo *AsWritten =
769- CTPSD->getTemplateArgsAsWritten ()) {
770- for (unsigned i = 0 ; i < AsWritten->getNumTemplateArgs (); i++) {
771- Specialization.Params .emplace_back (
772- getSourceCode (D, (*AsWritten)[i].getSourceRange ()));
773- }
774- }
775- } else {
776- for (const TemplateArgument &Arg : CTSD->getTemplateArgs ().asArray ()) {
777- Specialization.Params .push_back (TemplateArgumentToInfo (D, Arg));
778- }
779- }
780- }
781-
782- // Records are inserted into the parent by reference, so we need to return
783- // both the parent and the record itself.
784- auto Parent = MakeAndInsertIntoParent<const RecordInfo &>(*I);
785- return {std::move (I), std::move (Parent)};
786- }
787746
788747std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
789748emitInfo (const FunctionDecl *D, const FullComment *FC, int LineNumber,
@@ -811,6 +770,7 @@ emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
811770 return {};
812771
813772 Func.IsMethod = true ;
773+ Func.IsStatic = D->isStatic ();
814774
815775 const NamedDecl *Parent = nullptr ;
816776 if (const auto *SD =
0 commit comments