forked from OSchip/llvm-project
[clang-doc] Implement a YAML generator
Implmenting a YAML generator from the emitted bitcode summary of declarations. Emits one YAML file for each declaration information. For a more detailed overview of the tool, see the design document on the mailing list: http://lists.llvm.org/pipermail/cfe-dev/2017-December/056203.html llvm-svn: 334103
This commit is contained in:
parent
381072c417
commit
e78f30183e
|
@ -8,9 +8,11 @@ add_clang_library(clangDoc
|
|||
BitcodeReader.cpp
|
||||
BitcodeWriter.cpp
|
||||
ClangDoc.cpp
|
||||
Generators.cpp
|
||||
Mapper.cpp
|
||||
Representation.cpp
|
||||
Serialize.cpp
|
||||
YAMLGenerator.cpp
|
||||
|
||||
LINK_LIBS
|
||||
clangAnalysis
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
//===---- Generator.cpp - Generator Registry ---------------------*- C++-*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Generators.h"
|
||||
|
||||
LLVM_INSTANTIATE_REGISTRY(clang::doc::GeneratorRegistry)
|
||||
|
||||
namespace clang {
|
||||
namespace doc {
|
||||
|
||||
llvm::Expected<std::unique_ptr<Generator>>
|
||||
findGeneratorByName(llvm::StringRef Format) {
|
||||
for (auto I = GeneratorRegistry::begin(), E = GeneratorRegistry::end();
|
||||
I != E; ++I) {
|
||||
if (I->getName() != Format)
|
||||
continue;
|
||||
return I->instantiate();
|
||||
}
|
||||
return llvm::make_error<llvm::StringError>("Can't find generator: " + Format,
|
||||
llvm::inconvertibleErrorCode());
|
||||
}
|
||||
|
||||
// This anchor is used to force the linker to link in the generated object file
|
||||
// and thus register the generators.
|
||||
extern volatile int YAMLGeneratorAnchorSource;
|
||||
static int LLVM_ATTRIBUTE_UNUSED YAMLGeneratorAnchorDest =
|
||||
YAMLGeneratorAnchorSource;
|
||||
|
||||
} // namespace doc
|
||||
} // namespace clang
|
|
@ -0,0 +1,41 @@
|
|||
//===-- Generators.h - ClangDoc Generator ----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Generator classes for converting declaration information into documentation
|
||||
// in a specified format.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
|
||||
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
|
||||
|
||||
#include "Representation.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Registry.h"
|
||||
|
||||
namespace clang {
|
||||
namespace doc {
|
||||
|
||||
// Abstract base class for generators.
|
||||
// This is expected to be implemented and exposed via the GeneratorRegistry.
|
||||
class Generator {
|
||||
public:
|
||||
virtual ~Generator() = default;
|
||||
|
||||
// Write out the decl info in the specified format.
|
||||
virtual bool generateDocForInfo(Info *I, llvm::raw_ostream &OS) = 0;
|
||||
};
|
||||
|
||||
typedef llvm::Registry<Generator> GeneratorRegistry;
|
||||
|
||||
llvm::Expected<std::unique_ptr<Generator>>
|
||||
findGeneratorByName(llvm::StringRef Format);
|
||||
|
||||
} // namespace doc
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
|
|
@ -73,6 +73,11 @@ struct Reference {
|
|||
Reference(SymbolID USR, StringRef Name, InfoType IT)
|
||||
: USR(USR), Name(Name), RefType(IT) {}
|
||||
|
||||
bool operator==(const Reference &Other) const {
|
||||
return std::tie(USR, Name, RefType) ==
|
||||
std::tie(Other.USR, Other.Name, Other.RefType);
|
||||
}
|
||||
|
||||
SymbolID USR = SymbolID(); // Unique identifer for referenced decl
|
||||
SmallString<16> Name; // Name of type (possibly unresolved).
|
||||
InfoType RefType = InfoType::IT_default; // Indicates the type of this
|
||||
|
@ -87,6 +92,8 @@ struct TypeInfo {
|
|||
: Type(Type, Field, IT) {}
|
||||
TypeInfo(llvm::StringRef RefName) : Type(RefName) {}
|
||||
|
||||
bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
|
||||
|
||||
Reference Type; // Referenced type in this info.
|
||||
};
|
||||
|
||||
|
@ -99,6 +106,10 @@ struct FieldTypeInfo : public TypeInfo {
|
|||
FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name)
|
||||
: TypeInfo(RefName), Name(Name) {}
|
||||
|
||||
bool operator==(const FieldTypeInfo &Other) const {
|
||||
return std::tie(Type, Name) == std::tie(Other.Type, Other.Name);
|
||||
}
|
||||
|
||||
SmallString<16> Name; // Name associated with this info.
|
||||
};
|
||||
|
||||
|
@ -112,6 +123,11 @@ struct MemberTypeInfo : public FieldTypeInfo {
|
|||
AccessSpecifier Access)
|
||||
: FieldTypeInfo(RefName, Name), Access(Access) {}
|
||||
|
||||
bool operator==(const MemberTypeInfo &Other) const {
|
||||
return std::tie(Type, Name, Access) ==
|
||||
std::tie(Other.Type, Other.Name, Other.Access);
|
||||
}
|
||||
|
||||
AccessSpecifier Access = AccessSpecifier::AS_none; // Access level associated
|
||||
// with this info (public,
|
||||
// protected, private,
|
||||
|
@ -123,6 +139,11 @@ struct Location {
|
|||
Location(int LineNumber, SmallString<16> Filename)
|
||||
: LineNumber(LineNumber), Filename(std::move(Filename)) {}
|
||||
|
||||
bool operator==(const Location &Other) const {
|
||||
return std::tie(LineNumber, Filename) ==
|
||||
std::tie(Other.LineNumber, Other.Filename);
|
||||
}
|
||||
|
||||
int LineNumber; // Line number of this Location.
|
||||
SmallString<32> Filename; // File for this Location.
|
||||
};
|
||||
|
@ -173,10 +194,9 @@ 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).
|
||||
llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters.
|
||||
// Access level for this method (public, private, protected, none).
|
||||
AccessSpecifier Access = AccessSpecifier::AS_none;
|
||||
};
|
||||
|
||||
// TODO: Expand to allow for documenting templating, inheritance access,
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
//===-- ClangDocYAML.cpp - ClangDoc YAML -----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Implementation of the YAML generator, converting decl info into YAML output.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Generators.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace clang::doc;
|
||||
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(Reference)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(Location)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>)
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
|
||||
// Enumerations to YAML output.
|
||||
|
||||
template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
|
||||
static void enumeration(IO &IO, clang::AccessSpecifier &Value) {
|
||||
IO.enumCase(Value, "Public", clang::AccessSpecifier::AS_public);
|
||||
IO.enumCase(Value, "Protected", clang::AccessSpecifier::AS_protected);
|
||||
IO.enumCase(Value, "Private", clang::AccessSpecifier::AS_private);
|
||||
IO.enumCase(Value, "None", clang::AccessSpecifier::AS_none);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ScalarEnumerationTraits<clang::TagTypeKind> {
|
||||
static void enumeration(IO &IO, clang::TagTypeKind &Value) {
|
||||
IO.enumCase(Value, "Struct", clang::TagTypeKind::TTK_Struct);
|
||||
IO.enumCase(Value, "Interface", clang::TagTypeKind::TTK_Interface);
|
||||
IO.enumCase(Value, "Union", clang::TagTypeKind::TTK_Union);
|
||||
IO.enumCase(Value, "Class", clang::TagTypeKind::TTK_Class);
|
||||
IO.enumCase(Value, "Enum", clang::TagTypeKind::TTK_Enum);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ScalarEnumerationTraits<InfoType> {
|
||||
static void enumeration(IO &IO, InfoType &Value) {
|
||||
IO.enumCase(Value, "Namespace", InfoType::IT_namespace);
|
||||
IO.enumCase(Value, "Record", InfoType::IT_record);
|
||||
IO.enumCase(Value, "Function", InfoType::IT_function);
|
||||
IO.enumCase(Value, "Enum", InfoType::IT_enum);
|
||||
IO.enumCase(Value, "Default", InfoType::IT_default);
|
||||
}
|
||||
};
|
||||
|
||||
// Scalars to YAML output.
|
||||
template <unsigned U> struct ScalarTraits<SmallString<U>> {
|
||||
|
||||
static void output(const SmallString<U> &S, void *, llvm::raw_ostream &OS) {
|
||||
for (const auto &C : S)
|
||||
OS << C;
|
||||
}
|
||||
|
||||
static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) {
|
||||
Value.assign(Scalar.begin(), Scalar.end());
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
};
|
||||
|
||||
template <> struct ScalarTraits<std::array<unsigned char, 20>> {
|
||||
|
||||
static void output(const std::array<unsigned char, 20> &S, void *,
|
||||
llvm::raw_ostream &OS) {
|
||||
OS << toHex(toStringRef(S));
|
||||
}
|
||||
|
||||
static StringRef input(StringRef Scalar, void *,
|
||||
std::array<unsigned char, 20> &Value) {
|
||||
if (Scalar.size() != 40)
|
||||
return "Error: Incorrect scalar size for USR.";
|
||||
Value = StringToSymbol(Scalar);
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
static SymbolID StringToSymbol(llvm::StringRef Value) {
|
||||
SymbolID USR;
|
||||
std::string HexString = fromHex(Value);
|
||||
std::copy(HexString.begin(), HexString.end(), USR.begin());
|
||||
return SymbolID(USR);
|
||||
}
|
||||
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
};
|
||||
|
||||
// Helper functions to map infos to YAML.
|
||||
|
||||
static void TypeInfoMapping(IO &IO, TypeInfo &I) {
|
||||
IO.mapOptional("Type", I.Type, Reference());
|
||||
}
|
||||
|
||||
static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
|
||||
TypeInfoMapping(IO, I);
|
||||
IO.mapOptional("Name", I.Name, SmallString<16>());
|
||||
}
|
||||
|
||||
static void InfoMapping(IO &IO, Info &I) {
|
||||
IO.mapRequired("USR", I.USR);
|
||||
IO.mapOptional("Name", I.Name, SmallString<16>());
|
||||
IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
|
||||
IO.mapOptional("Description", I.Description);
|
||||
}
|
||||
|
||||
static void SymbolInfoMapping(IO &IO, SymbolInfo &I) {
|
||||
InfoMapping(IO, I);
|
||||
IO.mapOptional("DefLocation", I.DefLoc, Optional<Location>());
|
||||
IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
|
||||
}
|
||||
|
||||
static void CommentInfoMapping(IO &IO, CommentInfo &I) {
|
||||
IO.mapOptional("Kind", I.Kind, SmallString<16>());
|
||||
IO.mapOptional("Text", I.Text, SmallString<64>());
|
||||
IO.mapOptional("Name", I.Name, SmallString<16>());
|
||||
IO.mapOptional("Direction", I.Direction, SmallString<8>());
|
||||
IO.mapOptional("ParamName", I.ParamName, SmallString<16>());
|
||||
IO.mapOptional("CloseName", I.CloseName, SmallString<16>());
|
||||
IO.mapOptional("SelfClosing", I.SelfClosing, false);
|
||||
IO.mapOptional("Explicit", I.Explicit, false);
|
||||
IO.mapOptional("Args", I.Args, llvm::SmallVector<SmallString<16>, 4>());
|
||||
IO.mapOptional("AttrKeys", I.AttrKeys,
|
||||
llvm::SmallVector<SmallString<16>, 4>());
|
||||
IO.mapOptional("AttrValues", I.AttrValues,
|
||||
llvm::SmallVector<SmallString<16>, 4>());
|
||||
IO.mapOptional("Children", I.Children);
|
||||
}
|
||||
|
||||
// Template specialization to YAML traits for Infos.
|
||||
|
||||
template <> struct MappingTraits<Location> {
|
||||
static void mapping(IO &IO, Location &Loc) {
|
||||
IO.mapOptional("LineNumber", Loc.LineNumber, 0);
|
||||
IO.mapOptional("Filename", Loc.Filename, SmallString<32>());
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<Reference> {
|
||||
static void mapping(IO &IO, Reference &Ref) {
|
||||
IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
|
||||
IO.mapOptional("Name", Ref.Name, SmallString<16>());
|
||||
IO.mapOptional("USR", Ref.USR, SymbolID());
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<TypeInfo> {
|
||||
static void mapping(IO &IO, TypeInfo &I) { TypeInfoMapping(IO, I); }
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<FieldTypeInfo> {
|
||||
static void mapping(IO &IO, FieldTypeInfo &I) {
|
||||
TypeInfoMapping(IO, I);
|
||||
IO.mapOptional("Name", I.Name, SmallString<16>());
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<MemberTypeInfo> {
|
||||
static void mapping(IO &IO, MemberTypeInfo &I) {
|
||||
FieldTypeInfoMapping(IO, I);
|
||||
IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<NamespaceInfo> {
|
||||
static void mapping(IO &IO, NamespaceInfo &I) { InfoMapping(IO, I); }
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<RecordInfo> {
|
||||
static void mapping(IO &IO, RecordInfo &I) {
|
||||
SymbolInfoMapping(IO, I);
|
||||
IO.mapOptional("TagType", I.TagType, clang::TagTypeKind::TTK_Struct);
|
||||
IO.mapOptional("Members", I.Members);
|
||||
IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
|
||||
IO.mapOptional("VirtualParents", I.VirtualParents,
|
||||
llvm::SmallVector<Reference, 4>());
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<EnumInfo> {
|
||||
static void mapping(IO &IO, EnumInfo &I) {
|
||||
SymbolInfoMapping(IO, I);
|
||||
IO.mapOptional("Scoped", I.Scoped, false);
|
||||
IO.mapOptional("Members", I.Members);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<FunctionInfo> {
|
||||
static void mapping(IO &IO, FunctionInfo &I) {
|
||||
SymbolInfoMapping(IO, I);
|
||||
IO.mapOptional("IsMethod", I.IsMethod, false);
|
||||
IO.mapOptional("Parent", I.Parent, Reference());
|
||||
IO.mapOptional("Params", I.Params);
|
||||
IO.mapOptional("ReturnType", I.ReturnType);
|
||||
IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<CommentInfo> {
|
||||
static void mapping(IO &IO, CommentInfo &I) { CommentInfoMapping(IO, I); }
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<std::unique_ptr<CommentInfo>> {
|
||||
static void mapping(IO &IO, std::unique_ptr<CommentInfo> &I) {
|
||||
if (I)
|
||||
CommentInfoMapping(IO, *I);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace yaml
|
||||
} // end namespace llvm
|
||||
|
||||
namespace clang {
|
||||
namespace doc {
|
||||
|
||||
/// Generator for YAML documentation.
|
||||
class YAMLGenerator : public Generator {
|
||||
public:
|
||||
static const char *Format;
|
||||
|
||||
bool generateDocForInfo(Info *I, llvm::raw_ostream &OS) override;
|
||||
};
|
||||
|
||||
const char *YAMLGenerator::Format = "yaml";
|
||||
|
||||
bool YAMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS) {
|
||||
llvm::yaml::Output InfoYAML(OS);
|
||||
switch (I->IT) {
|
||||
case InfoType::IT_namespace:
|
||||
InfoYAML << *static_cast<clang::doc::NamespaceInfo *>(I);
|
||||
break;
|
||||
case InfoType::IT_record:
|
||||
InfoYAML << *static_cast<clang::doc::RecordInfo *>(I);
|
||||
break;
|
||||
case InfoType::IT_enum:
|
||||
InfoYAML << *static_cast<clang::doc::EnumInfo *>(I);
|
||||
break;
|
||||
case InfoType::IT_function:
|
||||
InfoYAML << *static_cast<clang::doc::FunctionInfo *>(I);
|
||||
break;
|
||||
case InfoType::IT_default:
|
||||
llvm::errs() << "Unexpected info type in index.\n";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static GeneratorRegistry::Add<YAMLGenerator> YAML(YAMLGenerator::Format,
|
||||
"Generator for YAML output.");
|
||||
|
||||
// This anchor is used to force the linker to link in the generated object file
|
||||
// and thus register the generator.
|
||||
volatile int YAMLGeneratorAnchorSource = 0;
|
||||
|
||||
} // namespace doc
|
||||
} // namespace clang
|
|
@ -21,6 +21,7 @@
|
|||
#include "BitcodeReader.h"
|
||||
#include "BitcodeWriter.h"
|
||||
#include "ClangDoc.h"
|
||||
#include "Generators.h"
|
||||
#include "Representation.h"
|
||||
#include "clang/AST/AST.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
@ -67,10 +68,10 @@ enum OutputFormatTy {
|
|||
yaml,
|
||||
};
|
||||
|
||||
static llvm::cl::opt<OutputFormatTy>
|
||||
Format("format", llvm::cl::desc("Format for outputted docs."),
|
||||
llvm::cl::values(clEnumVal(yaml, "Documentation in YAML format.")),
|
||||
llvm::cl::init(yaml), llvm::cl::cat(ClangDocCategory));
|
||||
static llvm::cl::opt<OutputFormatTy> FormatEnum(
|
||||
"format", llvm::cl::desc("Format for outputted docs."),
|
||||
llvm::cl::values(clEnumVal(yaml, "Documentation in YAML format.")),
|
||||
llvm::cl::init(yaml), llvm::cl::cat(ClangDocCategory));
|
||||
|
||||
static llvm::cl::opt<bool> DoxygenOnly(
|
||||
"doxygen",
|
||||
|
@ -116,8 +117,41 @@ bool DumpResultToFile(const Twine &DirName, const Twine &FileName,
|
|||
return false;
|
||||
}
|
||||
|
||||
llvm::Expected<llvm::SmallString<128>>
|
||||
getPath(StringRef Root, StringRef Ext, StringRef Name,
|
||||
llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
|
||||
std::error_code OK;
|
||||
llvm::SmallString<128> Path;
|
||||
llvm::sys::path::native(Root, Path);
|
||||
for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
|
||||
llvm::sys::path::append(Path, R->Name);
|
||||
|
||||
if (CreateDirectory(Path))
|
||||
return llvm::make_error<llvm::StringError>("Unable to create directory.\n",
|
||||
llvm::inconvertibleErrorCode());
|
||||
|
||||
llvm::sys::path::append(Path, Name + Ext);
|
||||
return Path;
|
||||
}
|
||||
|
||||
std::string getFormatString(OutputFormatTy Ty) {
|
||||
switch (Ty) {
|
||||
case yaml:
|
||||
return "yaml";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
|
||||
std::error_code OK;
|
||||
|
||||
// Fail early if an invalid format was provided.
|
||||
std::string Format = getFormatString(FormatEnum);
|
||||
auto G = doc::findGeneratorByName(Format);
|
||||
if (!G) {
|
||||
llvm::errs() << toString(G.takeError()) << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto Exec = clang::tooling::createExecutorFromCommandLineArgs(
|
||||
argc, argv, ClangDocCategory);
|
||||
|
@ -173,7 +207,7 @@ int main(int argc, const char **argv) {
|
|||
}
|
||||
});
|
||||
|
||||
// Reducing phase
|
||||
// Reducing and generation phases
|
||||
llvm::outs() << "Reducing " << MapOutput.size() << " infos...\n";
|
||||
llvm::StringMap<std::unique_ptr<doc::Info>> ReduceOutput;
|
||||
for (auto &Group : MapOutput) {
|
||||
|
@ -186,16 +220,27 @@ int main(int argc, const char **argv) {
|
|||
llvm::BitstreamWriter Stream(Buffer);
|
||||
doc::ClangDocBitcodeWriter Writer(Stream);
|
||||
Writer.dispatchInfoForWrite(Reduced.get().get());
|
||||
if (DumpResultToFile("bc", Group.getKey() + ".bc", Buffer)) {
|
||||
llvm::errs() << "Error writing " << Group.getKey() << " to file.\n";
|
||||
continue;
|
||||
}
|
||||
if (DumpResultToFile("bc", Group.getKey() + ".bc", Buffer))
|
||||
llvm::errs() << "Error dumping to bitcode.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
ReduceOutput.insert(
|
||||
std::make_pair(Group.getKey(), std::move(Reduced.get())));
|
||||
// Create the relevant ostream and emit the documentation for this decl.
|
||||
doc::Info *I = Reduced.get().get();
|
||||
auto InfoPath = getPath(OutDirectory, "." + Format, I->Name, I->Namespace);
|
||||
if (!InfoPath) {
|
||||
llvm::errs() << toString(InfoPath.takeError()) << "\n";
|
||||
continue;
|
||||
}
|
||||
std::error_code FileErr;
|
||||
llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr, llvm::sys::fs::F_None);
|
||||
if (FileErr != OK) {
|
||||
llvm::errs() << "Error opening index file: " << FileErr.message() << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: Add support for emitting different output formats.
|
||||
if (G->get()->generateDocForInfo(I, InfoOS))
|
||||
llvm::errs() << "Unable to generate docs for info.\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: echo "" > %t/compile_flags.txt
|
||||
// RUN: cp "%s" "%t/test.cpp"
|
||||
// RUN: clang-doc -doxygen -p %t %t/test.cpp -output=%t/docs
|
||||
// RUN: cat %t/docs/F.yaml | 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 void
|
||||
void F(int I, int J);
|
||||
|
||||
/// Bonus comment on definition
|
||||
void F(int I, int J) {}
|
||||
|
||||
// CHECK: ---
|
||||
// CHECK-NEXT: USR: '7574630614A535710E5A6ABCFFF98BCA2D06A4CA'
|
||||
// CHECK-NEXT: Name: 'F'
|
||||
// CHECK-NEXT: Description:
|
||||
// CHECK-NEXT: - Kind: 'FullComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'BlockCommandComment'
|
||||
// CHECK-NEXT: Name: 'brief'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' Brief description.'
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' Extended description that'
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' continues onto the next line.'
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'HTMLStartTagComment'
|
||||
// CHECK-NEXT: Name: 'ul'
|
||||
// CHECK-NEXT: AttrKeys:
|
||||
// CHECK-NEXT: - 'class'
|
||||
// CHECK-NEXT: AttrValues:
|
||||
// CHECK-NEXT: - 'test'
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'HTMLStartTagComment'
|
||||
// CHECK-NEXT: Name: 'li'
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' Testing.'
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'HTMLEndTagComment'
|
||||
// CHECK-NEXT: Name: 'ul'
|
||||
// CHECK-NEXT: SelfClosing: true
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'VerbatimBlockComment'
|
||||
// CHECK-NEXT: Name: 'verbatim'
|
||||
// CHECK-NEXT: CloseName: 'endverbatim'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'VerbatimBlockLineComment'
|
||||
// CHECK-NEXT: Text: ' The description continues.'
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'ParamCommandComment'
|
||||
// CHECK-NEXT: Direction: '[out]'
|
||||
// CHECK-NEXT: ParamName: 'I'
|
||||
// CHECK-NEXT: Explicit: true
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' is a parameter.'
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'ParamCommandComment'
|
||||
// CHECK-NEXT: Direction: '[in]'
|
||||
// CHECK-NEXT: ParamName: 'J'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' is a parameter.'
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: - Kind: 'BlockCommandComment'
|
||||
// CHECK-NEXT: Name: 'return'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' void'
|
||||
// CHECK-NEXT: - Kind: 'FullComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'ParagraphComment'
|
||||
// CHECK-NEXT: Children:
|
||||
// CHECK-NEXT: - Kind: 'TextComment'
|
||||
// CHECK-NEXT: Text: ' Bonus comment on definition'
|
||||
// CHECK-NEXT: DefLocation:
|
||||
// CHECK-NEXT: LineNumber: 27
|
||||
// CHECK-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-NEXT: Location:
|
||||
// CHECK-NEXT: - LineNumber: 24
|
||||
// CHECK-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-NEXT: Params:
|
||||
// CHECK-NEXT: - Type:
|
||||
// CHECK-NEXT: Name: 'int'
|
||||
// CHECK-NEXT: Name: 'I'
|
||||
// CHECK-NEXT: - Type:
|
||||
// CHECK-NEXT: Name: 'int'
|
||||
// CHECK-NEXT: Name: 'J'
|
||||
// CHECK-NEXT: ReturnType:
|
||||
// CHECK-NEXT: Type:
|
||||
// CHECK-NEXT: Name: 'void'
|
||||
// CHECK-NEXT: ...
|
|
@ -0,0 +1,102 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: echo "" > %t/compile_flags.txt
|
||||
// RUN: cp "%s" "%t/test.cpp"
|
||||
// RUN: clang-doc -doxygen -p %t %t/test.cpp -output=%t/docs
|
||||
// RUN: cat %t/docs/A.yaml | FileCheck %s --check-prefix=CHECK-A
|
||||
// RUN: cat %t/docs/A/B.yaml | FileCheck %s --check-prefix=CHECK-B
|
||||
// RUN: cat %t/docs/A/f.yaml | FileCheck %s --check-prefix=CHECK-F
|
||||
// RUN: cat %t/docs/A/B/E.yaml | FileCheck %s --check-prefix=CHECK-E
|
||||
// RUN: cat %t/docs/A/B/func.yaml | FileCheck %s --check-prefix=CHECK-FUNC
|
||||
|
||||
namespace A {
|
||||
|
||||
// CHECK-A: ---
|
||||
// CHECK-A-NEXT: USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
|
||||
// CHECK-A-NEXT: Name: 'A'
|
||||
// CHECK-A-NEXT: ...
|
||||
|
||||
|
||||
void f();
|
||||
|
||||
} // namespace A
|
||||
|
||||
namespace A {
|
||||
|
||||
void f(){};
|
||||
|
||||
// CHECK-F: ---
|
||||
// CHECK-F-NEXT: USR: '39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC'
|
||||
// CHECK-F-NEXT: Name: 'f'
|
||||
// CHECK-F-NEXT: Namespace:
|
||||
// CHECK-F-NEXT: - Type: Namespace
|
||||
// CHECK-F-NEXT: Name: 'A'
|
||||
// CHECK-F-NEXT: USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
|
||||
// CHECK-F-NEXT: DefLocation:
|
||||
// CHECK-F-NEXT: LineNumber: 26
|
||||
// CHECK-F-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-F-NEXT: Location:
|
||||
// CHECK-F-NEXT: - LineNumber: 20
|
||||
// CHECK-F-NEXT: Filename: 'test'
|
||||
// CHECK-F-NEXT: ReturnType:
|
||||
// CHECK-F-NEXT: Type:
|
||||
// CHECK-F-NEXT: Name: 'void'
|
||||
// CHECK-F-NEXT: ...
|
||||
|
||||
namespace B {
|
||||
|
||||
// CHECK-B: ---
|
||||
// CHECK-B-NEXT: USR: 'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
|
||||
// CHECK-B-NEXT: Name: 'B'
|
||||
// CHECK-B-NEXT: Namespace:
|
||||
// CHECK-B-NEXT: - Type: Namespace
|
||||
// CHECK-B-NEXT: Name: 'A'
|
||||
// CHECK-B-NEXT: USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
|
||||
// CHECK-B-NEXT: ...
|
||||
|
||||
|
||||
enum E { X };
|
||||
|
||||
// CHECK-E: ---
|
||||
// CHECK-E-NEXT: USR: 'E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775'
|
||||
// CHECK-E-NEXT: Name: 'E'
|
||||
// CHECK-E-NEXT: Namespace:
|
||||
// CHECK-E-NEXT: - Type: Namespace
|
||||
// CHECK-E-NEXT: Name: 'B'
|
||||
// CHECK-E-NEXT: USR: 'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
|
||||
// CHECK-E-NEXT: - Type: Namespace
|
||||
// CHECK-E-NEXT: Name: 'A'
|
||||
// CHECK-E-NEXT: USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
|
||||
// CHECK-E-NEXT: DefLocation:
|
||||
// CHECK-E-NEXT: LineNumber: 58
|
||||
// CHECK-E-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-E-NEXT: Members:
|
||||
// CHECK-E-NEXT: - 'X'
|
||||
// CHECK-E-NEXT: ...
|
||||
|
||||
E func(int i) { return X; }
|
||||
|
||||
// CHECK-FUNC: ---
|
||||
// CHECK-FUNC-NEXT: USR: '9A82CB33ED0FDF81EE383D31CD0957D153C5E840'
|
||||
// CHECK-FUNC-NEXT: Name: 'func'
|
||||
// CHECK-FUNC-NEXT: Namespace:
|
||||
// CHECK-FUNC-NEXT: - Type: Namespace
|
||||
// CHECK-FUNC-NEXT: Name: 'B'
|
||||
// CHECK-FUNC-NEXT: USR: 'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
|
||||
// CHECK-FUNC-NEXT: - Type: Namespace
|
||||
// CHECK-FUNC-NEXT: Name: 'A'
|
||||
// CHECK-FUNC-NEXT: USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
|
||||
// CHECK-FUNC-NEXT: DefLocation:
|
||||
// CHECK-FUNC-NEXT: LineNumber: 77
|
||||
// CHECK-FUNC-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-FUNC-NEXT: Params:
|
||||
// CHECK-FUNC-NEXT: - Type:
|
||||
// CHECK-FUNC-NEXT: Name: 'int'
|
||||
// CHECK-FUNC-NEXT: Name: 'i'
|
||||
// CHECK-FUNC-NEXT: ReturnType:
|
||||
// CHECK-FUNC-NEXT: Type:
|
||||
// CHECK-FUNC-NEXT: Name: 'enum A::B::E'
|
||||
// CHECK-FUNC-NEXT: ...
|
||||
|
||||
} // namespace B
|
||||
} // namespace A
|
|
@ -0,0 +1,250 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: echo "" > %t/compile_flags.txt
|
||||
// RUN: cp "%s" "%t/test.cpp"
|
||||
// RUN: clang-doc -doxygen -p %t %t/test.cpp -output=%t/docs
|
||||
// RUN: cat %t/docs/A.yaml | FileCheck %s --check-prefix=CHECK-A
|
||||
// RUN: cat %t/docs/Bc.yaml | FileCheck %s --check-prefix=CHECK-BC
|
||||
// RUN: cat %t/docs/B.yaml | FileCheck %s --check-prefix=CHECK-B
|
||||
// RUN: cat %t/docs/C.yaml | FileCheck %s --check-prefix=CHECK-C
|
||||
// RUN: cat %t/docs/D.yaml | FileCheck %s --check-prefix=CHECK-D
|
||||
// RUN: cat %t/docs/E.yaml | FileCheck %s --check-prefix=CHECK-E
|
||||
// RUN: cat %t/docs/E/ProtectedMethod.yaml | FileCheck %s --check-prefix=CHECK-EPM
|
||||
// RUN: cat %t/docs/E/E.yaml | FileCheck %s --check-prefix=CHECK-ECON
|
||||
// RUN: cat %t/docs/E/'~E.yaml' | FileCheck %s --check-prefix=CHECK-EDES
|
||||
// RUN: cat %t/docs/F.yaml | FileCheck %s --check-prefix=CHECK-F
|
||||
// RUN: cat %t/docs/X.yaml | FileCheck %s --check-prefix=CHECK-X
|
||||
// RUN: cat %t/docs/X/Y.yaml | FileCheck %s --check-prefix=CHECK-Y
|
||||
// RUN: cat %t/docs/H.yaml | FileCheck %s --check-prefix=CHECK-H
|
||||
// RUN: cat %t/docs/H/I.yaml | FileCheck %s --check-prefix=CHECK-I
|
||||
|
||||
union A { int X; int Y; };
|
||||
|
||||
// CHECK-A: ---
|
||||
// CHECK-A-NEXT: USR: 'ACE81AFA6627B4CEF2B456FB6E1252925674AF7E'
|
||||
// CHECK-A-NEXT: Name: 'A'
|
||||
// CHECK-A-NEXT: DefLocation:
|
||||
// CHECK-A-NEXT: LineNumber: 21
|
||||
// CHECK-A-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-A-NEXT: TagType: Union
|
||||
// CHECK-A-NEXT: Members:
|
||||
// CHECK-A-NEXT: - Type:
|
||||
// CHECK-A-NEXT: Name: 'int'
|
||||
// CHECK-A-NEXT: Name: 'X'
|
||||
// CHECK-A-NEXT: - Type:
|
||||
// CHECK-A-NEXT: Name: 'int'
|
||||
// CHECK-A-NEXT: Name: 'Y'
|
||||
// CHECK-A-NEXT: ...
|
||||
|
||||
|
||||
enum B { X, Y };
|
||||
|
||||
// CHECK-B: ---
|
||||
// CHECK-B-NEXT: USR: 'FC07BD34D5E77782C263FA944447929EA8753740'
|
||||
// CHECK-B-NEXT: Name: 'B'
|
||||
// CHECK-B-NEXT: DefLocation:
|
||||
// CHECK-B-NEXT: LineNumber: 40
|
||||
// CHECK-B-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-B-NEXT: Members:
|
||||
// CHECK-B-NEXT: - 'X'
|
||||
// CHECK-B-NEXT: - 'Y'
|
||||
// CHECK-B-NEXT: ...
|
||||
|
||||
enum class Bc { A, B };
|
||||
|
||||
// CHECK-BC: ---
|
||||
// CHECK-BC-NEXT: USR: '1E3438A08BA22025C0B46289FF0686F92C8924C5'
|
||||
// CHECK-BC-NEXT: Name: 'Bc'
|
||||
// CHECK-BC-NEXT: DefLocation:
|
||||
// CHECK-BC-NEXT: LineNumber: 53
|
||||
// CHECK-BC-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-BC-NEXT: Scoped: true
|
||||
// CHECK-BC-NEXT: Members:
|
||||
// CHECK-BC-NEXT: - 'A'
|
||||
// CHECK-BC-NEXT: - 'B'
|
||||
// CHECK-BC-NEXT: ...
|
||||
|
||||
struct C { int i; };
|
||||
|
||||
// CHECK-C: ---
|
||||
// CHECK-C-NEXT: USR: '06B5F6A19BA9F6A832E127C9968282B94619B210'
|
||||
// CHECK-C-NEXT: Name: 'C'
|
||||
// CHECK-C-NEXT: DefLocation:
|
||||
// CHECK-C-NEXT: LineNumber: 67
|
||||
// CHECK-C-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-C-NEXT: Members:
|
||||
// CHECK-C-NEXT: - Type:
|
||||
// CHECK-C-NEXT: Name: 'int'
|
||||
// CHECK-C-NEXT: Name: 'i'
|
||||
// CHECK-C-NEXT: ...
|
||||
|
||||
class D {};
|
||||
|
||||
// CHECK-D: ---
|
||||
// CHECK-D-NEXT: USR: '0921737541208B8FA9BB42B60F78AC1D779AA054'
|
||||
// CHECK-D-NEXT: Name: 'D'
|
||||
// CHECK-D-NEXT: DefLocation:
|
||||
// CHECK-D-NEXT: LineNumber: 81
|
||||
// CHECK-D-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-D-NEXT: TagType: Class
|
||||
// CHECK-D-NEXT: ...
|
||||
|
||||
class E {
|
||||
public:
|
||||
E() {}
|
||||
|
||||
// CHECK-ECON: ---
|
||||
// CHECK-ECON-NEXT: USR: 'DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4'
|
||||
// CHECK-ECON-NEXT: Name: 'E'
|
||||
// CHECK-ECON-NEXT: Namespace:
|
||||
// CHECK-ECON-NEXT: - Type: Record
|
||||
// CHECK-ECON-NEXT: Name: 'E'
|
||||
// CHECK-ECON-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-ECON-NEXT: DefLocation:
|
||||
// CHECK-ECON-NEXT: LineNumber: 94
|
||||
// CHECK-ECON-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-ECON-NEXT: IsMethod: true
|
||||
// CHECK-ECON-NEXT: Parent:
|
||||
// CHECK-ECON-NEXT: Type: Record
|
||||
// CHECK-ECON-NEXT: Name: 'E'
|
||||
// CHECK-ECON-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-ECON-NEXT: ReturnType:
|
||||
// CHECK-ECON-NEXT: Type:
|
||||
// CHECK-ECON-NEXT: Name: 'void'
|
||||
// CHECK-ECON-NEXT: ...
|
||||
|
||||
~E() {}
|
||||
|
||||
// CHECK-EDES: ---
|
||||
// CHECK-EDES-NEXT: USR: 'BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17'
|
||||
// CHECK-EDES-NEXT: Name: '~E'
|
||||
// CHECK-EDES-NEXT: Namespace:
|
||||
// CHECK-EDES-NEXT: - Type: Record
|
||||
// CHECK-EDES-NEXT: Name: 'E'
|
||||
// CHECK-EDES-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-EDES-NEXT: DefLocation:
|
||||
// CHECK-EDES-NEXT: LineNumber: 116
|
||||
// CHECK-EDES-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-EDES-NEXT: IsMethod: true
|
||||
// CHECK-EDES-NEXT: Parent:
|
||||
// CHECK-EDES-NEXT: Type: Record
|
||||
// CHECK-EDES-NEXT: Name: 'E'
|
||||
// CHECK-EDES-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-EDES-NEXT: ReturnType:
|
||||
// CHECK-EDES-NEXT: Type:
|
||||
// CHECK-EDES-NEXT: Name: 'void'
|
||||
// CHECK-EDES-NEXT: ...
|
||||
|
||||
|
||||
protected:
|
||||
void ProtectedMethod();
|
||||
};
|
||||
|
||||
// CHECK-E: ---
|
||||
// CHECK-E-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-E-NEXT: Name: 'E'
|
||||
// CHECK-E-NEXT: DefLocation:
|
||||
// CHECK-E-NEXT: LineNumber: 92
|
||||
// CHECK-E-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-E-NEXT: TagType: Class
|
||||
// CHECK-E-NEXT: ...
|
||||
|
||||
void E::ProtectedMethod() {}
|
||||
|
||||
// CHECK-EPM: ---
|
||||
// CHECK-EPM-NEXT: USR: '5093D428CDC62096A67547BA52566E4FB9404EEE'
|
||||
// CHECK-EPM-NEXT: Name: 'ProtectedMethod'
|
||||
// CHECK-EPM-NEXT: Namespace:
|
||||
// CHECK-EPM-NEXT: - Type: Record
|
||||
// CHECK-EPM-NEXT: Name: 'E'
|
||||
// CHECK-EPM-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-EPM-NEXT: DefLocation:
|
||||
// CHECK-EPM-NEXT: LineNumber: 152
|
||||
// CHECK-EPM-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-EPM-NEXT: Location:
|
||||
// CHECK-EPM-NEXT: - LineNumber: 140
|
||||
// CHECK-EPM-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-EPM-NEXT: IsMethod: true
|
||||
// CHECK-EPM-NEXT: Parent:
|
||||
// CHECK-EPM-NEXT: Type: Record
|
||||
// CHECK-EPM-NEXT: Name: 'E'
|
||||
// CHECK-EPM-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-EPM-NEXT: ReturnType:
|
||||
// CHECK-EPM-NEXT: Type:
|
||||
// CHECK-EPM-NEXT: Name: 'void'
|
||||
// CHECK-EPM-NEXT: ...
|
||||
|
||||
class F : virtual private D, public E {};
|
||||
|
||||
// CHECK-F: ---
|
||||
// CHECK-F-NEXT: USR: 'E3B54702FABFF4037025BA194FC27C47006330B5'
|
||||
// CHECK-F-NEXT: Name: 'F'
|
||||
// CHECK-F-NEXT: DefLocation:
|
||||
// CHECK-F-NEXT: LineNumber: 177
|
||||
// CHECK-F-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-F-NEXT: TagType: Class
|
||||
// CHECK-F-NEXT: Parents:
|
||||
// CHECK-F-NEXT: - Type: Record
|
||||
// CHECK-F-NEXT: Name: 'E'
|
||||
// CHECK-F-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1'
|
||||
// CHECK-F-NEXT: VirtualParents:
|
||||
// CHECK-F-NEXT: - Type: Record
|
||||
// CHECK-F-NEXT: Name: 'D'
|
||||
// CHECK-F-NEXT: USR: '0921737541208B8FA9BB42B60F78AC1D779AA054'
|
||||
// CHECK-F-NEXT: ...
|
||||
|
||||
class X {
|
||||
class Y {};
|
||||
|
||||
// CHECK-Y: ---
|
||||
// CHECK-Y-NEXT: USR: '641AB4A3D36399954ACDE29C7A8833032BF40472'
|
||||
// CHECK-Y-NEXT: Name: 'Y'
|
||||
// CHECK-Y-NEXT: Namespace:
|
||||
// CHECK-Y-NEXT: - Type: Record
|
||||
// CHECK-Y-NEXT: Name: 'X'
|
||||
// CHECK-Y-NEXT: USR: 'CA7C7935730B5EACD25F080E9C83FA087CCDC75E'
|
||||
// CHECK-Y-NEXT: DefLocation:
|
||||
// CHECK-Y-NEXT: LineNumber: 197
|
||||
// CHECK-Y-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-Y-NEXT: TagType: Class
|
||||
// CHECK-Y-NEXT: ...
|
||||
|
||||
};
|
||||
|
||||
// CHECK-X: ---
|
||||
// CHECK-X-NEXT: USR: 'CA7C7935730B5EACD25F080E9C83FA087CCDC75E'
|
||||
// CHECK-X-NEXT: Name: 'X'
|
||||
// CHECK-X-NEXT: DefLocation:
|
||||
// CHECK-X-NEXT: LineNumber: 196
|
||||
// CHECK-X-NEXT: Filename: '{{.*}}'
|
||||
// CHECK-X-NEXT: TagType: Class
|
||||
// CHECK-X-NEXT: ...
|
||||
|
||||
void H() {
|
||||
class I {};
|
||||
|
||||
// CHECK-I: ---
|
||||
// CHECK-I-NEXT: USR: '{{.*}}'
|
||||
// CHECK-I-NEXT: Name: 'I'
|
||||
// CHECK-I-NEXT: Namespace:
|
||||
// CHECK-I-NEXT: - Type: Function
|
||||
// CHECK-I-NEXT: Name: 'H'
|
||||
// CHECK-I-NEXT: USR: 'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E'
|
||||
// CHECK-I-NEXT: DefLocation:
|
||||
// CHECK-I-NEXT: LineNumber: 224
|
||||
// CHECK-I-NEXT: Filename: 'test'
|
||||
// CHECK-I-NEXT: TagType: Class
|
||||
// CHECK-I-NEXT: ...
|
||||
|
||||
}
|
||||
|
||||
// CHECK-H: ---
|
||||
// CHECK-H-NEXT: USR: 'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E'
|
||||
// CHECK-H-NEXT: Name: 'H'
|
||||
// CHECK-H-NEXT: DefLocation:
|
||||
// CHECK-H-NEXT: LineNumber: 223
|
||||
// CHECK-H-NEXT: Filename: 'test'
|
||||
// CHECK-H-NEXT: ReturnType:
|
||||
// CHECK-H-NEXT: Type:
|
||||
// CHECK-H-NEXT: Name: 'void'
|
||||
// CHECK-H-NEXT: ...
|
Loading…
Reference in New Issue