cling/lib/Interpreter/ClingPragmas.cpp
Axel Naumann 1ffc20a6b2 Add a cling pragma handler. For now implement #pragma cling load(file)
Extremely handy for sources that require certain libraries to be loaded;
it's similar to MSVC's #pragma comment(lib"libToLink").
2015-02-18 14:51:21 +01:00

83 lines
2.9 KiB
C++

//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
#include "ClingPragmas.h"
#include "cling/Interpreter/Interpreter.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "clang/Parse/Parser.h"
using namespace cling;
using namespace clang;
namespace {
class PHLoad: public PragmaHandler {
Interpreter& m_Interp;
public:
PHLoad(Interpreter& interp):
PragmaHandler("load"), m_Interp(interp) {}
void HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &FirstToken) override {
// TODO: use Diagnostics!
struct SkipToEOD_t {
Preprocessor& m_PP;
SkipToEOD_t(Preprocessor& PP): m_PP(PP) {}
~SkipToEOD_t() { m_PP.DiscardUntilEndOfDirective(); }
} SkipToEOD(PP);
Token Tok;
PP.Lex(Tok);
if (Tok.isNot(tok::l_paren)) {
llvm::errs() << "cling::PHLoad: expect '(' after #pragma cling load!\n";
return;
}
std::string FileName;
if (!PP.LexStringLiteral(Tok, FileName, "pragma cling load",
false /*allowMacroExpansion*/)) {
// already diagnosed.
return;
}
Preprocessor::CleanupAndRestoreCacheRAII cleanupRAII(PP);
clang::Parser& P = m_Interp.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& CurTok = const_cast<Token&>(P.getCurToken());
CurTok.setKind(tok::semi);
// We can't PushDeclContext, because we go up and the routine that pops
// the DeclContext assumes that we drill down always.
// We have to be on the global context. At that point we are in a
// wrapper function so the parent context must be the global.
TranslationUnitDecl* TU
= m_Interp.getCI()->getASTContext().getTranslationUnitDecl();
Sema::ContextAndScopeRAII pushedDCAndS(m_Interp.getSema(),
TU, m_Interp.getSema().TUScope);
Interpreter::PushTransactionRAII pushedT(&m_Interp);
m_Interp.loadFile(FileName, true /*allowSharedLib*/);
}
};
}
void cling::addClingPragmas(Interpreter& interp) {
Preprocessor& PP = interp.getCI()->getPreprocessor();
// PragmaNamespace / PP takes ownership of sub-handlers.
PP.AddPragmaHandler("cling", new PHLoad(interp));
}