llvm-project/clang/Driver/ASTConsumers.cpp
Chris Lattner a2e25e5e72 adjust to changes in various APIs from LLVM. We can't print
an APInt directly to an ostream now, so add some hacks.  It would
be better to switch all of the bugreport (and friends) stuff over
to raw_ostream.

llvm-svn: 55264
2008-08-23 22:23:37 +00:00

728 lines
22 KiB
C++

//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// AST Consumer Implementations.
//
//===----------------------------------------------------------------------===//
#include "ASTConsumers.h"
#include "HTMLDiagnostics.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "llvm/Module.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/Timer.h"
#include "llvm/ADT/OwningPtr.h"
#include <fstream>
using namespace clang;
//===----------------------------------------------------------------------===//
/// DeclPrinter - Utility class for printing top-level decls.
namespace {
class DeclPrinter {
public:
std::ostream& Out;
DeclPrinter(std::ostream* out) : Out(out ? *out : *llvm::cerr.stream()) {}
DeclPrinter() : Out(*llvm::cerr.stream()) {}
void PrintDecl(Decl *D);
void PrintFunctionDeclStart(FunctionDecl *FD);
void PrintTypeDefDecl(TypedefDecl *TD);
void PrintLinkageSpec(LinkageSpecDecl *LS);
void PrintObjCMethodDecl(ObjCMethodDecl *OMD);
void PrintObjCImplementationDecl(ObjCImplementationDecl *OID);
void PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID);
void PrintObjCProtocolDecl(ObjCProtocolDecl *PID);
void PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID);
void PrintObjCCategoryDecl(ObjCCategoryDecl *PID);
void PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID);
void PrintObjCPropertyDecl(ObjCPropertyDecl *PD);
void PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID);
};
} // end anonymous namespace
void DeclPrinter:: PrintDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
PrintFunctionDeclStart(FD);
if (FD->getBody()) {
Out << ' ';
FD->getBody()->printPretty(Out);
Out << '\n';
}
} else if (isa<ObjCMethodDecl>(D)) {
// Do nothing, methods definitions are printed in
// PrintObjCImplementationDecl.
} else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
PrintTypeDefDecl(TD);
} else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
PrintObjCInterfaceDecl(OID);
} else if (ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(D)) {
PrintObjCProtocolDecl(PID);
} else if (ObjCForwardProtocolDecl *OFPD =
dyn_cast<ObjCForwardProtocolDecl>(D)) {
Out << "@protocol ";
for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
const ObjCProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
if (i) Out << ", ";
Out << D->getName();
}
Out << ";\n";
} else if (ObjCImplementationDecl *OID =
dyn_cast<ObjCImplementationDecl>(D)) {
PrintObjCImplementationDecl(OID);
} else if (ObjCCategoryImplDecl *OID =
dyn_cast<ObjCCategoryImplDecl>(D)) {
PrintObjCCategoryImplDecl(OID);
} else if (ObjCCategoryDecl *OID =
dyn_cast<ObjCCategoryDecl>(D)) {
PrintObjCCategoryDecl(OID);
} else if (ObjCCompatibleAliasDecl *OID =
dyn_cast<ObjCCompatibleAliasDecl>(D)) {
PrintObjCCompatibleAliasDecl(OID);
} else if (ObjCClassDecl *OFCD = dyn_cast<ObjCClassDecl>(D)) {
Out << "@class ";
ObjCInterfaceDecl **ForwardDecls = OFCD->getForwardDecls();
for (unsigned i = 0, e = OFCD->getNumForwardDecls(); i != e; ++i) {
const ObjCInterfaceDecl *D = ForwardDecls[i];
if (i) Out << ", ";
Out << D->getName();
}
Out << ";\n";
} else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
} else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
PrintLinkageSpec(LSD);
} else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) {
Out << "asm(";
AD->getAsmString()->printPretty(Out);
Out << ")\n";
} else {
assert(0 && "Unknown decl type!");
}
}
void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
bool HasBody = FD->getBody();
Out << '\n';
switch (FD->getStorageClass()) {
default: assert(0 && "Unknown storage class");
case FunctionDecl::None: break;
case FunctionDecl::Extern: Out << "extern "; break;
case FunctionDecl::Static: Out << "static "; break;
case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
}
if (FD->isInline())
Out << "inline ";
std::string Proto = FD->getName();
const FunctionType *AFT = FD->getType()->getAsFunctionType();
if (const FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
Proto += "(";
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
if (i) Proto += ", ";
std::string ParamStr;
if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
FT->getArgType(i).getAsStringInternal(ParamStr);
Proto += ParamStr;
}
if (FT->isVariadic()) {
if (FD->getNumParams()) Proto += ", ";
Proto += "...";
}
Proto += ")";
} else {
assert(isa<FunctionTypeNoProto>(AFT));
Proto += "()";
}
AFT->getResultType().getAsStringInternal(Proto);
Out << Proto;
if (!FD->getBody())
Out << ";\n";
// Doesn't print the body.
}
void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
std::string S = TD->getName();
TD->getUnderlyingType().getAsStringInternal(S);
Out << "typedef " << S << ";\n";
}
void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
const char *l;
if (LS->getLanguage() == LinkageSpecDecl::lang_c)
l = "C";
else {
assert(LS->getLanguage() == LinkageSpecDecl::lang_cxx &&
"unknown language in linkage specification");
l = "C++";
}
Out << "extern \"" << l << "\" { ";
PrintDecl(LS->getDecl());
Out << "}\n";
}
void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstance())
Out << "\n- ";
else
Out << "\n+ ";
if (!OMD->getResultType().isNull())
Out << '(' << OMD->getResultType().getAsString() << ")";
std::string name = OMD->getSelector().getName();
std::string::size_type pos, lastPos = 0;
for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i) {
ParmVarDecl *PDecl = OMD->getParamDecl(i);
// FIXME: selector is missing here!
pos = name.find_first_of(":", lastPos);
Out << " " << name.substr(lastPos, pos - lastPos);
Out << ":(" << PDecl->getType().getAsString() << ")" << PDecl->getName();
lastPos = pos + 1;
}
if (OMD->getNumParams() == 0)
Out << " " << name;
if (OMD->isVariadic())
Out << ", ...";
Out << ";";
}
void DeclPrinter::PrintObjCImplementationDecl(ObjCImplementationDecl *OID) {
std::string I = OID->getName();
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
Out << "@implementation " << I << " : " << SID->getName();
else
Out << "@implementation " << I;
for (ObjCImplementationDecl::instmeth_iterator I = OID->instmeth_begin(),
E = OID->instmeth_end(); I != E; ++I) {
ObjCMethodDecl *OMD = *I;
PrintObjCMethodDecl(OMD);
if (OMD->getBody()) {
Out << ' ';
OMD->getBody()->printPretty(Out);
Out << '\n';
}
}
for (ObjCImplementationDecl::classmeth_iterator I = OID->classmeth_begin(),
E = OID->classmeth_end(); I != E; ++I) {
ObjCMethodDecl *OMD = *I;
PrintObjCMethodDecl(OMD);
if (OMD->getBody()) {
Out << ' ';
OMD->getBody()->printPretty(Out);
Out << '\n';
}
}
for (ObjCImplementationDecl::propimpl_iterator I = OID->propimpl_begin(),
E = OID->propimpl_end(); I != E; ++I)
PrintObjCPropertyImplDecl(*I);
Out << "@end\n";
}
void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
std::string I = OID->getName();
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
Out << "@interface " << I << " : " << SID->getName();
else
Out << "@interface " << I;
// Protocols?
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
if (!Protocols.empty()) {
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end(); I != E; ++I)
Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getName();
}
if (!Protocols.empty())
Out << ">";
Out << '\n';
if (OID->ivar_size() > 0) {
Out << '{';
for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
E = OID->ivar_end(); I != E; ++I) {
Out << '\t' << (*I)->getType().getAsString()
<< ' ' << (*I)->getName() << ";\n";
}
Out << "}\n";
}
for (ObjCInterfaceDecl::classprop_iterator I = OID->classprop_begin(),
E = OID->classprop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
bool eol_needed = false;
for (ObjCInterfaceDecl::classmeth_iterator I = OID->classmeth_begin(),
E = OID->classmeth_end(); I != E; ++I)
eol_needed = true, PrintObjCMethodDecl(*I);
for (ObjCInterfaceDecl::instmeth_iterator I = OID->instmeth_begin(),
E = OID->instmeth_end(); I != E; ++I)
eol_needed = true, PrintObjCMethodDecl(*I);
Out << (eol_needed ? "\n@end\n" : "@end\n");
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCProtocolDecl(ObjCProtocolDecl *PID) {
Out << "@protocol " << PID->getName() << '\n';
for (ObjCProtocolDecl::classprop_iterator I = PID->classprop_begin(),
E = PID->classprop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
Out << "@implementation "
<< PID->getClassInterface()->getName()
<< '(' << PID->getName() << ");\n";
for (ObjCCategoryImplDecl::propimpl_iterator I = PID->propimpl_begin(),
E = PID->propimpl_end(); I != E; ++I)
PrintObjCPropertyImplDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCategoryDecl(ObjCCategoryDecl *PID) {
Out << "@interface "
<< PID->getClassInterface()->getName()
<< '(' << PID->getName() << ");\n";
// Output property declarations.
for (ObjCCategoryDecl::classprop_iterator I = PID->classprop_begin(),
E = PID->classprop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
Out << "@compatibility_alias " << AID->getName()
<< ' ' << AID->getClassInterface()->getName() << ";\n";
}
/// PrintObjCPropertyDecl - print a property declaration.
///
void DeclPrinter::PrintObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
Out << "@required\n";
else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
Out << "@optional\n";
Out << "@property";
if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
bool first = true;
Out << " (";
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_readonly) {
Out << (first ? ' ' : ',') << "readonly";
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
Out << (first ? ' ' : ',') << "getter = "
<< PDecl->getGetterName().getName();
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
Out << (first ? ' ' : ',') << "setter = "
<< PDecl->getSetterName().getName();
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
Out << (first ? ' ' : ',') << "assign";
first = false;
}
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_readwrite) {
Out << (first ? ' ' : ',') << "readwrite";
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
Out << (first ? ' ' : ',') << "retain";
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
Out << (first ? ' ' : ',') << "copy";
first = false;
}
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_nonatomic) {
Out << (first ? ' ' : ',') << "nonatomic";
first = false;
}
Out << " )";
}
Out << ' ' << PDecl->getType().getAsString()
<< ' ' << PDecl->getName();
Out << ";\n";
}
/// PrintObjCPropertyImplDecl - Print an objective-c property implementation
/// declaration syntax.
///
void DeclPrinter::PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
if (PID->getPropertyImplementation() ==
ObjCPropertyImplDecl::OBJC_PR_IMPL_SYNTHSIZE)
Out << "\n@synthesize ";
else
Out << "\n@dynamic ";
Out << PID->getPropertyDecl()->getName();
if (PID->getPropertyIvarDecl())
Out << "=" << PID->getPropertyIvarDecl()->getName();
Out << ";\n";
}
//===----------------------------------------------------------------------===//
/// ASTPrinter - Pretty-printer of ASTs
namespace {
class ASTPrinter : public ASTConsumer, public DeclPrinter {
public:
ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}
virtual void HandleTopLevelDecl(Decl *D) {
PrintDecl(D);
}
};
}
ASTConsumer *clang::CreateASTPrinter(std::ostream* out) {
return new ASTPrinter(out);
}
//===----------------------------------------------------------------------===//
/// ASTDumper - Low-level dumper of ASTs
namespace {
class ASTDumper : public ASTConsumer, public DeclPrinter {
SourceManager *SM;
public:
ASTDumper() : DeclPrinter() {}
void Initialize(ASTContext &Context) {
SM = &Context.getSourceManager();
}
virtual void HandleTopLevelDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
PrintFunctionDeclStart(FD);
if (FD->getBody()) {
Out << '\n';
// FIXME: convert dumper to use std::ostream?
FD->getBody()->dumpAll(*SM);
Out << '\n';
}
} else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
PrintTypeDefDecl(TD);
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
} else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
Out << "Read objc interface '" << OID->getName() << "'\n";
} else if (ObjCProtocolDecl *OPD = dyn_cast<ObjCProtocolDecl>(D)) {
Out << "Read objc protocol '" << OPD->getName() << "'\n";
} else if (ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(D)) {
Out << "Read objc category '" << OCD->getName() << "'\n";
} else if (isa<ObjCForwardProtocolDecl>(D)) {
Out << "Read objc fwd protocol decl\n";
} else if (isa<ObjCClassDecl>(D)) {
Out << "Read objc fwd class decl\n";
} else if (isa<FileScopeAsmDecl>(D)) {
Out << "Read file scope asm decl\n";
} else if (ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) {
Out << "Read objc method decl: '" << MD->getSelector().getName()
<< "'\n";
if (MD->getBody()) {
// FIXME: convert dumper to use std::ostream?
MD->getBody()->dumpAll(*SM);
Out << '\n';
}
} else if (isa<ObjCImplementationDecl>(D)) {
Out << "Read objc implementation decl\n";
}
else {
assert(0 && "Unknown decl type!");
}
}
};
}
ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
//===----------------------------------------------------------------------===//
/// ASTViewer - AST Visualization
namespace {
class ASTViewer : public ASTConsumer {
SourceManager *SM;
public:
void Initialize(ASTContext &Context) {
SM = &Context.getSourceManager();
}
virtual void HandleTopLevelDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
DeclPrinter().PrintFunctionDeclStart(FD);
if (FD->getBody()) {
llvm::cerr << '\n';
FD->getBody()->viewAST();
llvm::cerr << '\n';
}
}
else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
DeclPrinter().PrintObjCMethodDecl(MD);
if (MD->getBody()) {
llvm::cerr << '\n';
MD->getBody()->viewAST();
llvm::cerr << '\n';
}
}
}
};
}
ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
//===----------------------------------------------------------------------===//
// AST Serializer
namespace {
class ASTSerializer : public ASTConsumer {
protected:
Diagnostic& Diags;
public:
ASTSerializer(Diagnostic& diags) : Diags(diags) {}
};
class SingleFileSerializer : public ASTSerializer {
const llvm::sys::Path FName;
public:
SingleFileSerializer(const llvm::sys::Path& F, Diagnostic& diags)
: ASTSerializer(diags), FName(F) {}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
if (Diags.hasErrorOccurred())
return;
EmitASTBitcodeFile(&TU, FName);
}
};
class BuildSerializer : public ASTSerializer {
llvm::sys::Path EmitDir;
public:
BuildSerializer(const llvm::sys::Path& dir, Diagnostic& diags)
: ASTSerializer(diags), EmitDir(dir) {}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
if (Diags.hasErrorOccurred())
return;
SourceManager& SourceMgr = TU.getContext().getSourceManager();
unsigned ID = SourceMgr.getMainFileID();
assert (ID && "MainFileID not set!");
const FileEntry* FE = SourceMgr.getFileEntryForID(ID);
assert (FE && "No FileEntry for main file.");
// FIXME: This is not portable to Windows.
// FIXME: This logic should probably be moved elsewhere later.
llvm::sys::Path FName(EmitDir);
std::vector<char> buf;
buf.reserve(strlen(FE->getName())+100);
sprintf(&buf[0], "dev_%llx", (uint64_t) FE->getDevice());
FName.appendComponent(&buf[0]);
FName.createDirectoryOnDisk(true);
if (!FName.canWrite() || !FName.isDirectory()) {
assert (false && "Could not create 'device' serialization directory.");
return;
}
sprintf(&buf[0], "%s-%llX.ast", FE->getName(), (uint64_t) FE->getInode());
FName.appendComponent(&buf[0]);
EmitASTBitcodeFile(&TU, FName);
// Now emit the sources.
}
};
} // end anonymous namespace
ASTConsumer* clang::CreateASTSerializer(const std::string& InFile,
const std::string& OutputFile,
Diagnostic &Diags) {
if (OutputFile.size()) {
if (InFile == "-") {
llvm::cerr <<
"error: Cannot use --serialize with -o for source read from STDIN.\n";
return NULL;
}
// The user specified an AST-emission directory. Determine if the path
// is absolute.
llvm::sys::Path EmitDir(OutputFile);
if (!EmitDir.isAbsolute()) {
llvm::cerr <<
"error: Output directory for --serialize must be an absolute path.\n";
return NULL;
}
// Create the directory if it does not exist.
EmitDir.createDirectoryOnDisk(true);
if (!EmitDir.canWrite() || !EmitDir.isDirectory()) {
llvm::cerr <<
"error: Could not create output directory for --serialize.\n";
return NULL;
}
// FIXME: We should probably only allow using BuildSerializer when
// the ASTs come from parsed source files, and not from .ast files.
return new BuildSerializer(EmitDir, Diags);
}
// The user did not specify an output directory for serialized ASTs.
// Serialize the translation to a single file whose name is the same
// as the input file with the ".ast" extension appended.
llvm::sys::Path FName(InFile.c_str());
FName.appendSuffix("ast");
return new SingleFileSerializer(FName, Diags);
}
class LLVMCodeGenWriter : public ASTConsumer {
llvm::OwningPtr<CodeGenerator> Gen;
const std::string &InFile;
const std::string &OutputFile;
bool EmitBitcode;
public:
LLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags, const LangOptions &Features,
const std::string& infile, const std::string& outfile,
bool GenerateDebugInfo)
: Gen(CreateLLVMCodeGen(Diags, Features, infile, GenerateDebugInfo)),
InFile(infile), OutputFile(outfile), EmitBitcode(EmitBC) {}
virtual void Initialize(ASTContext &Context) {
Gen->Initialize(Context);
}
virtual void InitializeTU(TranslationUnit& TU) {
Gen->InitializeTU(TU);
}
virtual void HandleTopLevelDecl(Decl *D) {
Gen->HandleTopLevelDecl(D);
}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
Gen->HandleTranslationUnit(TU);
}
virtual void HandleTagDeclDefinition(TagDecl *D) {
Gen->HandleTagDeclDefinition(D);
}
virtual ~LLVMCodeGenWriter() {
llvm::OwningPtr<llvm::Module> CodeGenModule(Gen->ReleaseModule());
if (!CodeGenModule)
return;
std::ostream *Out;
if (OutputFile == "-") {
Out = llvm::cout.stream();
} else if (!OutputFile.empty()) {
Out = new std::ofstream(OutputFile.c_str(),
std::ios_base::binary|std::ios_base::out);
} else if (InFile == "-") {
Out = llvm::cout.stream();
} else {
llvm::sys::Path Path(InFile);
Path.eraseSuffix();
if (!EmitBitcode)
Path.appendSuffix("ll");
else
Path.appendSuffix("bc");
Out = new std::ofstream(Path.toString().c_str(),
std::ios_base::binary|std::ios_base::out);
}
if (!EmitBitcode)
*Out << *CodeGenModule.get();
else
llvm::WriteBitcodeToFile(CodeGenModule.get(), *Out);
if (Out != llvm::cout.stream())
delete Out;
}
};
ASTConsumer *clang::CreateLLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags,
const LangOptions &Features,
const std::string& InFile,
const std::string& OutFile,
bool GenerateDebugInfo) {
return new LLVMCodeGenWriter(EmitBC, Diags, Features, InFile, OutFile,
GenerateDebugInfo);
}