https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/145070
>From f3e1d5e735b42bb8c123fe16fbe8317ded219331 Mon Sep 17 00:00:00 2001 From: Erick Velez <erickvel...@gmail.com> Date: Wed, 18 Jun 2025 16:36:49 -0700 Subject: [PATCH] [clang-doc] document global variables --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 40 ++++++++++++++++++ clang-tools-extra/clang-doc/BitcodeWriter.cpp | 32 +++++++++++++-- clang-tools-extra/clang-doc/BitcodeWriter.h | 6 +++ clang-tools-extra/clang-doc/HTMLGenerator.cpp | 3 ++ .../clang-doc/HTMLMustacheGenerator.cpp | 2 + clang-tools-extra/clang-doc/JSONGenerator.cpp | 14 +++++++ clang-tools-extra/clang-doc/MDGenerator.cpp | 4 ++ clang-tools-extra/clang-doc/Mapper.cpp | 6 +++ clang-tools-extra/clang-doc/Mapper.h | 1 + .../clang-doc/Representation.cpp | 16 ++++++++ clang-tools-extra/clang-doc/Representation.h | 14 ++++++- clang-tools-extra/clang-doc/Serialize.cpp | 27 ++++++++++++ clang-tools-extra/clang-doc/Serialize.h | 4 ++ clang-tools-extra/clang-doc/YAMLGenerator.cpp | 1 + .../test/clang-doc/json/namespace.cpp | 41 +++++++++---------- .../unittests/clang-doc/BitcodeTest.cpp | 2 + 16 files changed, 188 insertions(+), 25 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 66852931226bf..cbdd5d245b8de 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -93,6 +93,7 @@ static llvm::Error decodeRecord(const Record &R, InfoType &Field, case InfoType::IT_enum: case InfoType::IT_typedef: case InfoType::IT_concept: + case InfoType::IT_variable: Field = IT; return llvm::Error::success(); } @@ -416,6 +417,23 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, "invalid field for ConstraintInfo"); } +static llvm::Error parseRecord(const Record &R, unsigned ID, + llvm::StringRef Blob, VarInfo *I) { + switch (ID) { + case VAR_USR: + return decodeRecord(R, I->USR, Blob); + case VAR_NAME: + return decodeRecord(R, I->Name, Blob); + case VAR_DEFLOCATION: + return decodeRecord(R, I->DefLoc, Blob); + case VAR_IS_STATIC: + return decodeRecord(R, I->IsStatic, Blob); + default: + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid field for VarInfo"); + } +} + template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid type cannot contain CommentInfo"); @@ -458,6 +476,10 @@ template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) { return &I->Description.emplace_back(); } +template <> Expected<CommentInfo *> getCommentInfo(VarInfo *I) { + return &I->Description.emplace_back(); +} + // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on // the parent block to set it. The template specializations define what to do // for each supported parent block. @@ -497,6 +519,11 @@ template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) { return llvm::Error::success(); } +template <> llvm::Error addTypeInfo(VarInfo *I, TypeInfo &&T) { + I->Type = std::move(T); + return llvm::Error::success(); +} + template <typename T> static llvm::Error addReference(T I, Reference &&R, FieldId F) { return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -643,6 +670,9 @@ template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) { template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) { I->Children.Concepts.emplace_back(std::move(R)); } +template <> void addChild(NamespaceInfo *I, VarInfo &&R) { + I->Children.Variables.emplace_back(std::move(R)); +} // Record children: template <> void addChild(RecordInfo *I, FunctionInfo &&R) { @@ -887,6 +917,13 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { addChild(I, std::move(CI)); return llvm::Error::success(); } + case BI_VAR_BLOCK_ID: { + VarInfo VI; + if (auto Err = readBlock(ID, &VI)) + return Err; + addChild(I, std::move(VI)); + return llvm::Error::success(); + } default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid subblock type"); @@ -996,6 +1033,8 @@ ClangDocBitcodeReader::readBlockToInfo(unsigned ID) { return createInfo<ConceptInfo>(ID); case BI_FUNCTION_BLOCK_ID: return createInfo<FunctionInfo>(ID); + case BI_VAR_BLOCK_ID: + return createInfo<VarInfo>(ID); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "cannot create info"); @@ -1035,6 +1074,7 @@ ClangDocBitcodeReader::readBitcode() { case BI_ENUM_BLOCK_ID: case BI_TYPEDEF_BLOCK_ID: case BI_CONCEPT_BLOCK_ID: + case BI_VAR_BLOCK_ID: case BI_FUNCTION_BLOCK_ID: { auto InfoOrErr = readBlockToInfo(ID); if (!InfoOrErr) diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index b7308c012786f..c3351d1decbf5 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -130,7 +130,8 @@ static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"}, {BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"}, {BI_CONSTRAINT_BLOCK_ID, "ConstraintBlock"}, - {BI_CONCEPT_BLOCK_ID, "ConceptBlock"}}; + {BI_CONCEPT_BLOCK_ID, "ConceptBlock"}, + {BI_VAR_BLOCK_ID, "VarBlock"}}; assert(Inits.size() == BlockIdCount); for (const auto &Init : Inits) BlockIdNameMap[Init.first] = Init.second; @@ -213,7 +214,12 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> {CONCEPT_IS_TYPE, {"IsType", &genBoolAbbrev}}, {CONCEPT_CONSTRAINT_EXPRESSION, {"ConstraintExpression", &genStringAbbrev}}, - {CONSTRAINT_EXPRESSION, {"Expression", &genStringAbbrev}}}; + {CONSTRAINT_EXPRESSION, {"Expression", &genStringAbbrev}}, + {VAR_USR, {"USR", &genSymbolIdAbbrev}}, + {VAR_NAME, {"Name", &genStringAbbrev}}, + {VAR_DEFLOCATION, {"DefLocation", &genLocationAbbrev}}, + {VAR_IS_STATIC, {"IsStatic", &genBoolAbbrev}}}; + assert(Inits.size() == RecordIdCount); for (const auto &Init : Inits) { RecordIdNameMap[Init.first] = Init.second; @@ -277,7 +283,8 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>> {CONCEPT_USR, CONCEPT_NAME, CONCEPT_IS_TYPE, CONCEPT_CONSTRAINT_EXPRESSION}}, // Constraint Block - {BI_CONSTRAINT_BLOCK_ID, {CONSTRAINT_EXPRESSION}}}; + {BI_CONSTRAINT_BLOCK_ID, {CONSTRAINT_EXPRESSION}}, + {BI_VAR_BLOCK_ID, {VAR_NAME, VAR_USR, VAR_DEFLOCATION, VAR_IS_STATIC}}}; // AbbreviationMap @@ -540,6 +547,8 @@ void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) { emitBlock(C); for (const auto &C : I.Children.Concepts) emitBlock(C); + for (const auto &C : I.Children.Variables) + emitBlock(C); } void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) { @@ -682,6 +691,20 @@ void ClangDocBitcodeWriter::emitBlock(const ConstraintInfo &C) { emitBlock(C.ConceptRef, FieldId::F_concept); } +void ClangDocBitcodeWriter::emitBlock(const VarInfo &I) { + StreamSubBlockGuard Block(Stream, BI_VAR_BLOCK_ID); + emitRecord(I.USR, VAR_USR); + emitRecord(I.Name, VAR_NAME); + for (const auto &N : I.Namespace) + emitBlock(N, FieldId::F_namespace); + for (const auto &CI : I.Description) + emitBlock(CI); + if (I.DefLoc) + emitRecord(*I.DefLoc, VAR_DEFLOCATION); + emitRecord(I.IsStatic, VAR_IS_STATIC); + emitBlock(I.Type); +} + bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) { switch (I->IT) { case InfoType::IT_namespace: @@ -702,6 +725,9 @@ bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) { case InfoType::IT_concept: emitBlock(*static_cast<clang::doc::ConceptInfo *>(I)); break; + case InfoType::IT_variable: + emitBlock(*static_cast<VarInfo *>(I)); + break; case InfoType::IT_default: llvm::errs() << "Unexpected info, unable to write.\n"; return true; diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h index 4d0c0c07805e7..a70e50b53a61a 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.h +++ b/clang-tools-extra/clang-doc/BitcodeWriter.h @@ -69,6 +69,7 @@ enum BlockId { BI_CONSTRAINT_BLOCK_ID, BI_TYPEDEF_BLOCK_ID, BI_CONCEPT_BLOCK_ID, + BI_VAR_BLOCK_ID, BI_LAST, BI_FIRST = BI_VERSION_BLOCK_ID }; @@ -142,6 +143,10 @@ enum RecordId { CONCEPT_IS_TYPE, CONCEPT_CONSTRAINT_EXPRESSION, CONSTRAINT_EXPRESSION, + VAR_USR, + VAR_NAME, + VAR_DEFLOCATION, + VAR_IS_STATIC, RI_LAST, RI_FIRST = VERSION }; @@ -190,6 +195,7 @@ class ClangDocBitcodeWriter { void emitBlock(const ConceptInfo &T); void emitBlock(const ConstraintInfo &T); void emitBlock(const Reference &B, FieldId F); + void emitBlock(const VarInfo &B); private: class AbbreviationMap { diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index 935bbfee7a9b1..c4303d287da9e 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -986,6 +986,7 @@ llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS, genHTML(*static_cast<clang::doc::TypedefInfo *>(I), CDCtx, InfoTitle); break; case InfoType::IT_concept: + case InfoType::IT_variable: break; case InfoType::IT_default: return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -1015,6 +1016,8 @@ static std::string getRefType(InfoType IT) { return "typedef"; case InfoType::IT_concept: return "concept"; + case InfoType::IT_variable: + return "variable"; } llvm_unreachable("Unknown InfoType"); } diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 81ba99c21e374..c611c946b3937 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -587,6 +587,8 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, break; case InfoType::IT_concept: break; + case InfoType::IT_variable: + break; case InfoType::IT_default: return createStringError(inconvertibleErrorCode(), "unexpected InfoType"); } diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 8a37621597c6a..91f5ba4080619 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -482,6 +482,15 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj, serializeCommonChildren(I.Children, Obj, RepositoryUrl); } +static void serializeInfo(const VarInfo &I, json::Object &Obj, + std::optional<StringRef> RepositoryUrl) { + serializeCommonAttributes(I, Obj, RepositoryUrl); + Obj["IsStatic"] = I.IsStatic; + auto TypeObj = Object(); + serializeInfo(I.Type, TypeObj); + Obj["Type"] = std::move(TypeObj); +} + static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, std::optional<StringRef> RepositoryUrl) { serializeCommonAttributes(I, Obj, RepositoryUrl); @@ -519,6 +528,10 @@ static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, if (!I.Children.Concepts.empty()) serializeArray(I.Children.Concepts, Obj, "Concepts", SerializeInfo); + if (!I.Children.Variables.empty()) { + serializeArray(I.Children.Variables, Obj, "Variables", SerializeInfo); + } + serializeCommonChildren(I.Children, Obj, RepositoryUrl); } @@ -573,6 +586,7 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS, case InfoType::IT_enum: case InfoType::IT_function: case InfoType::IT_typedef: + case InfoType::IT_variable: break; case InfoType::IT_default: return createStringError(inconvertibleErrorCode(), "unexpected info type"); diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp index 6e68e09cfa2a6..608a7f6d4a9d3 100644 --- a/clang-tools-extra/clang-doc/MDGenerator.cpp +++ b/clang-tools-extra/clang-doc/MDGenerator.cpp @@ -375,6 +375,9 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) { case InfoType::IT_concept: Type = "Concept"; break; + case InfoType::IT_variable: + Type = "Variable"; + break; case InfoType::IT_default: Type = "Other"; } @@ -468,6 +471,7 @@ llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS, genMarkdown(CDCtx, *static_cast<clang::doc::TypedefInfo *>(I), OS); break; case InfoType::IT_concept: + case InfoType::IT_variable: break; case InfoType::IT_default: return createStringError(llvm::inconvertibleErrorCode(), diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index 6021e17b4696d..497b80cf97463 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -138,6 +138,12 @@ bool MapASTVisitor::VisitConceptDecl(const ConceptDecl *D) { return mapDecl(D, true); } +bool MapASTVisitor::VisitVarDecl(const VarDecl *D) { + if (D->isCXXClassMember()) + return true; + return mapDecl(D, D->isThisDeclarationADefinition()); +} + comments::FullComment * MapASTVisitor::getComment(const NamedDecl *D, const ASTContext &Context) const { RawComment *Comment = Context.getRawCommentForDeclNoCache(D); diff --git a/clang-tools-extra/clang-doc/Mapper.h b/clang-tools-extra/clang-doc/Mapper.h index 04dc5450c8ba3..322df6d594b3d 100644 --- a/clang-tools-extra/clang-doc/Mapper.h +++ b/clang-tools-extra/clang-doc/Mapper.h @@ -42,6 +42,7 @@ class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>, bool VisitTypedefDecl(const TypedefDecl *D); bool VisitTypeAliasDecl(const TypeAliasDecl *D); bool VisitConceptDecl(const ConceptDecl *D); + bool VisitVarDecl(const VarDecl *D); private: template <typename T> bool mapDecl(const T *D, bool IsDefinition); diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 286aeeea1001b..5b94d37d868b4 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -145,6 +145,8 @@ mergeInfos(std::vector<std::unique_ptr<Info>> &Values) { return reduce<TypedefInfo>(Values); case InfoType::IT_concept: return reduce<ConceptInfo>(Values); + case InfoType::IT_variable: + return reduce<VarInfo>(Values); case InfoType::IT_default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "unexpected info type"); @@ -291,6 +293,7 @@ void NamespaceInfo::merge(NamespaceInfo &&Other) { reduceChildren(Children.Enums, std::move(Other.Children.Enums)); reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs)); reduceChildren(Children.Concepts, std::move(Other.Children.Concepts)); + reduceChildren(Children.Variables, std::move(Other.Children.Variables)); mergeBase(std::move(Other)); } @@ -368,6 +371,15 @@ void ConceptInfo::merge(ConceptInfo &&Other) { SymbolInfo::merge(std::move(Other)); } +void VarInfo::merge(VarInfo &&Other) { + assert(mergeable(Other)); + if (!IsStatic) + IsStatic = Other.IsStatic; + if (Type.Type.USR == EmptySID && Type.Type.Name == "") + Type = std::move(Other.Type); + SymbolInfo::merge(std::move(Other)); +} + BaseRecordInfo::BaseRecordInfo() : RecordInfo() {} BaseRecordInfo::BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, @@ -407,6 +419,9 @@ llvm::SmallString<16> Info::extractName() const { case InfoType::IT_concept: return llvm::SmallString<16>("@nonymous_concept_" + toHex(llvm::toStringRef(USR))); + case InfoType::IT_variable: + return llvm::SmallString<16>("@nonymous_variable_" + + toHex(llvm::toStringRef(USR))); case InfoType::IT_default: return llvm::SmallString<16>("@nonymous_" + toHex(llvm::toStringRef(USR))); } @@ -473,6 +488,7 @@ void ScopeChildren::sort() { llvm::sort(Enums.begin(), Enums.end()); llvm::sort(Typedefs.begin(), Typedefs.end()); llvm::sort(Concepts.begin(), Concepts.end()); + llvm::sort(Variables.begin(), Variables.end()); } } // namespace doc } // namespace clang diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index b23069f2bd324..59874f0cfcedf 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -36,6 +36,7 @@ struct FunctionInfo; struct Info; struct TypedefInfo; struct ConceptInfo; +struct VarInfo; enum class InfoType { IT_default, @@ -44,7 +45,8 @@ enum class InfoType { IT_function, IT_enum, IT_typedef, - IT_concept + IT_concept, + IT_variable }; enum class CommentKind { @@ -169,6 +171,7 @@ struct ScopeChildren { std::vector<EnumInfo> Enums; std::vector<TypedefInfo> Typedefs; std::vector<ConceptInfo> Concepts; + std::vector<VarInfo> Variables; void sort(); }; @@ -376,6 +379,15 @@ struct SymbolInfo : public Info { bool IsStatic = false; }; +struct VarInfo : SymbolInfo { + VarInfo() : SymbolInfo(InfoType::IT_variable) {} + explicit VarInfo(SymbolID USR) : SymbolInfo(InfoType::IT_variable, USR) {} + + void merge(VarInfo &&I); + + TypeInfo Type; +}; + // TODO: Expand to allow for documenting templating and default args. // Info for functions. struct FunctionInfo : public SymbolInfo { diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 5f3e5c37fa34d..7a9cb8a1eddb9 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -401,6 +401,8 @@ std::string serialize(std::unique_ptr<Info> &I) { return serialize(*static_cast<FunctionInfo *>(I.get())); case InfoType::IT_concept: return serialize(*static_cast<ConceptInfo *>(I.get())); + case InfoType::IT_variable: + return serialize(*static_cast<VarInfo *>(I.get())); case InfoType::IT_typedef: case InfoType::IT_default: return ""; @@ -508,6 +510,10 @@ static void InsertChild(ScopeChildren &Scope, ConceptInfo Info) { Scope.Concepts.push_back(std::move(Info)); } +static void InsertChild(ScopeChildren &Scope, VarInfo Info) { + Scope.Variables.push_back(std::move(Info)); +} + // Creates a parent of the correct type for the given child and inserts it into // that parent. // @@ -549,6 +555,7 @@ static std::unique_ptr<Info> makeAndInsertIntoParent(ChildType Child) { case InfoType::IT_function: case InfoType::IT_typedef: case InfoType::IT_concept: + case InfoType::IT_variable: break; } llvm_unreachable("Invalid reference type for parent namespace"); @@ -1164,6 +1171,26 @@ emitInfo(const ConceptDecl *D, const FullComment *FC, const Location &Loc, return {nullptr, makeAndInsertIntoParent<ConceptInfo &&>(std::move(Concept))}; } +std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> +emitInfo(const VarDecl *D, const FullComment *FC, const Location &Loc, + bool PublicOnly) { + VarInfo Var; + bool IsInAnonymousNamespace = false; + populateSymbolInfo(Var, D, FC, Loc, IsInAnonymousNamespace); + if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) + return {}; + + if (D->getStorageClass() == StorageClass::SC_Static) + Var.IsStatic = true; + Var.Type = + getTypeInfoForType(D->getType(), D->getASTContext().getPrintingPolicy()); + + if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D)) + return {}; + + return {nullptr, makeAndInsertIntoParent<VarInfo &&>(std::move(Var))}; +} + } // namespace serialize } // namespace doc } // namespace clang diff --git a/clang-tools-extra/clang-doc/Serialize.h b/clang-tools-extra/clang-doc/Serialize.h index 497b09bb339f8..06c4d64c51494 100644 --- a/clang-tools-extra/clang-doc/Serialize.h +++ b/clang-tools-extra/clang-doc/Serialize.h @@ -72,6 +72,10 @@ std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> emitInfo(const ConceptDecl *D, const FullComment *FC, const Location &Loc, bool PublicOnly); +std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> +emitInfo(const VarDecl *D, const FullComment *FC, const Location &Loc, + bool PublicOnly); + // Function to hash a given USR value for storage. // As USRs (Unified Symbol Resolution) could be large, especially for functions // with long type arguments, we use 160-bits SHA1(USR) values to diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp index f958871046981..3ca4d4947fa97 100644 --- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp @@ -409,6 +409,7 @@ llvm::Error YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS, InfoYAML << *static_cast<clang::doc::TypedefInfo *>(I); break; case InfoType::IT_concept: + case InfoType::IT_variable: break; case InfoType::IT_default: return llvm::createStringError(llvm::inconvertibleErrorCode(), diff --git a/clang-tools-extra/test/clang-doc/json/namespace.cpp b/clang-tools-extra/test/clang-doc/json/namespace.cpp index 248d47351bd38..f1e094f6cab17 100644 --- a/clang-tools-extra/test/clang-doc/json/namespace.cpp +++ b/clang-tools-extra/test/clang-doc/json/namespace.cpp @@ -9,7 +9,6 @@ void myFunction(int Param); namespace NestedNamespace { } // namespace NestedNamespace -// FIXME: Global variables are not mapped or serialized. static int Global; enum Color { @@ -25,7 +24,7 @@ typedef int MyTypedef; // CHECK-NEXT: { // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}namespace.cpp", -// CHECK-NEXT: "LineNumber": 15 +// CHECK-NEXT: "LineNumber": 14 // CHECK-NEXT: }, // CHECK-NEXT: "Members": [ // CHECK-NEXT: { @@ -88,7 +87,7 @@ typedef int MyTypedef; // CHECK-NEXT: "IsUsing": false, // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}namespace.cpp", -// CHECK-NEXT: "LineNumber": 21 +// CHECK-NEXT: "LineNumber": 20 // CHECK-NEXT: }, // CHECK-NEXT: "Name": "MyTypedef", // CHECK-NEXT: "TypeDeclaration": "", @@ -103,23 +102,23 @@ typedef int MyTypedef; // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "USR": "0000000000000000000000000000000000000000" -// CHECK-NOT: "Variables": [ -// CHECK-NOT: { -// CHECK-NOT: "IsStatic": true, -// CHECK-NOT: "Location": { -// CHECK-NOT: "Filename": "{{.*}}namespace.cpp", -// CHECK-NOT: "LineNumber": 13 -// CHECK-NOT: }, -// CHECK-NOT: "Name": "Global", -// CHECK-NOT: "Type": { +// CHECK-NEXT: "Variables": [ +// CHECK-NEXT: { +// CHECK-NEXT: "IsStatic": true, +// CHECK-NEXT: "Location": { +// CHECK-NEXT: "Filename": "{{.*}}namespace.cpp", +// CHECK-NEXT: "LineNumber": 12 +// CHECK-NEXT: }, +// CHECK-NEXT: "Name": "Global", +// CHECK-NEXT: "Type": { // COM: FIXME: IsBuiltIn emits as its default value -// CHECK-NOT: "IsBuiltIn": false, -// CHECK-NOT: "IsTemplate": false, -// CHECK-NOT: "Name": "int", -// CHECK-NOT: "QualName": "int", -// CHECK-NOT: "USR": "0000000000000000000000000000000000000000" -// CHECK-NOT: }, -// CHECK-NOT: "USR": "{{[0-9A-F]*}}" -// CHECK-NOT: } -// CHECK-NOT: ] +// CHECK-NEXT: "IsBuiltIn": false, +// CHECK-NEXT: "IsTemplate": false, +// CHECK-NEXT: "Name": "int", +// CHECK-NEXT: "QualName": "int", +// CHECK-NEXT: "USR": "0000000000000000000000000000000000000000" +// CHECK-NEXT: }, +// CHECK-NEXT: "USR": "{{[0-9A-F]*}}" +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp index a38dfd3036604..323431c4fc9e0 100644 --- a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp @@ -39,6 +39,8 @@ static std::string writeInfo(Info *I) { return writeInfo(*static_cast<TypedefInfo *>(I)); case InfoType::IT_concept: return writeInfo(*static_cast<ConceptInfo *>(I)); + case InfoType::IT_variable: + return writeInfo(*static_cast<VarInfo *>(I)); case InfoType::IT_default: return ""; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits