Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

- Add new TPPClingCallbacks class & two new methods TCling__CompileMacro... #4

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions core/meta/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,23 @@ extern "C" int TCling__AutoLoadCallback(const char* className)
return gCling->AutoLoad(cls.c_str());
}

extern "C" int TCling__CompileMacro(const char *fileName, const char *options)
{
string file(fileName);
string opt(options);
return gSystem->CompileMacro(file.c_str(), opt.c_str());
}

extern "C" string TCling__SplitAclicMode(const char* fileName, string &mode,
string &args, string &io)
{
string file(fileName);
TString fname, amode, arguments, aclicio;
fname = gSystem->SplitAclicMode(file.c_str(), amode, arguments, aclicio);
mode = amode.Data(); args = arguments.Data(); io = aclicio.Data();
return string(fname.Data());
}

//______________________________________________________________________________
//
//
Expand Down
85 changes: 85 additions & 0 deletions core/meta/src/TClingCallbacks.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"

#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/PPCallbacks.h"
#include "llvm/Support/FileSystem.h"

using namespace clang;
using namespace cling;

Expand All @@ -37,15 +41,96 @@ extern "C" {
Decl* TCling__GetObjectDecl(TObject *obj);
int TCling__AutoLoadCallback(const char* className);
void TCling__UpdateListsOnDeclDeserialized(const clang::Decl*);
int TCling__CompileMacro(const char *fileName, const char *options);
std::string TCling__SplitAclicMode(const char* fileName, std::string &mode,
std::string &args, std::string &io);
}

// Preprocessor callbacks used to handle special cases
// like for example: #include "myMacro.C+"
//
class TPPClingCallbacks : public PPCallbacks {
private:
cling::Interpreter *fInterpreter;
Preprocessor *fPreprocessor;
bool fOldFlag;
bool fChanged;
public:
TPPClingCallbacks(cling::Interpreter *inter, Preprocessor *PP) :
fInterpreter(inter), fPreprocessor(PP), fOldFlag(false),
fChanged(false) { }
~TPPClingCallbacks() { }

virtual bool FileNotFound(llvm::StringRef FileName,
llvm::SmallVectorImpl<char> &RecoveryPath) {
// Method called via Callbacks->FileNotFound(Filename, RecoveryPath)
// in Preprocessor::HandleIncludeDirective(), initally allowing to
// change the include path, and allowing us to compile code via ACLiC
// when specifying #include "myfile.C+", and suppressing the preprocessor
// error message:
// input_line_23:1:10: fatal error: 'myfile.C+' file not found
if ((!fPreprocessor) || (!fInterpreter))
return false;

// remove any trailing "\n
std::string filename(FileName.str().substr(0,
FileName.str().find_last_of('"')));
std::string mode, arguments, io;
// extract the filename and ACliC mode
std::string fname = TCling__SplitAclicMode(filename.c_str(), mode,
arguments, io);
if (mode.length() > 0) {
if (llvm::sys::fs::exists(fname)) {
// format the CompileMacro() option string
std::string options = "k";
if (mode.find("++") != std::string::npos) options += "f";
if (mode.find("g") != std::string::npos) options += "g";
if (mode.find("O") != std::string::npos) options += "O";

// Save state of the preprocessor
Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(*fPreprocessor);
Parser& P = const_cast<Parser&>(fInterpreter->getParser());
Parser::ParserCurTokRestoreRAII savedCurToken(P);

// After we have saved the token reset the current one to
// something which is safe (semi colon usually means empty decl)
Token& Tok = const_cast<Token&>(P.getCurToken());
Tok.setKind(tok::semi);

int retcode = TCling__CompileMacro(fname.c_str(), options.c_str());
if (retcode) {
// complation was successful, let's remember the original
// preprocessor "include not found" error suppression flag
if (!fChanged)
fOldFlag = fPreprocessor->GetSuppressIncludeNotFoundError();
fPreprocessor->SetSuppressIncludeNotFoundError(true);
fChanged = true;
}
return true;
}
}
if (fChanged) {
// restore the original preprocessor "include not found" error
// suppression flag
fPreprocessor->SetSuppressIncludeNotFoundError(fOldFlag);
fChanged = false;
}
return false;
}

};

TClingCallbacks::TClingCallbacks(cling::Interpreter* interp)
: InterpreterCallbacks(interp),
fLastLookupCtx(0), fROOTSpecialNamespace(0), fFirstRun(true),
fIsAutoloading(false), fIsAutoloadingRecursively(false) {
Transaction* T = 0;
m_Interpreter->declare("namespace __ROOT_SpecialObjects{}", &T);
fROOTSpecialNamespace = dyn_cast<NamespaceDecl>(T->getFirstDecl().getSingleDecl());
// Add PreProcessor callback implementing FileNotFound(Filename, RecoveryPath)
// in order to properly handle #include "myMacro.C+"
Preprocessor &PP = interp->getCI()->getPreprocessor();
PP.addPPCallbacks(new TPPClingCallbacks(interp, &PP));
}

//pin the vtable here
Expand Down