#include <stdio.h>
-namespace {
- enum { BasicMetadataBlock = 1,
- ASTContextBlock = 2,
- DeclsBlock = 3 };
-}
-
using namespace clang;
+enum { BasicMetadataBlock = 1,
+ ASTContextBlock = 2,
+ DeclsBlock = 3 };
+
+
bool clang::EmitASTBitcodeFile(const TranslationUnit& TU,
const llvm::sys::Path& Filename) {
// around to the block for the Selectors during deserialization.
Sezr.EnterBlock();
+ // Emit the name of the source file.
+ Sezr.EmitCStr(SourceFile.c_str());
+ Sezr.FlushRecord();
+
// Emit the SourceManager.
Sezr.Emit(Context->getSourceManager());
FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
assert (FoundBlock);
+
+ { // Read the SourceFile.
+ char* SName = Dezr.ReadCStr(NULL,0,true);
+ TU->SourceFile = SName;
+ delete [] SName;
+ }
// Read the SourceManager.
SourceManager::CreateAndRegister(Dezr,FMgr);
TranslationUnit TU;
const llvm::sys::Path FName;
public:
- ASTSerializer(const llvm::sys::Path& F, Diagnostic &diags,
+ ASTSerializer(const std::string& SourceFile,
+ const llvm::sys::Path& F, Diagnostic &diags,
const LangOptions &LO)
- : Diags(diags), TU(LO), FName(F) {}
-
+ : Diags(diags), TU(SourceFile,LO), FName(F) {}
virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
TU.setContext(&Context);
} // end anonymous namespace
-ASTConsumer* clang::CreateASTSerializer(const std::string& InFile,
+ASTConsumer* clang::CreateASTSerializer(const std::string& SourceFile,
Diagnostic &Diags,
const LangOptions &Features) {
-
+ // FIXME: If the translation unit we are serializing came was itself
+ // deserialized from disk, we may overwrite that file. This
+ // is only a temporary bug, since the code in this function will
+ // be completely replaced momentarily.
+
// FIXME: This is a hack: "/" separator not portable.
- std::string::size_type idx = InFile.rfind("/");
+ std::string::size_type idx = SourceFile.rfind("/");
- if (idx != std::string::npos && idx == InFile.size()-1)
+ if (idx != std::string::npos && idx == SourceFile.size()-1)
return NULL;
std::string TargetPrefix( idx == std::string::npos ?
- InFile : InFile.substr(idx+1));
+ SourceFile : SourceFile.substr(idx+1));
llvm::sys::Path FName = llvm::sys::Path((TargetPrefix + ".ast").c_str());
- return new ASTSerializer(FName, Diags, Features);
+ return new ASTSerializer(SourceFile, FName, Diags, Features);
}
ASTConsumer *CreateUnitValsChecker(Diagnostic &Diags);
ASTConsumer *CreateLLVMEmitter(Diagnostic &Diags, const LangOptions &Features);
ASTConsumer *CreateCodeRewriterTest(Diagnostic &Diags);
-ASTConsumer *CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
+ASTConsumer *CreateSerializationTest(const std::string& SourceFile,
+ Diagnostic &Diags, FileManager& FMgr,
const LangOptions &LOpts);
-ASTConsumer *CreateASTSerializer(const std::string& InFile,
+ASTConsumer *CreateASTSerializer(const std::string& SourceFile,
Diagnostic &Diags, const LangOptions &LOpts);
} // end clang namespace
Diagnostic &Diags;
FileManager &FMgr;
public:
- SerializationTest(Diagnostic &d, FileManager& fmgr, const LangOptions& LOpts)
- : TU(LOpts), Diags(d), FMgr(fmgr) {}
+ SerializationTest(const std::string& SourceFile, Diagnostic &d,
+ FileManager& fmgr, const LangOptions& LOpts)
+ : TU(SourceFile, LOpts), Diags(d), FMgr(fmgr) {}
~SerializationTest();
virtual void HandleTopLevelDecl(Decl *D) {
TU.AddTopLevelDecl(D);
}
+
private:
bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
} // end anonymous namespace
ASTConsumer*
-clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
- const LangOptions &LOpts) {
- return new SerializationTest(Diags,FMgr,LOpts);
+clang::CreateSerializationTest(const std::string& SourceFile, Diagnostic &Diags,
+ FileManager& FMgr, const LangOptions &LOpts) {
+ return new SerializationTest(SourceFile,Diags,FMgr,LOpts);
}
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Signals.h"
#include "llvm/Config/config.h"
+#include "llvm/ADT/scoped_ptr.h"
#include <memory>
using namespace clang;
/// CreateASTConsumer - Create the ASTConsumer for the corresponding program
/// action. These consumers can operate on both ASTs that are freshly
/// parsed from source files as well as those deserialized from Bitcode.
-static ASTConsumer* CreateASTConsumer(const std::string& InFile,
+static ASTConsumer* CreateASTConsumer(const std::string& SourceFile,
Diagnostic& Diag, FileManager& FileMgr,
const LangOptions& LangOpts) {
switch (ProgAction) {
return CreateUnitValsChecker(Diag);
case TestSerialization:
- return CreateSerializationTest(Diag, FileMgr, LangOpts);
+ return CreateSerializationTest(SourceFile, Diag, FileMgr, LangOpts);
case EmitLLVM:
return CreateLLVMEmitter(Diag, LangOpts);
case SerializeAST:
// FIXME: Allow user to tailor where the file is written.
- return CreateASTSerializer(InFile, Diag, LangOpts);
+ return CreateASTSerializer(SourceFile, Diag, LangOpts);
case RewriteTest:
return CreateCodeRewriterTest(Diag);
/// ProcessInputFile - Process a single input file with the specified state.
///
static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
- const std::string &InFile,
+ const std::string &SourceFile,
TextDiagnostics &OurDiagnosticClient) {
ASTConsumer* Consumer = NULL;
switch (ProgAction) {
default:
- Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(),
+ Consumer = CreateASTConsumer(SourceFile, PP.getDiagnostics(),
PP.getFileManager(),
PP.getLangOptions());
}
if (Stats) {
- fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str());
+ fprintf(stderr, "\nSTATISTICS FOR '%s':\n", SourceFile.c_str());
PP.PrintStats();
PP.getIdentifierTable().PrintStats();
PP.getHeaderSearchInfo().PrintStats();
exit (1);
}
- TranslationUnit* TU = ReadASTBitcodeFile(Filename,FileMgr);
+ llvm::scoped_ptr<TranslationUnit> TU(ReadASTBitcodeFile(Filename,FileMgr));
if (!TU) {
fprintf(stderr, "error: file '%s' could not be deserialized\n",
exit (1);
}
- ASTConsumer* Consumer = CreateASTConsumer(InFile,Diag,
- FileMgr,TU->getLangOpts());
+ // Observe that we use the source file name stored in the deserialized
+ // translation unit, rather than InFile.
+ llvm::scoped_ptr<ASTConsumer>
+ Consumer(CreateASTConsumer(TU->getSourceFile(), Diag, FileMgr,
+ TU->getLangOpts()));
if (!Consumer) {
fprintf(stderr, "Unsupported program action with serialized ASTs!\n");
}
// FIXME: only work on consumers that do not require MainFileID.
- Consumer->Initialize(*TU->getContext(),0);
+ Consumer->Initialize(*TU->getContext(), 0);
for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I)
Consumer->HandleTopLevelDecl(*I);
-
- delete Consumer;
}
#include "llvm/Bitcode/SerializationFwd.h"
#include "llvm/System/Path.h"
#include <vector>
+#include <string>
namespace clang {
class FileEntry;
class TranslationUnit {
- // Information to help uniquely identify a translation unit on disk.
- // We may also incorporate a UUID in the future.
- uint64_t ino;
- uint64_t dev;
- const char* SourceFile;
-
- // The actual data of the translation unit.
+ std::string SourceFile;
LangOptions LangOpts;
ASTContext* Context;
std::vector<Decl*> TopLevelDecls;
// The default ctor is only invoked during deserialization.
- explicit TranslationUnit() : SourceFile(NULL), Context(NULL) {}
+ explicit TranslationUnit() : Context(NULL) {}
public:
- explicit TranslationUnit(const LangOptions& lopt)
- : LangOpts(lopt), Context(NULL) {}
+ explicit TranslationUnit(const std::string& sourcefile,
+ const LangOptions& lopt)
+ : SourceFile(sourcefile), LangOpts(lopt), Context(NULL) {}
+
- explicit TranslationUnit(const LangOptions& lopt, ASTContext& context)
- : LangOpts(lopt), Context(&context) {}
-
void setContext(ASTContext* context) { Context = context; }
ASTContext* getContext() const { return Context; }
const LangOptions& getLangOpts() const { return LangOpts; }
+ const std::string& getSourceFile() const { return SourceFile; }
/// Emit - Emit the translation unit to an arbitray bitcode stream.
void Emit(llvm::Serializer& S) const;