raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum);
raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang);
raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access);
+raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type);
raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id);
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
uint16_t UInt16;
uint32_t UInt32;
uint64_t UInt64;
- void* Pointer;
};
+#define VARIANT_EQUAL_CASE(Enum) \
+ case PDB_VariantType::Enum: \
+ return Enum == Other.Enum;
+ bool operator==(const Variant &Other) const {
+ if (Type != Other.Type)
+ return false;
+ switch (Type) {
+ VARIANT_EQUAL_CASE(Bool)
+ VARIANT_EQUAL_CASE(Int8)
+ VARIANT_EQUAL_CASE(Int16)
+ VARIANT_EQUAL_CASE(Int32)
+ VARIANT_EQUAL_CASE(Int64)
+ VARIANT_EQUAL_CASE(Single)
+ VARIANT_EQUAL_CASE(Double)
+ VARIANT_EQUAL_CASE(UInt8)
+ VARIANT_EQUAL_CASE(UInt16)
+ VARIANT_EQUAL_CASE(UInt32)
+ VARIANT_EQUAL_CASE(UInt64)
+ default:
+ return true;
+ }
+ }
+#undef VARIANT_EQUAL_CASE
+ bool operator!=(const Variant &Other) const { return !(*this == Other); }
};
} // namespace llvm
return OS;
}
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_MemberAccess &Access) {
+ switch (Access) {
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Public, "public", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Protected, "protected", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Private, "private", OS)
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UdtType &Type) {
+ switch (Type) {
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Class, "class", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Struct, "struct", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Interface, "interface", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Union, "union", OS)
+ }
+ return OS;
+}
+
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) {
static const char *Lookup = "0123456789ABCDEF";
default:
OS << Value.Type;
}
- OS << " {" << Value.Type << "}";
return OS;
}
; FULL_CLASS: ---TYPES---
; FULL_CLASS: Classes
-; FULL_CLASS-DAG: class A {
+; FULL_CLASS-DAG: struct A {
; FULL_CLASS: public:
; FULL_CLASS: virtual void PureFunc() = 0
; FULL_CLASS: virtual void VirtualFunc()
; FULL_CLASS: void RegularFunc()
; FULL_CLASS: }
-; FULL_CLASS-DAG: class MemberTest {
+; FULL_CLASS-DAG: struct MemberTest {
; FULL_CLASS: data +0x00 MemberTest::NestedEnum m_nested_enum
; FULL_CLASS: data +0x04 int m_typedef
; FULL_CLASS: data +0x08 bool m_bool
--- /dev/null
+// Compile with "cl /c /Zi /GR- ClassLayoutTest.cpp"\r
+// Link with "link ClassLayoutTest.obj /debug /nodefaultlib /entry:main"\r
+\r
+namespace MembersTest {\r
+ class A {\r
+ public:\r
+ typedef int NestedTypedef;\r
+ enum NestedEnum {\r
+ NestedEnumValue1\r
+ };\r
+\r
+ void MemberFunc() {}\r
+\r
+ private:\r
+ int IntMemberVar;\r
+ double DoubleMemberVar;\r
+ };\r
+}\r
+\r
+namespace GlobalsTest {\r
+ int IntVar;\r
+ double DoubleVar;\r
+ \r
+ typedef int Typedef;\r
+ enum Enum {\r
+ Val1\r
+ } EnumVar;\r
+ Typedef TypedefVar;\r
+}\r
+\r
+namespace BaseClassTest {\r
+ class A {};\r
+ class B : public virtual A {};\r
+ class C : public virtual A {};\r
+ class D : protected B, private C {};\r
+}\r
+\r
+namespace UdtKindTest {\r
+ struct A {};\r
+ class B {};\r
+ union C {};\r
+}\r
+\r
+namespace BitFieldTest {\r
+ struct A {\r
+ int Bits1 : 1;\r
+ int Bits2 : 2;\r
+ int Bits3 : 3;\r
+ int Bits4 : 4;\r
+ int Bits22 : 22;\r
+ int Offset0x04;\r
+ };\r
+};\r
+\r
+int main(int argc, char **argv) {\r
+ MembersTest::A v1;\r
+ v1.MemberFunc();\r
+ BaseClassTest::D v2;\r
+ UdtKindTest::A v3;\r
+ UdtKindTest::B v4;\r
+ UdtKindTest::C v5;\r
+ BitFieldTest::A v7;\r
+ return 0;\r
+}\r
--- /dev/null
+; RUN: llvm-pdbdump -all %p/Inputs/ClassLayoutTest.pdb > %t\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_TEST\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBERS_TEST\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_A\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_B\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_C\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_D\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=UDT_KIND_TEST\r
+; RUN: FileCheck -input-file=%t %s -check-prefix=BITFIELD_TEST\r
+\r
+; GLOBALS_TEST: ---GLOBALS---\r
+; GLOBALS_TEST-DAG: int GlobalsTest::IntVar\r
+; GLOBALS_TEST-DAG: double GlobalsTest::DoubleVar\r
+; GLOBALS_TEST-DAG: GlobalsTest::Enum GlobalsTest::EnumVar\r
+\r
+; MEMBERS_TEST: ---TYPES---\r
+; MEMBERS_TEST: class MembersTest::A {\r
+; MEMBERS_TEST-DAG: typedef int NestedTypedef\r
+; MEMBERS_TEST-DAG: enum NestedEnum\r
+; MEMBERS_TEST: public:\r
+; MEMBERS_TEST-NEXT: void MemberFunc()\r
+; MEMBERS_TEST-NEXT: private:\r
+; MEMBERS_TEST-DAG: int IntMemberVar\r
+; MEMBERS_TEST-DAG: double DoubleMemberVar\r
+; MEMBERS_TEST: }\r
+\r
+; BASE_CLASS_A: ---TYPES---\r
+; BASE_CLASS_A: class BaseClassTest::A {}\r
+\r
+; BASE_CLASS_B: ---TYPES---\r
+; BASE_CLASS_B: class BaseClassTest::B\r
+; BASE_CLASS_B-NEXT: : public virtual BaseClassTest::A {\r
+\r
+; BASE_CLASS_C: ---TYPES---\r
+; BASE_CLASS_C: class BaseClassTest::C\r
+; BASE_CLASS_C-NEXT: : public virtual BaseClassTest::A {\r
+\r
+; BASE_CLASS_D: ---TYPES---\r
+; BASE_CLASS_D: class BaseClassTest::D\r
+; BASE_CLASS_D-DAG: protected BaseClassTest::B\r
+; BASE_CLASS_D-DAG: private BaseClassTest::C\r
+; BASE_CLASS_D-DAG: protected virtual BaseClassTest::A\r
+\r
+; UDT_KIND_TEST: ---TYPES---\r
+; UDT_KIND_TEST-DAG: union UdtKindTest::C {}\r
+; UDT_KIND_TEST-DAG: class UdtKindTest::B {}\r
+; UDT_KIND_TEST-DAG: struct UdtKindTest::A {}\r
+\r
+; BITFIELD_TEST: ---TYPES---\r
+; BITFIELD_TEST: struct BitFieldTest::A {\r
+; BITFIELD_TEST-NEXT: public:\r
+; BITFIELD_TEST-NEXT: +0x00 int Bits1 : 1\r
+; BITFIELD_TEST-NEXT: +0x00 int Bits2 : 2\r
+; BITFIELD_TEST-NEXT: +0x00 int Bits3 : 3\r
+; BITFIELD_TEST-NEXT: +0x00 int Bits4 : 4\r
+; BITFIELD_TEST-NEXT: +0x00 int Bits22 : 22\r
+; BITFIELD_TEST-NEXT: +0x04 int Offset0x04\r
; NO_FILTER: Typedefs
; NO_FILTER: typedef int GlobalTypedef
; NO_FILTER: Classes:
-; NO_FILTER: class __vc_attributes
+; NO_FILTER: struct __vc_attributes
; NO_FILTER: class FilterTestClass
; NO_FILTER-DAG: typedef int NestedTypedef
; NO_FILTER-DAG: enum NestedEnum
WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
break;
default:
- WithColor(Printer, PDB_ColorItem::Type).get() << "(unknown)";
+ WithColor(Printer, PDB_ColorItem::Type).get() << "void";
break;
}
}
void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
std::string Name = Class.getName();
- WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
+
+ auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
+ if (Bases->getChildCount() > 0) {
+ Printer.Indent();
+ Printer.NewLine();
+ Printer << ":";
+ uint32_t BaseIndex = 0;
+ while (auto Base = Bases->getNext()) {
+ Printer << " ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
+ if (Base->isVirtualBaseClass())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
+ WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName();
+ if (++BaseIndex < Bases->getChildCount()) {
+ Printer.NewLine();
+ Printer << ",";
+ }
+ }
+ Printer.Unindent();
+ }
+
Printer << " {";
auto Children = Class.findAllChildren();
if (Children->getChildCount() == 0) {
auto &AccessGroup = Groups.find((int)Access)->second;
if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
- if (Func->isCompilerGenerated())
+ if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated)
continue;
- if (Func->getLength() == 0 && !Func->isPureVirtual())
+ if (Func->getLength() == 0 && !Func->isPureVirtual() &&
+ !Func->isIntroVirtualFunction())
continue;
Child.release();
AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
<< "[" << format_hex(RVA, 10) << " - "
<< format_hex(RVA + Symbol.getLength(), 10) << "]";
}
- Printer << " (" << Ordinal << ") ";
+ Printer << " (";
+ WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
+ Printer << ") ";
std::string Name = Symbol.getName();
if (!Name.empty())
WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
uint32_t FuncStart = Symbol.getRelativeVirtualAddress();
uint32_t FuncEnd = FuncStart + Symbol.getLength();
- Printer << "func ";
- WithColor(Printer, PDB_ColorItem::Address).get() << "["
- << format_hex(FuncStart, 8);
+ Printer << "func [";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
uint32_t Prologue = DebugStart->getRelativeVirtualAddress() - FuncStart;
WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
}
- WithColor(Printer, PDB_ColorItem::Address).get() << " - "
- << format_hex(FuncEnd, 8);
+ Printer << " - ";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
uint32_t Epilogue = FuncEnd - DebugEnd->getRelativeVirtualAddress();
WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
}
- WithColor(Printer, PDB_ColorItem::Address).get() << "] ";
+ Printer << "] (";
- if (Symbol.hasFramePointer())
- WithColor(Printer, PDB_ColorItem::Address).get()
- << "(" << Symbol.getLocalBasePointerRegisterId() << ")";
- else
- WithColor(Printer, PDB_ColorItem::Address).get() << "(FPO)";
+ if (Symbol.hasFramePointer()) {
+ WithColor(Printer, PDB_ColorItem::Register).get()
+ << Symbol.getLocalBasePointerRegisterId();
+ } else {
+ WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
+ }
+ Printer << ") ";
- Printer << " ";
if (Symbol.isVirtual() || Symbol.isPureVirtual())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+
#include "llvm/Support/Regex.h"
#include <algorithm>
using namespace llvm;
LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
- : OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {}
+ : OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {
+ SetFilters(TypeFilters, opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
+ SetFilters(SymbolFilters, opts::ExcludeSymbols.begin(),
+ opts::ExcludeSymbols.end());
+ SetFilters(CompilandFilters, opts::ExcludeCompilands.begin(),
+ opts::ExcludeCompilands.end());
+}
void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
Color = raw_ostream::MAGENTA;
Bold = true;
return;
+ case PDB_ColorItem::Register:
case PDB_ColorItem::Offset:
Color = raw_ostream::YELLOW;
Bold = false;
public:
LinePrinter(int Indent, raw_ostream &Stream);
- template <typename Iter> void SetTypeFilters(Iter Begin, Iter End) {
- TypeFilters.clear();
- for (; Begin != End; ++Begin)
- TypeFilters.push_back(StringRef(*Begin));
- }
- template <typename Iter> void SetSymbolFilters(Iter Begin, Iter End) {
- SymbolFilters.clear();
- for (; Begin != End; ++Begin)
- SymbolFilters.push_back(StringRef(*Begin));
- }
- template <typename Iter> void SetCompilandFilters(Iter Begin, Iter End) {
- CompilandFilters.clear();
- for (; Begin != End; ++Begin)
- CompilandFilters.push_back(StringRef(*Begin));
- }
-
void Indent();
void Unindent();
void NewLine();
raw_ostream &getStream() { return OS; }
+ int getIndentLevel() const { return CurrentIndent; }
bool IsTypeExcluded(llvm::StringRef TypeName);
bool IsSymbolExcluded(llvm::StringRef SymbolName);
bool IsCompilandExcluded(llvm::StringRef CompilandName);
private:
+ template <typename Iter>
+ void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) {
+ List.clear();
+ for (; Begin != End; ++Begin)
+ List.push_back(StringRef(*Begin));
+ }
+
raw_ostream &OS;
int IndentSpaces;
int CurrentIndent;
Path,
SectionHeader,
LiteralValue,
+ Register,
};
class WithColor {
uint32_t TargetId = Symbol.getTypeId();
if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
TypeSymbol->dump(*this);
- WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
+ << Symbol.getName();
}
void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {}
void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
- WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}
: PDBSymDumper(true), Printer(P) {}
void VariableDumper::start(const PDBSymbolData &Var) {
+ if (Var.isCompilerGenerated() && opts::ExcludeCompilerGenerated)
+ return;
if (Printer.IsSymbolExcluded(Var.getName()))
return;
switch (auto LocType = Var.getLocationType()) {
case PDB_LocType::Static:
+ Printer << "[";
WithColor(Printer, PDB_ColorItem::Address).get()
- << "[" << format_hex(Var.getRelativeVirtualAddress(), 10) << "] ";
+ << format_hex(Var.getRelativeVirtualAddress(), 10);
+ Printer << "] ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
case PDB_LocType::Constant:
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
dumpSymbolTypeAndName(*VarType, Var.getName());
- Printer << "[";
+ Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
- Printer << "]";
break;
case PDB_LocType::ThisRel:
WithColor(Printer, PDB_ColorItem::Offset).get()
<< "+" << format_hex(Var.getOffset(), 4) << " ";
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
+ case PDB_LocType::BitField:
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(Var.getOffset(), 4) << " ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ Printer << " : ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
+ break;
default:
Printer << "unknown(" << LocType << ") ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
cl::desc("<input PDB files>"),
cl::OneOrMore);
-cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"));
-cl::opt<bool> Symbols("symbols",
- cl::desc("Display symbols for each compiland"));
-cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"));
-cl::opt<bool> Types("types", cl::desc("Display types"));
-cl::opt<bool> ClassDefs("class-definitions",
- cl::desc("Display full class definitions"));
+cl::OptionCategory TypeCategory("Symbol Type Options");
+cl::OptionCategory FilterCategory("Filtering Options");
+
+cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
+ cl::cat(TypeCategory));
+cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
+ cl::cat(TypeCategory));
+cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
+ cl::cat(TypeCategory));
+cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
+cl::opt<bool>
+ ClassDefs("class-definitions",
+ cl::desc("Display full class definitions (implies -types)"),
+ cl::cat(TypeCategory));
+cl::opt<bool>
+ All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
+ cl::cat(TypeCategory));
cl::list<std::string>
ExcludeTypes("exclude-types",
cl::desc("Exclude types by regular expression"),
- cl::ZeroOrMore);
+ cl::ZeroOrMore, cl::cat(FilterCategory));
cl::list<std::string>
ExcludeSymbols("exclude-symbols",
cl::desc("Exclude symbols by regular expression"),
- cl::ZeroOrMore);
+ cl::ZeroOrMore, cl::cat(FilterCategory));
cl::list<std::string>
ExcludeCompilands("exclude-compilands",
cl::desc("Exclude compilands by regular expression"),
- cl::ZeroOrMore);
+ cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::opt<bool> ExcludeCompilerGenerated(
+ "no-compiler-generated",
+ cl::desc("Don't show compiler generated types and symbols"),
+ cl::cat(FilterCategory));
+cl::opt<bool>
+ ExcludeSystemLibraries("no-system-libs",
+ cl::desc("Don't show symbols from system libraries"),
+ cl::cat(FilterCategory));
}
static void dumpInput(StringRef Path) {
}
LinePrinter Printer(2, outs());
- Printer.SetTypeFilters(opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
- Printer.SetSymbolFilters(opts::ExcludeSymbols.begin(),
- opts::ExcludeSymbols.end());
- Printer.SetCompilandFilters(opts::ExcludeCompilands.begin(),
- opts::ExcludeCompilands.end());
auto GlobalScope(Session->getGlobalScope());
std::string FileName(GlobalScope->getSymbolsFileName());
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
+ if (opts::ClassDefs)
+ opts::Types = true;
+ if (opts::All) {
+ opts::Compilands = true;
+ opts::Symbols = true;
+ opts::Globals = true;
+ opts::Types = true;
+ opts::ClassDefs = true;
+ }
+ if (opts::ExcludeCompilerGenerated) {
+ opts::ExcludeTypes.push_back("__vc_attributes");
+ opts::ExcludeCompilands.push_back("* Linker *");
+ }
+ if (opts::ExcludeSystemLibraries) {
+ opts::ExcludeCompilands.push_back(
+ "f:\\binaries\\Intermediate\\vctools\\crt_bld");
+ }
#if defined(HAVE_DIA_SDK)
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
-namespace llvm {
-struct newline {
- newline(int IndentWidth) : Width(IndentWidth) {}
- int Width;
-};
+namespace opts {
+extern llvm::cl::opt<bool> Compilands;
+extern llvm::cl::opt<bool> Symbols;
+extern llvm::cl::opt<bool> Globals;
+extern llvm::cl::opt<bool> Types;
+extern llvm::cl::opt<bool> ClassDefs;
+extern llvm::cl::opt<bool> All;
-inline raw_ostream &operator<<(raw_ostream &OS, const newline &Indent) {
- OS << "\n";
- OS.indent(Indent.Width);
- return OS;
-}
+extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
+
+extern llvm::cl::list<std::string> ExcludeTypes;
+extern llvm::cl::list<std::string> ExcludeSymbols;
+extern llvm::cl::list<std::string> ExcludeCompilands;
}
#endif
\ No newline at end of file