| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| //===-- Mapper.cpp - ClangDoc Mapper ----------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "Mapper.h" | ||
| #include "BitcodeWriter.h" | ||
| #include "Serialize.h" | ||
| #include "clang/AST/Comment.h" | ||
| #include "clang/Index/USRGeneration.h" | ||
| #include "llvm/ADT/StringExtras.h" | ||
|
|
||
| using clang::comments::FullComment; | ||
|
|
||
| namespace clang { | ||
| namespace doc { | ||
|
|
||
| void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) { | ||
| TraverseDecl(Context.getTranslationUnitDecl()); | ||
| } | ||
|
|
||
| template <typename T> bool MapASTVisitor::mapDecl(const T *D) { | ||
| // If we're looking a decl not in user files, skip this decl. | ||
| if (D->getASTContext().getSourceManager().isInSystemHeader(D->getLocation())) | ||
| return true; | ||
|
|
||
| llvm::SmallString<128> USR; | ||
| // If there is an error generating a USR for the decl, skip this decl. | ||
| if (index::generateUSRForDecl(D, USR)) | ||
| return true; | ||
|
|
||
| ECtx->reportResult(llvm::toHex(llvm::toStringRef(serialize::hashUSR(USR))), | ||
| serialize::emitInfo(D, getComment(D, D->getASTContext()), | ||
| getLine(D, D->getASTContext()), | ||
| getFile(D, D->getASTContext()))); | ||
| return true; | ||
| } | ||
|
|
||
| bool MapASTVisitor::VisitNamespaceDecl(const NamespaceDecl *D) { | ||
| return mapDecl(D); | ||
| } | ||
|
|
||
| bool MapASTVisitor::VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); } | ||
|
|
||
| bool MapASTVisitor::VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); } | ||
|
|
||
| bool MapASTVisitor::VisitCXXMethodDecl(const CXXMethodDecl *D) { | ||
| return mapDecl(D); | ||
| } | ||
|
|
||
| bool MapASTVisitor::VisitFunctionDecl(const FunctionDecl *D) { | ||
| // Don't visit CXXMethodDecls twice | ||
| if (dyn_cast<CXXMethodDecl>(D)) | ||
| return true; | ||
| return mapDecl(D); | ||
| } | ||
|
|
||
| comments::FullComment * | ||
| MapASTVisitor::getComment(const NamedDecl *D, const ASTContext &Context) const { | ||
| RawComment *Comment = Context.getRawCommentForDeclNoCache(D); | ||
| // FIXME: Move setAttached to the initial comment parsing. | ||
| if (Comment) { | ||
| Comment->setAttached(); | ||
| return Comment->parse(Context, nullptr, D); | ||
| } | ||
| return nullptr; | ||
| } | ||
|
|
||
| int MapASTVisitor::getLine(const NamedDecl *D, | ||
| const ASTContext &Context) const { | ||
| return Context.getSourceManager().getPresumedLoc(D->getLocStart()).getLine(); | ||
| } | ||
|
|
||
| llvm::StringRef MapASTVisitor::getFile(const NamedDecl *D, | ||
| const ASTContext &Context) const { | ||
| return Context.getSourceManager() | ||
| .getPresumedLoc(D->getLocStart()) | ||
| .getFilename(); | ||
| } | ||
|
|
||
| } // namespace doc | ||
| } // namespace clang |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| //===-- Mapper.h - ClangDoc Mapper ------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file implements the Mapper piece of the clang-doc tool. It implements | ||
| // a RecursiveASTVisitor to look at each declaration and populate the info | ||
| // into the internal representation. Each seen declaration is serialized to | ||
| // to bitcode and written out to the ExecutionContext as a KV pair where the | ||
| // key is the declaration's USR and the value is the serialized bitcode. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_MAPPER_H | ||
| #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_MAPPER_H | ||
|
|
||
| #include "clang/AST/RecursiveASTVisitor.h" | ||
| #include "clang/Tooling/Execution.h" | ||
|
|
||
| using namespace clang::comments; | ||
| using namespace clang::tooling; | ||
|
|
||
| namespace clang { | ||
| namespace doc { | ||
|
|
||
| class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>, | ||
| public ASTConsumer { | ||
| public: | ||
| explicit MapASTVisitor(ASTContext *Ctx, ExecutionContext *ECtx) | ||
| : ECtx(ECtx) {} | ||
|
|
||
| void HandleTranslationUnit(ASTContext &Context) override; | ||
| bool VisitNamespaceDecl(const NamespaceDecl *D); | ||
| bool VisitRecordDecl(const RecordDecl *D); | ||
| bool VisitEnumDecl(const EnumDecl *D); | ||
| bool VisitCXXMethodDecl(const CXXMethodDecl *D); | ||
| bool VisitFunctionDecl(const FunctionDecl *D); | ||
|
|
||
| private: | ||
| template <typename T> bool mapDecl(const T *D); | ||
|
|
||
| int getLine(const NamedDecl *D, const ASTContext &Context) const; | ||
| StringRef getFile(const NamedDecl *D, const ASTContext &Context) const; | ||
| comments::FullComment *getComment(const NamedDecl *D, | ||
| const ASTContext &Context) const; | ||
|
|
||
| ExecutionContext *ECtx; | ||
| }; | ||
|
|
||
| } // namespace doc | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_MAPPER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,184 @@ | ||
| ///===-- Representation.h - ClangDoc Represenation --------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file defines the internal representations of different declaration | ||
| // types for the clang-doc tool. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H | ||
| #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H | ||
|
|
||
| #include "clang/AST/Type.h" | ||
| #include "clang/Basic/Specifiers.h" | ||
| #include "llvm/ADT/Optional.h" | ||
| #include "llvm/ADT/SmallVector.h" | ||
| #include "llvm/ADT/StringExtras.h" | ||
| #include <array> | ||
| #include <string> | ||
|
|
||
| namespace clang { | ||
| namespace doc { | ||
|
|
||
| using SymbolID = std::array<uint8_t, 20>; | ||
|
|
||
| struct Info; | ||
| enum class InfoType { | ||
| IT_namespace, | ||
| IT_record, | ||
| IT_function, | ||
| IT_enum, | ||
| IT_default | ||
| }; | ||
|
|
||
| // A representation of a parsed comment. | ||
| struct CommentInfo { | ||
| CommentInfo() = default; | ||
| CommentInfo(CommentInfo &&Other) : Children(std::move(Other.Children)) {} | ||
|
|
||
| SmallString<16> | ||
| Kind; // Kind of comment (TextComment, InlineCommandComment, | ||
| // HTMLStartTagComment, HTMLEndTagComment, BlockCommandComment, | ||
| // ParamCommandComment, TParamCommandComment, VerbatimBlockComment, | ||
| // VerbatimBlockLineComment, VerbatimLineComment). | ||
| SmallString<64> Text; // Text of the comment. | ||
| SmallString<16> Name; // Name of the comment (for Verbatim and HTML). | ||
| SmallString<8> Direction; // Parameter direction (for (T)ParamCommand). | ||
| SmallString<16> ParamName; // Parameter name (for (T)ParamCommand). | ||
| SmallString<16> CloseName; // Closing tag name (for VerbatimBlock). | ||
| bool SelfClosing = false; // Indicates if tag is self-closing (for HTML). | ||
| bool Explicit = false; // Indicates if the direction of a param is explicit | ||
| // (for (T)ParamCommand). | ||
| llvm::SmallVector<SmallString<16>, 4> | ||
| AttrKeys; // List of attribute keys (for HTML). | ||
| llvm::SmallVector<SmallString<16>, 4> | ||
| AttrValues; // List of attribute values for each key (for HTML). | ||
| llvm::SmallVector<SmallString<16>, 4> | ||
| Args; // List of arguments to commands (for InlineCommand). | ||
| std::vector<std::unique_ptr<CommentInfo>> | ||
| Children; // List of child comments for this CommentInfo. | ||
| }; | ||
|
|
||
| struct Reference { | ||
| Reference() = default; | ||
| Reference(llvm::StringRef Name) : UnresolvedName(Name) {} | ||
| Reference(SymbolID USR, InfoType IT) : USR(USR), RefType(IT) {} | ||
|
|
||
| SymbolID USR; // Unique identifer for referenced decl | ||
| SmallString<16> UnresolvedName; // Name of unresolved type. | ||
| InfoType RefType = | ||
| InfoType::IT_default; // Indicates the type of this Reference (namespace, | ||
| // record, function, enum, default). | ||
| }; | ||
|
|
||
| // A base struct for TypeInfos | ||
| struct TypeInfo { | ||
| TypeInfo() = default; | ||
| TypeInfo(SymbolID &Type, InfoType IT) : Type(Type, IT) {} | ||
| TypeInfo(llvm::StringRef RefName) : Type(RefName) {} | ||
|
|
||
| Reference Type; // Referenced type in this info. | ||
| }; | ||
|
|
||
| // Info for field types. | ||
| struct FieldTypeInfo : public TypeInfo { | ||
| FieldTypeInfo() = default; | ||
| FieldTypeInfo(SymbolID &Type, InfoType IT, llvm::StringRef Name) | ||
| : TypeInfo(Type, IT), Name(Name) {} | ||
| FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name) | ||
| : TypeInfo(RefName), Name(Name) {} | ||
|
|
||
| SmallString<16> Name; // Name associated with this info. | ||
| }; | ||
|
|
||
| // Info for member types. | ||
| struct MemberTypeInfo : public FieldTypeInfo { | ||
| MemberTypeInfo() = default; | ||
| MemberTypeInfo(SymbolID &Type, InfoType IT, llvm::StringRef Name) | ||
| : FieldTypeInfo(Type, IT, Name) {} | ||
| MemberTypeInfo(llvm::StringRef RefName, llvm::StringRef Name) | ||
| : FieldTypeInfo(RefName, Name) {} | ||
|
|
||
| AccessSpecifier Access = | ||
| clang::AccessSpecifier::AS_none; // Access level associated with this | ||
| // info (public, protected, private, | ||
| // none). | ||
| }; | ||
|
|
||
| struct Location { | ||
| Location() = default; | ||
| Location(int LineNumber, SmallString<16> Filename) | ||
| : LineNumber(LineNumber), Filename(std::move(Filename)) {} | ||
|
|
||
| int LineNumber; // Line number of this Location. | ||
| SmallString<32> Filename; // File for this Location. | ||
| }; | ||
|
|
||
| /// A base struct for Infos. | ||
| struct Info { | ||
| Info() = default; | ||
| Info(Info &&Other) : Description(std::move(Other.Description)) {} | ||
| virtual ~Info() = default; | ||
|
|
||
| SymbolID USR; // Unique identifier for the decl described by this Info. | ||
| SmallString<16> Name; // Unqualified name of the decl. | ||
| llvm::SmallVector<Reference, 4> | ||
| Namespace; // List of parent namespaces for this decl. | ||
| std::vector<CommentInfo> Description; // Comment description of this decl. | ||
| }; | ||
|
|
||
| // Info for namespaces. | ||
| struct NamespaceInfo : public Info {}; | ||
|
|
||
| // Info for symbols. | ||
| struct SymbolInfo : public Info { | ||
| llvm::Optional<Location> DefLoc; // Location where this decl is defined. | ||
| llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared. | ||
| }; | ||
|
|
||
| // TODO: Expand to allow for documenting templating and default args. | ||
| // Info for functions. | ||
| struct FunctionInfo : public SymbolInfo { | ||
| bool IsMethod = false; // Indicates whether this function is a class method. | ||
| Reference Parent; // Reference to the parent class decl for this method. | ||
| TypeInfo ReturnType; // Info about the return type of this function. | ||
| llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters. | ||
| AccessSpecifier Access = | ||
| AccessSpecifier::AS_none; // Access level for this method (public, | ||
| // private, protected, none). | ||
| }; | ||
|
|
||
| // TODO: Expand to allow for documenting templating, inheritance access, | ||
| // friend classes | ||
| // Info for types. | ||
| struct RecordInfo : public SymbolInfo { | ||
| TagTypeKind TagType = TagTypeKind::TTK_Struct; // Type of this record (struct, | ||
| // class, union, interface). | ||
| llvm::SmallVector<MemberTypeInfo, 4> | ||
| Members; // List of info about record members. | ||
| llvm::SmallVector<Reference, 4> Parents; // List of base/parent records (does | ||
| // not include virtual parents). | ||
| llvm::SmallVector<Reference, 4> | ||
| VirtualParents; // List of virtual base/parent records. | ||
| }; | ||
|
|
||
| // TODO: Expand to allow for documenting templating. | ||
| // Info for types. | ||
| struct EnumInfo : public SymbolInfo { | ||
| bool Scoped = | ||
| false; // Indicates whether this enum is scoped (e.g. enum class). | ||
| llvm::SmallVector<SmallString<16>, 4> Members; // List of enum members. | ||
| }; | ||
|
|
||
| // TODO: Add functionality to include separate markdown pages. | ||
|
|
||
| } // namespace doc | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,336 @@ | ||
| //===-- Serializer.cpp - ClangDoc Serializer --------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "Serialize.h" | ||
| #include "BitcodeWriter.h" | ||
| #include "clang/AST/Comment.h" | ||
| #include "clang/Index/USRGeneration.h" | ||
| #include "llvm/ADT/Hashing.h" | ||
| #include "llvm/ADT/StringExtras.h" | ||
| #include "llvm/Support/SHA1.h" | ||
|
|
||
| using clang::comments::FullComment; | ||
|
|
||
| namespace clang { | ||
| namespace doc { | ||
| namespace serialize { | ||
|
|
||
| SymbolID hashUSR(llvm::StringRef USR) { | ||
| return llvm::SHA1::hash(arrayRefFromStringRef(USR)); | ||
| } | ||
|
|
||
| class ClangDocCommentVisitor | ||
| : public ConstCommentVisitor<ClangDocCommentVisitor> { | ||
| public: | ||
| ClangDocCommentVisitor(CommentInfo &CI) : CurrentCI(CI) {} | ||
|
|
||
| void parseComment(const comments::Comment *C); | ||
|
|
||
| void visitTextComment(const TextComment *C); | ||
| void visitInlineCommandComment(const InlineCommandComment *C); | ||
| void visitHTMLStartTagComment(const HTMLStartTagComment *C); | ||
| void visitHTMLEndTagComment(const HTMLEndTagComment *C); | ||
| void visitBlockCommandComment(const BlockCommandComment *C); | ||
| void visitParamCommandComment(const ParamCommandComment *C); | ||
| void visitTParamCommandComment(const TParamCommandComment *C); | ||
| void visitVerbatimBlockComment(const VerbatimBlockComment *C); | ||
| void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C); | ||
| void visitVerbatimLineComment(const VerbatimLineComment *C); | ||
|
|
||
| private: | ||
| std::string getCommandName(unsigned CommandID) const; | ||
| bool isWhitespaceOnly(StringRef S) const; | ||
|
|
||
| CommentInfo &CurrentCI; | ||
| }; | ||
|
|
||
| void ClangDocCommentVisitor::parseComment(const comments::Comment *C) { | ||
| CurrentCI.Kind = C->getCommentKindName(); | ||
| ConstCommentVisitor<ClangDocCommentVisitor>::visit(C); | ||
| for (comments::Comment *Child : | ||
| llvm::make_range(C->child_begin(), C->child_end())) { | ||
| CurrentCI.Children.emplace_back(llvm::make_unique<CommentInfo>()); | ||
| ClangDocCommentVisitor Visitor(*CurrentCI.Children.back()); | ||
| Visitor.parseComment(Child); | ||
| } | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitTextComment(const TextComment *C) { | ||
| if (!isWhitespaceOnly(C->getText())) | ||
| CurrentCI.Text = C->getText(); | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitInlineCommandComment( | ||
| const InlineCommandComment *C) { | ||
| CurrentCI.Name = getCommandName(C->getCommandID()); | ||
| for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I) | ||
| CurrentCI.Args.push_back(C->getArgText(I)); | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitHTMLStartTagComment( | ||
| const HTMLStartTagComment *C) { | ||
| CurrentCI.Name = C->getTagName(); | ||
| CurrentCI.SelfClosing = C->isSelfClosing(); | ||
| for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) { | ||
| const HTMLStartTagComment::Attribute &Attr = C->getAttr(I); | ||
| CurrentCI.AttrKeys.push_back(Attr.Name); | ||
| CurrentCI.AttrValues.push_back(Attr.Value); | ||
| } | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitHTMLEndTagComment( | ||
| const HTMLEndTagComment *C) { | ||
| CurrentCI.Name = C->getTagName(); | ||
| CurrentCI.SelfClosing = true; | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitBlockCommandComment( | ||
| const BlockCommandComment *C) { | ||
| CurrentCI.Name = getCommandName(C->getCommandID()); | ||
| for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) | ||
| CurrentCI.Args.push_back(C->getArgText(I)); | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitParamCommandComment( | ||
| const ParamCommandComment *C) { | ||
| CurrentCI.Direction = | ||
| ParamCommandComment::getDirectionAsString(C->getDirection()); | ||
| CurrentCI.Explicit = C->isDirectionExplicit(); | ||
| if (C->hasParamName()) | ||
| CurrentCI.ParamName = C->getParamNameAsWritten(); | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitTParamCommandComment( | ||
| const TParamCommandComment *C) { | ||
| if (C->hasParamName()) | ||
| CurrentCI.ParamName = C->getParamNameAsWritten(); | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitVerbatimBlockComment( | ||
| const VerbatimBlockComment *C) { | ||
| CurrentCI.Name = getCommandName(C->getCommandID()); | ||
| CurrentCI.CloseName = C->getCloseName(); | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitVerbatimBlockLineComment( | ||
| const VerbatimBlockLineComment *C) { | ||
| if (!isWhitespaceOnly(C->getText())) | ||
| CurrentCI.Text = C->getText(); | ||
| } | ||
|
|
||
| void ClangDocCommentVisitor::visitVerbatimLineComment( | ||
| const VerbatimLineComment *C) { | ||
| if (!isWhitespaceOnly(C->getText())) | ||
| CurrentCI.Text = C->getText(); | ||
| } | ||
|
|
||
| bool ClangDocCommentVisitor::isWhitespaceOnly(llvm::StringRef S) const { | ||
| return std::all_of(S.begin(), S.end(), isspace); | ||
| } | ||
|
|
||
| std::string ClangDocCommentVisitor::getCommandName(unsigned CommandID) const { | ||
| const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID); | ||
| if (Info) | ||
| return Info->Name; | ||
| // TODO: Add parsing for \file command. | ||
| return "<not a builtin command>"; | ||
| } | ||
|
|
||
| // Serializing functions. | ||
|
|
||
| template <typename T> static std::string serialize(T &I) { | ||
| SmallString<2048> Buffer; | ||
| llvm::BitstreamWriter Stream(Buffer); | ||
| ClangDocBitcodeWriter Writer(Stream); | ||
| Writer.emitBlock(I); | ||
| return Buffer.str().str(); | ||
| } | ||
|
|
||
| static void parseFullComment(const FullComment *C, CommentInfo &CI) { | ||
| ClangDocCommentVisitor Visitor(CI); | ||
| Visitor.parseComment(C); | ||
| } | ||
|
|
||
| static SymbolID getUSRForDecl(const Decl *D) { | ||
| llvm::SmallString<128> USR; | ||
| if (index::generateUSRForDecl(D, USR)) | ||
| return SymbolID(); | ||
| return hashUSR(USR); | ||
| } | ||
|
|
||
| static RecordDecl *getDeclForType(const QualType &T) { | ||
| auto *Ty = T->getAs<RecordType>(); | ||
| if (!Ty) | ||
| return nullptr; | ||
| return Ty->getDecl()->getDefinition(); | ||
| } | ||
|
|
||
| static void parseFields(RecordInfo &I, const RecordDecl *D) { | ||
| for (const FieldDecl *F : D->fields()) { | ||
| // FIXME: Set Access to the appropriate value. | ||
| SymbolID Type; | ||
| std::string Name; | ||
| InfoType RefType; | ||
| if (const auto *T = getDeclForType(F->getTypeSourceInfo()->getType())) { | ||
| Type = getUSRForDecl(T); | ||
| if (dyn_cast<EnumDecl>(T)) | ||
| RefType = InfoType::IT_enum; | ||
| else if (dyn_cast<RecordDecl>(T)) | ||
| RefType = InfoType::IT_record; | ||
| I.Members.emplace_back(Type, RefType, F->getQualifiedNameAsString()); | ||
| } else { | ||
| Name = F->getTypeSourceInfo()->getType().getAsString(); | ||
| I.Members.emplace_back(Name, F->getQualifiedNameAsString()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static void parseEnumerators(EnumInfo &I, const EnumDecl *D) { | ||
| for (const EnumConstantDecl *E : D->enumerators()) | ||
| I.Members.emplace_back(E->getNameAsString()); | ||
| } | ||
|
|
||
| static void parseParameters(FunctionInfo &I, const FunctionDecl *D) { | ||
| for (const ParmVarDecl *P : D->parameters()) { | ||
| SymbolID Type; | ||
| std::string Name; | ||
| InfoType RefType; | ||
| if (const auto *T = getDeclForType(P->getOriginalType())) { | ||
| Type = getUSRForDecl(T); | ||
| if (dyn_cast<EnumDecl>(T)) | ||
| RefType = InfoType::IT_enum; | ||
| else if (dyn_cast<RecordDecl>(T)) | ||
| RefType = InfoType::IT_record; | ||
| I.Params.emplace_back(Type, RefType, P->getQualifiedNameAsString()); | ||
| } else { | ||
| Name = P->getOriginalType().getAsString(); | ||
| I.Params.emplace_back(Name, P->getQualifiedNameAsString()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static void parseBases(RecordInfo &I, const CXXRecordDecl *D) { | ||
| for (const CXXBaseSpecifier &B : D->bases()) { | ||
| if (B.isVirtual()) | ||
| continue; | ||
| if (const auto *P = getDeclForType(B.getType())) | ||
| I.Parents.emplace_back(getUSRForDecl(P), InfoType::IT_record); | ||
| else | ||
| I.Parents.emplace_back(B.getType().getAsString()); | ||
| } | ||
| for (const CXXBaseSpecifier &B : D->vbases()) { | ||
| if (const auto *P = getDeclForType(B.getType())) | ||
| I.VirtualParents.emplace_back(getUSRForDecl(P), InfoType::IT_record); | ||
| else | ||
| I.VirtualParents.emplace_back(B.getType().getAsString()); | ||
| } | ||
| } | ||
|
|
||
| template <typename T> | ||
| static void | ||
| populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces, | ||
| const T *D) { | ||
| const auto *DC = dyn_cast<DeclContext>(D); | ||
| while ((DC = DC->getParent())) { | ||
| if (const auto *N = dyn_cast<NamespaceDecl>(DC)) | ||
| Namespaces.emplace_back(getUSRForDecl(N), InfoType::IT_namespace); | ||
| else if (const auto *N = dyn_cast<RecordDecl>(DC)) | ||
| Namespaces.emplace_back(getUSRForDecl(N), InfoType::IT_record); | ||
| else if (const auto *N = dyn_cast<FunctionDecl>(DC)) | ||
| Namespaces.emplace_back(getUSRForDecl(N), InfoType::IT_function); | ||
| else if (const auto *N = dyn_cast<EnumDecl>(DC)) | ||
| Namespaces.emplace_back(getUSRForDecl(N), InfoType::IT_enum); | ||
| } | ||
| } | ||
|
|
||
| template <typename T> | ||
| static void populateInfo(Info &I, const T *D, const FullComment *C) { | ||
| I.USR = getUSRForDecl(D); | ||
| I.Name = D->getNameAsString(); | ||
| populateParentNamespaces(I.Namespace, D); | ||
| if (C) { | ||
| I.Description.emplace_back(); | ||
| parseFullComment(C, I.Description.back()); | ||
| } | ||
| } | ||
|
|
||
| template <typename T> | ||
| static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, | ||
| int LineNumber, StringRef Filename) { | ||
| populateInfo(I, D, C); | ||
| if (D->isThisDeclarationADefinition()) | ||
| I.DefLoc.emplace(LineNumber, Filename); | ||
| else | ||
| I.Loc.emplace_back(LineNumber, Filename); | ||
| } | ||
|
|
||
| static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, | ||
| const FullComment *FC, int LineNumber, | ||
| StringRef Filename) { | ||
| populateSymbolInfo(I, D, FC, LineNumber, Filename); | ||
| if (const auto *T = getDeclForType(D->getReturnType())) { | ||
| I.ReturnType.Type.USR = getUSRForDecl(T); | ||
| if (dyn_cast<EnumDecl>(T)) | ||
| I.ReturnType.Type.RefType = InfoType::IT_enum; | ||
| else if (dyn_cast<RecordDecl>(T)) | ||
| I.ReturnType.Type.RefType = InfoType::IT_record; | ||
| } else { | ||
| I.ReturnType.Type.UnresolvedName = D->getReturnType().getAsString(); | ||
| } | ||
| parseParameters(I, D); | ||
| } | ||
|
|
||
| std::string emitInfo(const NamespaceDecl *D, const FullComment *FC, | ||
| int LineNumber, llvm::StringRef File) { | ||
| NamespaceInfo I; | ||
| populateInfo(I, D, FC); | ||
| return serialize(I); | ||
| } | ||
|
|
||
| std::string emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, | ||
| llvm::StringRef File) { | ||
| RecordInfo I; | ||
| populateSymbolInfo(I, D, FC, LineNumber, File); | ||
| I.TagType = D->getTagKind(); | ||
| parseFields(I, D); | ||
| if (const auto *C = dyn_cast<CXXRecordDecl>(D)) | ||
| parseBases(I, C); | ||
| return serialize(I); | ||
| } | ||
|
|
||
| std::string emitInfo(const FunctionDecl *D, const FullComment *FC, | ||
| int LineNumber, llvm::StringRef File) { | ||
| FunctionInfo I; | ||
| populateFunctionInfo(I, D, FC, LineNumber, File); | ||
| I.Access = clang::AccessSpecifier::AS_none; | ||
| return serialize(I); | ||
| } | ||
|
|
||
| std::string emitInfo(const CXXMethodDecl *D, const FullComment *FC, | ||
| int LineNumber, llvm::StringRef File) { | ||
| FunctionInfo I; | ||
| populateFunctionInfo(I, D, FC, LineNumber, File); | ||
| I.IsMethod = true; | ||
| I.Parent = Reference(getUSRForDecl(D->getParent()), InfoType::IT_record); | ||
| I.Access = D->getAccess(); | ||
| return serialize(I); | ||
| } | ||
|
|
||
| std::string emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, | ||
| llvm::StringRef File) { | ||
| EnumInfo I; | ||
| populateSymbolInfo(I, D, FC, LineNumber, File); | ||
| I.Scoped = D->isScoped(); | ||
| parseEnumerators(I, D); | ||
| return serialize(I); | ||
| } | ||
|
|
||
| } // namespace serialize | ||
| } // namespace doc | ||
| } // namespace clang |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| //===-- Serializer.h - ClangDoc Serializer ----------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file implements the serializing functions fro the clang-doc tool. Given | ||
| // a particular declaration, it collects the appropriate information and returns | ||
| // a serialized bitcode string for the declaration. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_SERIALIZE_H | ||
| #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_SERIALIZE_H | ||
|
|
||
| #include "Representation.h" | ||
| #include "clang/AST/AST.h" | ||
| #include "clang/AST/CommentVisitor.h" | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| using namespace clang::comments; | ||
|
|
||
| namespace clang { | ||
| namespace doc { | ||
| namespace serialize { | ||
|
|
||
| std::string emitInfo(const NamespaceDecl *D, const FullComment *FC, | ||
| int LineNumber, StringRef File); | ||
| std::string emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, | ||
| StringRef File); | ||
| std::string emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, | ||
| StringRef File); | ||
| std::string emitInfo(const FunctionDecl *D, const FullComment *FC, | ||
| int LineNumber, StringRef File); | ||
| std::string emitInfo(const CXXMethodDecl *D, const FullComment *FC, | ||
| int LineNumber, StringRef File); | ||
|
|
||
| // 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 | ||
| // guarantee the uniqueness of symbols while using a relatively small amount of | ||
| // memory (vs storing USRs directly). | ||
| SymbolID hashUSR(llvm::StringRef USR); | ||
|
|
||
| } // namespace serialize | ||
| } // namespace doc | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_SERIALIZE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) | ||
|
|
||
| add_clang_executable(clang-doc | ||
| ClangDocMain.cpp | ||
| ) | ||
|
|
||
| target_link_libraries(clang-doc | ||
| PRIVATE | ||
| clangAST | ||
| clangASTMatchers | ||
| clangBasic | ||
| clangFrontend | ||
| clangDoc | ||
| clangTooling | ||
| clangToolingCore | ||
| ) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| //===-- ClangDocMain.cpp - ClangDoc -----------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This tool for generating C and C++ documenation from source code | ||
| // and comments. Generally, it runs a LibTooling FrontendAction on source files, | ||
| // mapping each declaration in those files to its USR and serializing relevant | ||
| // information into LLVM bitcode. It then runs a pass over the collected | ||
| // declaration information, reducing by USR. There is an option to dump this | ||
| // intermediate result to bitcode. Finally, it hands the reduced information | ||
| // off to a generator, which does the final parsing from the intermediate | ||
| // representation to the desired output format. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "ClangDoc.h" | ||
| #include "clang/AST/AST.h" | ||
| #include "clang/AST/Decl.h" | ||
| #include "clang/ASTMatchers/ASTMatchFinder.h" | ||
| #include "clang/ASTMatchers/ASTMatchersInternal.h" | ||
| #include "clang/Driver/Options.h" | ||
| #include "clang/Frontend/FrontendActions.h" | ||
| #include "clang/Tooling/CommonOptionsParser.h" | ||
| #include "clang/Tooling/Execution.h" | ||
| #include "clang/Tooling/StandaloneExecution.h" | ||
| #include "clang/Tooling/Tooling.h" | ||
| #include "llvm/ADT/APFloat.h" | ||
| #include "llvm/Support/FileSystem.h" | ||
| #include "llvm/Support/Path.h" | ||
| #include "llvm/Support/Process.h" | ||
| #include "llvm/Support/Signals.h" | ||
| #include "llvm/Support/raw_ostream.h" | ||
| #include <string> | ||
|
|
||
| using namespace clang::ast_matchers; | ||
| using namespace clang::tooling; | ||
| using namespace clang; | ||
|
|
||
| static llvm::cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); | ||
| static llvm::cl::OptionCategory ClangDocCategory("clang-doc options"); | ||
|
|
||
| static llvm::cl::opt<std::string> | ||
| OutDirectory("output", | ||
| llvm::cl::desc("Directory for outputting generated files."), | ||
| llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory)); | ||
|
|
||
| static llvm::cl::opt<bool> | ||
| DumpMapperResult("dump-mapper", | ||
| llvm::cl::desc("Dump mapper results to bitcode file."), | ||
| llvm::cl::init(false), llvm::cl::cat(ClangDocCategory)); | ||
|
|
||
| static llvm::cl::opt<bool> DoxygenOnly( | ||
| "doxygen", | ||
| llvm::cl::desc("Use only doxygen-style comments to generate docs."), | ||
| llvm::cl::init(false), llvm::cl::cat(ClangDocCategory)); | ||
|
|
||
| int main(int argc, const char **argv) { | ||
| llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); | ||
| std::error_code OK; | ||
|
|
||
| auto Exec = clang::tooling::createExecutorFromCommandLineArgs( | ||
| argc, argv, ClangDocCategory); | ||
|
|
||
| if (!Exec) { | ||
| llvm::errs() << toString(Exec.takeError()) << "\n"; | ||
| return 1; | ||
| } | ||
|
|
||
| ArgumentsAdjuster ArgAdjuster; | ||
| if (!DoxygenOnly) | ||
| ArgAdjuster = combineAdjusters( | ||
| getInsertArgumentAdjuster("-fparse-all-comments", | ||
| tooling::ArgumentInsertPosition::END), | ||
| ArgAdjuster); | ||
|
|
||
| // Mapping phase | ||
| llvm::outs() << "Mapping decls...\n"; | ||
| auto Err = Exec->get()->execute(doc::newMapperActionFactory( | ||
| Exec->get()->getExecutionContext()), | ||
| ArgAdjuster); | ||
| if (Err) | ||
| llvm::errs() << toString(std::move(Err)) << "\n"; | ||
|
|
||
| if (DumpMapperResult) { | ||
| Exec->get()->getToolResults()->forEachResult([&](StringRef Key, | ||
| StringRef Value) { | ||
| SmallString<128> IRRootPath; | ||
| llvm::sys::path::native(OutDirectory, IRRootPath); | ||
| llvm::sys::path::append(IRRootPath, "bc"); | ||
| std::error_code DirectoryStatus = | ||
| llvm::sys::fs::create_directories(IRRootPath); | ||
| if (DirectoryStatus != OK) { | ||
| llvm::errs() << "Unable to create documentation directories.\n"; | ||
| return; | ||
| } | ||
| llvm::sys::path::append(IRRootPath, Key + ".bc"); | ||
| std::error_code OutErrorInfo; | ||
| llvm::raw_fd_ostream OS(IRRootPath, OutErrorInfo, llvm::sys::fs::F_None); | ||
| if (OutErrorInfo != OK) { | ||
| llvm::errs() << "Error opening documentation file.\n"; | ||
| return; | ||
| } | ||
| OS << Value; | ||
| OS.close(); | ||
| }); | ||
| } | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/641AB4A3D36399954ACDE29C7A8833032BF40472.bc --dump | FileCheck %s --check-prefix CHECK-X-Y | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/CA7C7935730B5EACD25F080E9C83FA087CCDC75E.bc --dump | FileCheck %s --check-prefix CHECK-X | ||
|
|
||
| class X { | ||
| class Y {}; | ||
| }; | ||
|
|
||
| // CHECK-X: <BLOCKINFO_BLOCK/> | ||
| // CHECK-X-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-X-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-X-NEXT: </VersionBlock> | ||
| // CHECK-X-NEXT: <RecordBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-X-NEXT: <USR abbrevid=4 op0=20 op1=202 op2=124 op3=121 op4=53 op5=115 op6=11 op7=94 op8=172 op9=210 op10=95 op11=8 op12=14 op13=156 op14=131 op15=250 op16=8 op17=124 op18=205 op19=199 op20=94/> | ||
| // CHECK-X-NEXT: <Name abbrevid=5 op0=1/> blob data = 'X' | ||
| // CHECK-X-NEXT: <DefLocation abbrevid=7 op0=9 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-X-NEXT: <TagType abbrevid=9 op0=3/> | ||
| // CHECK-X-NEXT: </RecordBlock> | ||
|
|
||
|
|
||
| // CHECK-X-Y: <BLOCKINFO_BLOCK/> | ||
| // CHECK-X-Y-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-X-Y-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-X-Y-NEXT: </VersionBlock> | ||
| // CHECK-X-Y-NEXT: <RecordBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-X-Y-NEXT: <USR abbrevid=4 op0=20 op1=100 op2=26 op3=180 op4=163 op5=211 op6=99 op7=153 op8=149 op9=74 op10=205 op11=226 op12=156 op13=122 op14=136 op15=51 op16=3 op17=43 op18=244 op19=4 op20=114/> | ||
| // CHECK-X-Y-NEXT: <Name abbrevid=5 op0=1/> blob data = 'Y' | ||
| // CHECK-X-Y-NEXT: <Namespace abbrevid=6 op0=1 op1=40/> blob data = 'CA7C7935730B5EACD25F080E9C83FA087CCDC75E' | ||
| // CHECK-X-Y-NEXT: <DefLocation abbrevid=7 op0=10 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-X-Y-NEXT: <TagType abbrevid=9 op0=3/> | ||
| // CHECK-X-Y-NEXT: </RecordBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // This test requires Linux due to the system-dependent USR for the | ||
| // inner class. | ||
| // REQUIRES: system-linux | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E.bc --dump | FileCheck %s --check-prefix CHECK-H | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/01A95F3F73F53281B3E50109A577FD2493159365.bc --dump | FileCheck %s --check-prefix CHECK-H-I | ||
|
|
||
| void H() { | ||
| class I {}; | ||
| } | ||
|
|
||
| // CHECK-H: <BLOCKINFO_BLOCK/> | ||
| // CHECK-H-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-H-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-H-NEXT: </VersionBlock> | ||
| // CHECK-H-NEXT: <FunctionBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-H-NEXT: <USR abbrevid=4 op0=20 op1=182 op2=172 op3=76 op4=92 op5=159 op6=46 op7=163 op8=242 op9=179 op10=236 op11=225 op12=163 op13=61 op14=52 op15=159 op16=78 op17=229 op18=2 op19=178 op20=78/> | ||
| // CHECK-H-NEXT: <Name abbrevid=5 op0=1/> blob data = 'H' | ||
| // CHECK-H-NEXT: <DefLocation abbrevid=7 op0=12 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-H-NEXT: <TypeBlock NumWords=4 BlockCodeSize=4> | ||
| // CHECK-H-NEXT: <Type abbrevid=4 op0=4 op1=4/> blob data = 'void' | ||
| // CHECK-H-NEXT: </TypeBlock> | ||
| // CHECK-H-NEXT: </FunctionBlock> | ||
|
|
||
| // CHECK-H-I: <BLOCKINFO_BLOCK/> | ||
| // CHECK-H-I-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-H-I-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-H-I-NEXT: </VersionBlock> | ||
| // CHECK-H-I-NEXT: <RecordBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-H-I-NEXT: <USR abbrevid=4 op0=20 op1=1 op2=169 op3=95 op4=63 op5=115 op6=245 op7=50 op8=129 op9=179 op10=229 op11=1 op12=9 op13=165 op14=119 op15=253 op16=36 op17=147 op18=21 op19=147 op20=101/> | ||
| // CHECK-H-I-NEXT: <Name abbrevid=5 op0=1/> blob data = 'I' | ||
| // CHECK-H-I-NEXT: <Namespace abbrevid=6 op0=2 op1=40/> blob data = 'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E' | ||
| // CHECK-H-I-NEXT: <DefLocation abbrevid=7 op0=13 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-H-I-NEXT: <TagType abbrevid=9 op0=3/> | ||
| // CHECK-H-I-NEXT: </RecordBlock> | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/289584A8E0FF4178A794622A547AA622503967A1.bc --dump | FileCheck %s | ||
|
|
||
| class E {}; | ||
|
|
||
| // CHECK: <BLOCKINFO_BLOCK/> | ||
| // CHECK-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-NEXT: </VersionBlock> | ||
| // CHECK-NEXT: <RecordBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-NEXT: <USR abbrevid=4 op0=20 op1=40 op2=149 op3=132 op4=168 op5=224 op6=255 op7=65 op8=120 op9=167 op10=148 op11=98 op12=42 op13=84 op14=122 op15=166 op16=34 op17=80 op18=57 op19=103 op20=161/> | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'E' | ||
| // CHECK-NEXT: <DefLocation abbrevid=7 op0=8 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-NEXT: <TagType abbrevid=9 op0=3/> | ||
| // CHECK-NEXT: </RecordBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/7574630614A535710E5A6ABCFFF98BCA2D06A4CA.bc --dump | FileCheck %s | ||
|
|
||
| /// \brief Brief description. | ||
| /// | ||
| /// Extended description that | ||
| /// continues onto the next line. | ||
| /// | ||
| /// <ul> class="test"> | ||
| /// <li> Testing. | ||
| /// </ul> | ||
| /// | ||
| /// \verbatim | ||
| /// The description continues. | ||
| /// \endverbatim | ||
| /// | ||
| /// \param [out] I is a parameter. | ||
| /// \param J is a parameter. | ||
| /// \return int | ||
| int F(int I, int J); | ||
|
|
||
| // CHECK: <BLOCKINFO_BLOCK/> | ||
| // CHECK-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-NEXT: </VersionBlock> | ||
| // CHECK-NEXT: <FunctionBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-NEXT: <USR abbrevid=4 op0=20 op1=117 op2=116 op3=99 op4=6 op5=20 op6=165 op7=53 op8=113 op9=14 op10=90 op11=106 op12=188 op13=255 op14=249 op15=139 op16=202 op17=45 op18=6 op19=164 op20=202/> | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'F' | ||
| // CHECK-NEXT: <CommentBlock NumWords=351 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'FullComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=13 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=31 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=19/> blob data = 'BlockCommandComment' | ||
| // CHECK-NEXT: <Name abbrevid=6 op0=5/> blob data = 'brief' | ||
| // CHECK-NEXT: <CommentBlock NumWords=19 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=11 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=19/> blob data = ' Brief description.' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=37 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=13 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=26/> blob data = ' Extended description that' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=14 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=30/> blob data = ' continues onto the next line.' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=83 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=9 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=19/> blob data = 'HTMLStartTagComment' | ||
| // CHECK-NEXT: <Name abbrevid=6 op0=2/> blob data = 'ul' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=10 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=14/> blob data = ' class="test">' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=9 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=19/> blob data = 'HTMLStartTagComment' | ||
| // CHECK-NEXT: <Name abbrevid=6 op0=2/> blob data = 'li' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=9 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=9/> blob data = ' Testing.' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=9 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=17/> blob data = 'HTMLEndTagComment' | ||
| // CHECK-NEXT: <Name abbrevid=6 op0=2/> blob data = 'ul' | ||
| // CHECK-NEXT: <SelfClosing abbrevid=10 op0=1/> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=13 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=32 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=20/> blob data = 'VerbatimBlockComment' | ||
| // CHECK-NEXT: <Name abbrevid=6 op0=8/> blob data = 'verbatim' | ||
| // CHECK-NEXT: <CloseName abbrevid=9 op0=11/> blob data = 'endverbatim' | ||
| // CHECK-NEXT: <CommentBlock NumWords=16 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=24/> blob data = 'VerbatimBlockLineComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=27/> blob data = ' The description continues.' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=13 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=39 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=19/> blob data = 'ParamCommandComment' | ||
| // CHECK-NEXT: <Direction abbrevid=7 op0=5/> blob data = '[out]' | ||
| // CHECK-NEXT: <ParamName abbrevid=8 op0=1/> blob data = 'I' | ||
| // CHECK-NEXT: <Explicit abbrevid=11 op0=1/> | ||
| // CHECK-NEXT: <CommentBlock NumWords=25 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=10 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=16/> blob data = ' is a parameter.' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=38 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=19/> blob data = 'ParamCommandComment' | ||
| // CHECK-NEXT: <Direction abbrevid=7 op0=4/> blob data = '[in]' | ||
| // CHECK-NEXT: <ParamName abbrevid=8 op0=1/> blob data = 'J' | ||
| // CHECK-NEXT: <CommentBlock NumWords=25 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=10 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=16/> blob data = ' is a parameter.' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=5 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <CommentBlock NumWords=27 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=19/> blob data = 'BlockCommandComment' | ||
| // CHECK-NEXT: <Name abbrevid=6 op0=6/> blob data = 'return' | ||
| // CHECK-NEXT: <CommentBlock NumWords=15 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=16/> blob data = 'ParagraphComment' | ||
| // CHECK-NEXT: <CommentBlock NumWords=7 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Kind abbrevid=4 op0=11/> blob data = 'TextComment' | ||
| // CHECK-NEXT: <Text abbrevid=5 op0=4/> blob data = ' int' | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: </CommentBlock> | ||
| // CHECK-NEXT: <Location abbrevid=8 op0=24 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-NEXT: <TypeBlock NumWords=4 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: </TypeBlock> | ||
| // CHECK-NEXT: <FieldTypeBlock NumWords=6 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'I' | ||
| // CHECK-NEXT: </FieldTypeBlock> | ||
| // CHECK-NEXT: <FieldTypeBlock NumWords=6 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'J' | ||
| // CHECK-NEXT: </FieldTypeBlock> | ||
| // CHECK-NEXT: </FunctionBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/FC07BD34D5E77782C263FA944447929EA8753740.bc --dump | FileCheck %s --check-prefix CHECK-B | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/020E6C32A700C3170C009FCCD41671EDDBEAF575.bc --dump | FileCheck %s --check-prefix CHECK-C | ||
|
|
||
| enum B { X, Y }; | ||
|
|
||
| // CHECK-B: <BLOCKINFO_BLOCK/> | ||
| // CHECK-B-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-B-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-B-NEXT: </VersionBlock> | ||
| // CHECK-B-NEXT: <EnumBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-B-NEXT: <USR abbrevid=4 op0=20 op1=252 op2=7 op3=189 op4=52 op5=213 op6=231 op7=119 op8=130 op9=194 op10=99 op11=250 op12=148 op13=68 op14=71 op15=146 op16=158 op17=168 op18=117 op19=55 op20=64/> | ||
| // CHECK-B-NEXT: <Name abbrevid=5 op0=1/> blob data = 'B' | ||
| // CHECK-B-NEXT: <DefLocation abbrevid=7 op0=9 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-B-NEXT: <Member abbrevid=9 op0=1/> blob data = 'X' | ||
| // CHECK-B-NEXT: <Member abbrevid=9 op0=1/> blob data = 'Y' | ||
| // CHECK-B-NEXT: </EnumBlock> | ||
|
|
||
| enum class C { A, B }; | ||
|
|
||
| // CHECK-C: <BLOCKINFO_BLOCK/> | ||
| // CHECK-C-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-C-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-C-NEXT: </VersionBlock> | ||
| // CHECK-C-NEXT: <EnumBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-C-NEXT: <USR abbrevid=4 op0=20 op1=2 op2=14 op3=108 op4=50 op5=167 op6=0 op7=195 op8=23 op9=12 op10=0 op11=159 op12=204 op13=212 op14=22 op15=113 op16=237 op17=219 op18=234 op19=245 op20=117/> | ||
| // CHECK-C-NEXT: <Name abbrevid=5 op0=1/> blob data = 'C' | ||
| // CHECK-C-NEXT: <DefLocation abbrevid=7 op0=23 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-C-NEXT: <Scoped abbrevid=10 op0=1/> | ||
| // CHECK-C-NEXT: <Member abbrevid=9 op0=1/> blob data = 'A' | ||
| // CHECK-C-NEXT: <Member abbrevid=9 op0=1/> blob data = 'B' | ||
| // CHECK-C-NEXT: </EnumBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/A44B32CC3C087C9AF75DAF50DE193E85E7B2C16B.bc --dump | FileCheck %s | ||
|
|
||
| int F(int param) { return param; } | ||
|
|
||
| // CHECK: <BLOCKINFO_BLOCK/> | ||
| // CHECK-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-NEXT: </VersionBlock> | ||
| // CHECK-NEXT: <FunctionBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-NEXT: <USR abbrevid=4 op0=20 op1=164 op2=75 op3=50 op4=204 op5=60 op6=8 op7=124 op8=154 op9=247 op10=93 op11=175 op12=80 op13=222 op14=25 op15=62 op16=133 op17=231 op18=178 op19=193 op20=107/> | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'F' | ||
| // CHECK-NEXT: <DefLocation abbrevid=7 op0=8 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-NEXT: <TypeBlock NumWords=4 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: </TypeBlock> | ||
| // CHECK-NEXT: <FieldTypeBlock NumWords=7 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=5/> blob data = 'param' | ||
| // CHECK-NEXT: </FieldTypeBlock> | ||
| // CHECK-NEXT: </FunctionBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/F0F9FC65FC90F54F690144A7AFB15DFC3D69B6E6.bc --dump | FileCheck %s --check-prefix CHECK-G-F | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/4202E8BF0ECB12AE354C8499C52725B0EE30AED5.bc --dump | FileCheck %s --check-prefix CHECK-G | ||
|
|
||
| class G { | ||
| public: | ||
| int Method(int param) { return param; } | ||
| }; | ||
|
|
||
| // CHECK-G: <BLOCKINFO_BLOCK/> | ||
| // CHECK-G-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-G-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-G-NEXT: </VersionBlock> | ||
| // CHECK-G-NEXT: <RecordBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-G-NEXT: <USR abbrevid=4 op0=20 op1=66 op2=2 op3=232 op4=191 op5=14 op6=203 op7=18 op8=174 op9=53 op10=76 op11=132 op12=153 op13=197 op14=39 op15=37 op16=176 op17=238 op18=48 op19=174 op20=213/> | ||
| // CHECK-G-NEXT: <Name abbrevid=5 op0=1/> blob data = 'G' | ||
| // CHECK-G-NEXT: <DefLocation abbrevid=7 op0=9 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-G-NEXT: <TagType abbrevid=9 op0=3/> | ||
| // CHECK-G-NEXT: </RecordBlock> | ||
|
|
||
| // CHECK-G-F: <BLOCKINFO_BLOCK/> | ||
| // CHECK-G-F-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-G-F-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-G-F-NEXT: </VersionBlock> | ||
| // CHECK-G-F-NEXT: <FunctionBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-G-F-NEXT: <USR abbrevid=4 op0=20 op1=240 op2=249 op3=252 op4=101 op5=252 op6=144 op7=245 op8=79 op9=105 op10=1 op11=68 op12=167 op13=175 op14=177 op15=93 op16=252 op17=61 op18=105 op19=182 op20=230/> | ||
| // CHECK-G-F-NEXT: <Name abbrevid=5 op0=6/> blob data = 'Method' | ||
| // CHECK-G-F-NEXT: <Namespace abbrevid=6 op0=1 op1=40/> blob data = '4202E8BF0ECB12AE354C8499C52725B0EE30AED5' | ||
| // CHECK-G-F-NEXT: <IsMethod abbrevid=11 op0=1/> | ||
| // CHECK-G-F-NEXT: <DefLocation abbrevid=7 op0=11 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-G-F-NEXT: <Parent abbrevid=9 op0=1 op1=40/> blob data = '4202E8BF0ECB12AE354C8499C52725B0EE30AED5' | ||
| // CHECK-G-F-NEXT: <TypeBlock NumWords=4 BlockCodeSize=4> | ||
| // CHECK-G-F-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-G-F-NEXT: </TypeBlock> | ||
| // CHECK-G-F-NEXT: <FieldTypeBlock NumWords=7 BlockCodeSize=4> | ||
| // CHECK-G-F-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-G-F-NEXT: <Name abbrevid=5 op0=5/> blob data = 'param' | ||
| // CHECK-G-F-NEXT: </FieldTypeBlock> | ||
| // CHECK-G-F-NEXT: </FunctionBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/8D042EFFC98B373450BC6B5B90A330C25A150E9C.bc --dump | FileCheck %s | ||
|
|
||
| namespace A {} | ||
|
|
||
| // CHECK: <BLOCKINFO_BLOCK/> | ||
| // CHECK-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-NEXT: </VersionBlock> | ||
| // CHECK-NEXT: <NamespaceBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-NEXT: <USR abbrevid=4 op0=20 op1=141 op2=4 op3=46 op4=255 op5=201 op6=139 op7=55 op8=52 op9=80 op10=188 op11=107 op12=91 op13=144 op14=163 op15=48 op16=194 op17=90 op18=21 op19=14 op20=156/> | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'A' | ||
| // CHECK-NEXT: </NamespaceBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/06B5F6A19BA9F6A832E127C9968282B94619B210.bc --dump | FileCheck %s | ||
|
|
||
| struct C { int i; }; | ||
|
|
||
| // CHECK: <BLOCKINFO_BLOCK/> | ||
| // CHECK-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-NEXT: </VersionBlock> | ||
| // CHECK-NEXT: <RecordBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-NEXT: <USR abbrevid=4 op0=20 op1=6 op2=181 op3=246 op4=161 op5=155 op6=169 op7=246 op8=168 op9=50 op10=225 op11=39 op12=201 op13=150 op14=130 op15=130 op16=185 op17=70 op18=25 op19=178 op20=16/> | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'C' | ||
| // CHECK-NEXT: <DefLocation abbrevid=7 op0=8 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-NEXT: <MemberTypeBlock NumWords=6 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=4/> blob data = 'C::i' | ||
| // CHECK-NEXT: <Access abbrevid=6 op0=3/> | ||
| // CHECK-NEXT: </MemberTypeBlock> | ||
| // CHECK-NEXT: </RecordBlock> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: mkdir %t | ||
| // RUN: echo "" > %t/compile_flags.txt | ||
| // RUN: cp "%s" "%t/test.cpp" | ||
| // RUN: clang-doc --dump-mapper -doxygen -p %t %t/test.cpp -output=%t/docs | ||
| // RUN: llvm-bcanalyzer %t/docs/bc/0B8A6B938B939B77C6325CCCC8AA3E938BF9E2E8.bc --dump | FileCheck %s | ||
|
|
||
| union D { int X; int Y; }; | ||
|
|
||
| // CHECK: <BLOCKINFO_BLOCK/> | ||
| // CHECK-NEXT: <VersionBlock NumWords=1 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Version abbrevid=4 op0=1/> | ||
| // CHECK-NEXT: </VersionBlock> | ||
| // CHECK-NEXT: <RecordBlock NumWords={{[0-9]*}} BlockCodeSize=4> | ||
| // CHECK-NEXT: <USR abbrevid=4 op0=20 op1=11 op2=138 op3=107 op4=147 op5=139 op6=147 op7=155 op8=119 op9=198 op10=50 op11=92 op12=204 op13=200 op14=170 op15=62 op16=147 op17=139 op18=249 op19=226 op20=232/> | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=1/> blob data = 'D' | ||
| // CHECK-NEXT: <DefLocation abbrevid=7 op0=8 op1={{[0-9]*}}/> blob data = '{{.*}}' | ||
| // CHECK-NEXT: <TagType abbrevid=9 op0=2/> | ||
| // CHECK-NEXT: <MemberTypeBlock NumWords=6 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=4/> blob data = 'D::X' | ||
| // CHECK-NEXT: <Access abbrevid=6 op0=3/> | ||
| // CHECK-NEXT: </MemberTypeBlock> | ||
| // CHECK-NEXT: <MemberTypeBlock NumWords=6 BlockCodeSize=4> | ||
| // CHECK-NEXT: <Type abbrevid=4 op0=4 op1=3/> blob data = 'int' | ||
| // CHECK-NEXT: <Name abbrevid=5 op0=4/> blob data = 'D::Y' | ||
| // CHECK-NEXT: <Access abbrevid=6 op0=3/> | ||
| // CHECK-NEXT: </MemberTypeBlock> | ||
| // CHECK-NEXT: </RecordBlock> |