diff options
Diffstat (limited to 'clang-tools-extra/clang-doc')
-rw-r--r-- | clang-tools-extra/clang-doc/BitcodeReader.cpp | 46 | ||||
-rw-r--r-- | clang-tools-extra/clang-doc/BitcodeWriter.cpp | 22 | ||||
-rw-r--r-- | clang-tools-extra/clang-doc/BitcodeWriter.h | 8 | ||||
-rw-r--r-- | clang-tools-extra/clang-doc/HTMLGenerator.cpp | 5 | ||||
-rw-r--r-- | clang-tools-extra/clang-doc/MDGenerator.cpp | 2 | ||||
-rw-r--r-- | clang-tools-extra/clang-doc/Representation.h | 37 | ||||
-rw-r--r-- | clang-tools-extra/clang-doc/Serialize.cpp | 25 | ||||
-rw-r--r-- | clang-tools-extra/clang-doc/YAMLGenerator.cpp | 11 |
8 files changed, 135 insertions, 21 deletions
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 7736e3d..da7f624 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -17,12 +17,19 @@ namespace doc { using Record = llvm::SmallVector<uint64_t, 1024>; +// This implements decode for SmallString. llvm::Error decodeRecord(const Record &R, llvm::SmallVectorImpl<char> &Field, llvm::StringRef Blob) { Field.assign(Blob.begin(), Blob.end()); return llvm::Error::success(); } +llvm::Error decodeRecord(const Record &R, std::string &Field, + llvm::StringRef Blob) { + Field.assign(Blob.begin(), Blob.end()); + return llvm::Error::success(); +} + llvm::Error decodeRecord(const Record &R, SymbolID &Field, llvm::StringRef Blob) { if (R[0] != BitCodeConstants::USRHashSize) @@ -218,8 +225,6 @@ llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, return decodeRecord(R, I->DefLoc, Blob); case ENUM_LOCATION: return decodeRecord(R, I->Loc, Blob); - case ENUM_MEMBER: - return decodeRecord(R, I->Members, Blob); case ENUM_SCOPED: return decodeRecord(R, I->Scoped, Blob); default: @@ -229,6 +234,21 @@ llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, } llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, + EnumValueInfo *I) { + switch (ID) { + case ENUM_VALUE_NAME: + return decodeRecord(R, I->Name, Blob); + case ENUM_VALUE_VALUE: + return decodeRecord(R, I->Value, Blob); + case ENUM_VALUE_EXPR: + return decodeRecord(R, I->ValueExpr, Blob); + default: + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid field for EnumValueInfo"); + } +} + +llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob, FunctionInfo *I) { switch (ID) { case FUNCTION_USR: @@ -372,6 +392,9 @@ llvm::Expected<CommentInfo *> getCommentInfo(std::unique_ptr<CommentInfo> &I) { return getCommentInfo(I.get()); } +// 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. template <typename T, typename TTypeInfo> llvm::Error addTypeInfo(T I, TTypeInfo &&TI) { return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -398,6 +421,11 @@ template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) { return llvm::Error::success(); } +template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) { + I->BaseType = std::move(T); + return llvm::Error::success(); +} + template <typename T> llvm::Error addReference(T I, Reference &&R, FieldId F) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid type cannot contain Reference"); @@ -524,6 +552,10 @@ template <> void addChild(RecordInfo *I, EnumInfo &&R) { I->ChildEnums.emplace_back(std::move(R)); } +template <> void addChild(EnumInfo *I, EnumValueInfo &&R) { + I->Members.emplace_back(std::move(R)); +} + template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) { I->Bases.emplace_back(std::move(R)); } @@ -587,8 +619,7 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) { template <typename T> llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { switch (ID) { - // Blocks can only have Comment, Reference, TypeInfo, FunctionInfo, or - // EnumInfo subblocks + // Blocks can only have certain types of sub blocks. case BI_COMMENT_BLOCK_ID: { auto Comment = getCommentInfo(I); if (!Comment) @@ -650,6 +681,13 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { addChild(I, std::move(E)); return llvm::Error::success(); } + case BI_ENUM_VALUE_BLOCK_ID: { + EnumValueInfo EV; + if (auto Err = readBlock(ID, &EV)) + return Err; + addChild(I, std::move(EV)); + return llvm::Error::success(); + } default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid subblock type"); diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index 7e23170..993e4dd 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -112,6 +112,7 @@ static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> {BI_VERSION_BLOCK_ID, "VersionBlock"}, {BI_NAMESPACE_BLOCK_ID, "NamespaceBlock"}, {BI_ENUM_BLOCK_ID, "EnumBlock"}, + {BI_ENUM_VALUE_BLOCK_ID, "EnumValueBlock"}, {BI_TYPE_BLOCK_ID, "TypeBlock"}, {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"}, {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"}, @@ -158,8 +159,10 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> {ENUM_NAME, {"Name", &StringAbbrev}}, {ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}}, {ENUM_LOCATION, {"Location", &LocationAbbrev}}, - {ENUM_MEMBER, {"Member", &StringAbbrev}}, {ENUM_SCOPED, {"Scoped", &BoolAbbrev}}, + {ENUM_VALUE_NAME, {"Name", &StringAbbrev}}, + {ENUM_VALUE_VALUE, {"Value", &StringAbbrev}}, + {ENUM_VALUE_EXPR, {"Expr", &StringAbbrev}}, {RECORD_USR, {"USR", &SymbolIDAbbrev}}, {RECORD_NAME, {"Name", &StringAbbrev}}, {RECORD_PATH, {"Path", &StringAbbrev}}, @@ -213,8 +216,10 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>> {BI_MEMBER_TYPE_BLOCK_ID, {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS}}, // Enum Block {BI_ENUM_BLOCK_ID, - {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_MEMBER, - ENUM_SCOPED}}, + {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_SCOPED}}, + // Enum Value Block + {BI_ENUM_VALUE_BLOCK_ID, + {ENUM_VALUE_NAME, ENUM_VALUE_VALUE, ENUM_VALUE_EXPR}}, // Namespace Block {BI_NAMESPACE_BLOCK_ID, {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}}, @@ -486,8 +491,17 @@ void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) { for (const auto &L : I.Loc) emitRecord(L, ENUM_LOCATION); emitRecord(I.Scoped, ENUM_SCOPED); + if (I.BaseType) + emitBlock(*I.BaseType); for (const auto &N : I.Members) - emitRecord(N, ENUM_MEMBER); + emitBlock(N); +} + +void ClangDocBitcodeWriter::emitBlock(const EnumValueInfo &I) { + StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID); + emitRecord(I.Name, ENUM_VALUE_NAME); + emitRecord(I.Value, ENUM_VALUE_VALUE); + emitRecord(I.ValueExpr, ENUM_VALUE_EXPR); } void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) { diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h index cc51eb5..4015c5d 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.h +++ b/clang-tools-extra/clang-doc/BitcodeWriter.h @@ -17,6 +17,7 @@ #include "Representation.h" #include "clang/AST/AST.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -54,6 +55,7 @@ enum BlockId { BI_VERSION_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, BI_NAMESPACE_BLOCK_ID, BI_ENUM_BLOCK_ID, + BI_ENUM_VALUE_BLOCK_ID, BI_TYPE_BLOCK_ID, BI_FIELD_TYPE_BLOCK_ID, BI_MEMBER_TYPE_BLOCK_ID, @@ -98,8 +100,10 @@ enum RecordId { ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, - ENUM_MEMBER, ENUM_SCOPED, + ENUM_VALUE_NAME, + ENUM_VALUE_VALUE, + ENUM_VALUE_EXPR, RECORD_USR, RECORD_NAME, RECORD_PATH, @@ -155,6 +159,7 @@ public: void emitBlock(const BaseRecordInfo &I); void emitBlock(const FunctionInfo &I); void emitBlock(const EnumInfo &I); + void emitBlock(const EnumValueInfo &I); void emitBlock(const TypeInfo &B); void emitBlock(const FieldTypeInfo &B); void emitBlock(const MemberTypeInfo &B); @@ -205,6 +210,7 @@ private: void emitRecord(bool Value, RecordId ID); void emitRecord(int Value, RecordId ID); void emitRecord(unsigned Value, RecordId ID); + void emitRecord(llvm::APSInt Value, RecordId ID); bool prepRecordData(RecordId ID, bool ShouldEmit = true); // Emission of appropriate abbreviation type. diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index 7456d96..211cc9f 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -361,13 +361,14 @@ genEnumsBlock(const std::vector<EnumInfo> &Enums, } static std::unique_ptr<TagNode> -genEnumMembersBlock(const llvm::SmallVector<SmallString<16>, 4> &Members) { +genEnumMembersBlock(const llvm::SmallVector<EnumValueInfo, 4> &Members) { if (Members.empty()) return nullptr; auto List = std::make_unique<TagNode>(HTMLTag::TAG_UL); for (const auto &M : Members) - List->Children.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_LI, M)); + List->Children.emplace_back( + std::make_unique<TagNode>(HTMLTag::TAG_LI, M.Name)); return List; } diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp index b04ad58..8957a47 100644 --- a/clang-tools-extra/clang-doc/MDGenerator.cpp +++ b/clang-tools-extra/clang-doc/MDGenerator.cpp @@ -136,7 +136,7 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I, llvm::raw_string_ostream Members(Buffer); if (!I.Members.empty()) for (const auto &N : I.Members) - Members << "| " << N << " |\n"; + Members << "| " << N.Name << " |\n"; writeLine(Members.str(), OS); if (I.DefLoc) writeFileDefinition(CDCtx, *I.DefLoc, OS); diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 65a0ae8..0f0a838 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -17,6 +17,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" #include "clang/Tooling/StandaloneExecution.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -397,6 +398,30 @@ struct BaseRecordInfo : public RecordInfo { bool IsParent = false; // Indicates if this base is a direct parent }; +// Information for a single possible value of an enumeration. +struct EnumValueInfo { + explicit EnumValueInfo(StringRef Name = StringRef(), + StringRef Value = StringRef("0"), + StringRef ValueExpr = StringRef()) + : Name(Name), Value(Value), ValueExpr(ValueExpr) {} + + bool operator==(const EnumValueInfo &Other) const { + return std::tie(Name, Value, ValueExpr) == + std::tie(Other.Name, Other.Value, Other.ValueExpr); + } + + SmallString<16> Name; + + // The computed value of the enumeration constant. This could be the result of + // evaluating the ValueExpr, or it could be automatically generated according + // to C rules. + SmallString<16> Value; + + // Stores the user-supplied initialization expression for this enumeration + // constant. This will be empty for implicit enumeration values. + SmallString<16> ValueExpr; +}; + // TODO: Expand to allow for documenting templating. // Info for types. struct EnumInfo : public SymbolInfo { @@ -405,9 +430,15 @@ struct EnumInfo : public SymbolInfo { void merge(EnumInfo &&I); - bool Scoped = - false; // Indicates whether this enum is scoped (e.g. enum class). - llvm::SmallVector<SmallString<16>, 4> Members; // List of enum members. + // Indicates whether this enum is scoped (e.g. enum class). + bool Scoped = false; + + // Set to nonempty to the type when this is an explicitly typed enum. For + // enum Foo : short { ... }; + // this will be "short". + llvm::Optional<TypeInfo> BaseType; + + llvm::SmallVector<EnumValueInfo, 4> Members; // List of enum members. }; struct Index : public Reference { diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index cb1b81d..4c161f0 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -182,6 +182,13 @@ std::string ClangDocCommentVisitor::getCommandName(unsigned CommandID) const { // Serializing functions. +std::string getSourceCode(const Decl *D, const SourceRange &R) { + return Lexer::getSourceText(CharSourceRange::getTokenRange(R), + D->getASTContext().getSourceManager(), + D->getASTContext().getLangOpts()) + .str(); +} + template <typename T> static std::string serialize(T &I) { SmallString<2048> Buffer; llvm::BitstreamWriter Stream(Buffer); @@ -305,8 +312,15 @@ static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly, } static void parseEnumerators(EnumInfo &I, const EnumDecl *D) { - for (const EnumConstantDecl *E : D->enumerators()) - I.Members.emplace_back(E->getNameAsString()); + for (const EnumConstantDecl *E : D->enumerators()) { + std::string ValueExpr; + if (const Expr *InitExpr = E->getInitExpr()) + ValueExpr = getSourceCode(D, InitExpr->getSourceRange()); + + SmallString<16> ValueStr; + E->getInitVal().toString(ValueStr); + I.Members.emplace_back(E->getNameAsString(), ValueStr, ValueExpr); + } } static void parseParameters(FunctionInfo &I, const FunctionDecl *D) { @@ -331,10 +345,7 @@ static void parseParameters(FunctionInfo &I, const FunctionDecl *D) { } if (const Expr *DefaultArg = P->getDefaultArg()) { - FieldInfo->DefaultValue = Lexer::getSourceText( - CharSourceRange::getTokenRange(DefaultArg->getSourceRange()), - D->getASTContext().getSourceManager(), - D->getASTContext().getLangOpts()); + FieldInfo->DefaultValue = getSourceCode(D, DefaultArg->getSourceRange()); } } } @@ -657,6 +668,8 @@ emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, return {}; Enum.Scoped = D->isScoped(); + if (D->isFixed()) + Enum.BaseType = TypeInfo(D->getIntegerType().getAsString()); parseEnumerators(Enum, D); // Put in global namespace diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp index 2022e4a..14d2c87 100644 --- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp @@ -14,6 +14,7 @@ using namespace clang::doc; +// These define YAML traits for decoding the listed values within a vector. LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(Reference) @@ -21,6 +22,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(Location) LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(EnumInfo) +LLVM_YAML_IS_SEQUENCE_VECTOR(EnumValueInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(BaseRecordInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>) @@ -226,10 +228,19 @@ template <> struct MappingTraits<BaseRecordInfo> { } }; +template <> struct MappingTraits<EnumValueInfo> { + static void mapping(IO &IO, EnumValueInfo &I) { + IO.mapOptional("Name", I.Name); + IO.mapOptional("Value", I.Value); + IO.mapOptional("Expr", I.ValueExpr, SmallString<16>()); + } +}; + template <> struct MappingTraits<EnumInfo> { static void mapping(IO &IO, EnumInfo &I) { SymbolInfoMapping(IO, I); IO.mapOptional("Scoped", I.Scoped, false); + IO.mapOptional("BaseType", I.BaseType); IO.mapOptional("Members", I.Members); } }; |