34#include "llvm/Support/raw_ostream.h"
36#include "clang/AST/ASTContext.h"
38#include "clang/Frontend/CompilerInstance.h"
40#include "clang/Lex/Preprocessor.h"
41#include "clang/Lex/Pragma.h"
43#include "cling/Interpreter/CIFactory.h"
44#include "cling/Interpreter/Interpreter.h"
147 vsr.SetAttributeValue(
"pattern",
"*");
155 vsr.SetAttributeValue(
"pattern",
"*");
166 esr.SetAttributeValue(
"pattern",
"*");
172 esr2.SetAttributeValue(
"pattern",
"*::*");
176 esr.SetAttributeValue(
"pattern",
"*");
183 fsr.SetAttributeValue(
"pattern",
"*");
199 csr3.SetAttributeValue(
"pattern",
"__va_*");
203 csr.SetAttributeValue(
"pattern",
"*");
204 csr2.SetAttributeValue(
"pattern",
"*::*");
213 csr.SetAttributeValue(
"pattern",
"*");
214 csr2.SetAttributeValue(
"pattern",
"*::*");
244 vsr.SetAttributeValue(
"pattern",
"*");
251 esr.SetAttributeValue(
"pattern",
"*");
258 fsr.SetAttributeValue(
"pattern",
"*");
265 csr.SetAttributeValue(
"pattern",
"*");
266 csr2.SetAttributeValue(
"pattern",
"*::*");
277 csr.SetRequestStreamerInfo(
true);
278 csr2.SetRequestStreamerInfo(
true);
362 csr.SetRequestOnlyTClass(
true);
366 const std::string
protStr(
"+protected");
367 const std::string
privStr(
"+private");
370 csr.SetRequestProtected(
true);
374 csr.SetRequestPrivate(
true);
389 csr.SetRequestStreamerInfo(
true);
392 csr.SetRequestNoInputOperator(
true);
395 csr.SetRequestNoStreamer(
true);
413 if (
csr.RequestStreamerInfo() &&
csr.RequestNoStreamer()) {
414 std::cerr <<
"Warning: " <<
localIdentifier <<
" option + mutual exclusive with -, + prevails\n";
415 csr.SetRequestNoStreamer(
false);
430 csr2.SetAttributeValue(
"pattern",
"*::*");
435 csr3.SetAttributeValue(
"pattern",
"__va_*");
443 csr2.SetAttributeValue(
"pattern",
"*::*");
448 esr.SetAttributeValue(
"pattern",
"*::*");
476 csr.SetAttributeValue(
"fromTypedef",
"true");
503 if (pos > -1)
return true;
525 std::cout <<
"Error at line " <<
fLine <<
" - too many ( in function prototype!" << std::endl;
533 std::cout <<
"Error at line " <<
fLine <<
" - too many ) in function prototype!" << std::endl;
539 std::cout <<
"Error at line " <<
fLine <<
" - missing ) in function prototype" << std::endl;
543 std::cout <<
"Error at line " <<
fLine <<
" - wrong order of ( and ) in function prototype" << std::endl;
559 std::cout <<
"Error at line " <<
fLine <<
" - missing ( in function prototype" << std::endl;
578 pos = pattern.find(
" ", pos + 1);
582 if ((pos < 0) && (
pos1 < 0) && (
pos2 < 0))
break;
587 if (pos < 0)
continue;
593 if (pos > 0)
before = pattern.at(pos - 1);
594 if (pos < (
int)(pattern.length() - 1))
after = pattern.at(pos + 1);
618 std::cout <<
"Error at line " <<
fLine - 1 <<
" - extra space" << std::endl;
621 pattern.erase(pos, 1);
625 std::cout <<
"Error at line " <<
fLine <<
" - number of < doesn't match number of >" << std::endl;
628 pattern =
"operator*(*" + pattern +
"*)";
641 void Error(
const char *message,
const clang::Token &
tok,
642 const clang::Preprocessor&
PP,
bool source =
true) {
644 std::cerr << message <<
" at ";
645 const clang::SourceManager &
SM =
PP.getSourceManager();
646 tok.getLocation().dump(
SM);
649 std::cerr <<
SM.getCharacterData(
tok.getLocation());
655 clang::Preprocessor &
PP,
673 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::equal)) {
674 Error(
"Error: the 'options' keyword must be followed by an '='",
tok,
PP);
679 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
680 if (!
tok.getIdentifierInfo()) {
681 Error(
"Error: Malformed version option.",
tok,
PP);
682 }
else if (
tok.getIdentifierInfo()->getName() ==
"nomap") {
685 }
else if (
tok.getIdentifierInfo()->getName() ==
"nostreamer") options.
fNoStreamer = 1;
686 else if (
tok.getIdentifierInfo()->getName() ==
"noinputoper") options.
fNoInputOper = 1;
688 else if (
tok.getIdentifierInfo()->getName() ==
"rntupleStreamerMode") {
689 clang::Token start =
tok;
691 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::l_paren)) {
692 Error(
"Error: missing left parenthesis after rntupleStreamerMode.", start,
PP);
697 if (
tok.isNot(clang::tok::eod))
699 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::r_paren)) {
700 Error(
"Error: missing right parenthesis after rntupleStreamerMode.", start,
PP);
703 if (!
boolval.getIdentifierInfo()) {
704 Error(
"Error: Malformed rntupleStreamerMode option (either 'true' or 'false').",
boolval,
PP);
707 if (
boolval.getIdentifierInfo()->getName() ==
"false") {
709 Error(
"Error: Can only specify a single rntuple option "
710 "(either rntupleStreamerMode(true) or rntupleStreamerMode(false))",
715 }
else if (
boolval.getIdentifierInfo()->getName() ==
"true") {
717 Error(
"Error: Can only specify a single rntuple option "
718 "(either rntupleStreamerMode(true) or rntupleStreamerMode(false))",
724 Error(
"Error: Malformed rntupleStreamerMode option (either 'true' or 'false').",
boolval,
PP);
726 }
else if (
tok.getIdentifierInfo()->getName() ==
"stub") {
729 }
else if (
tok.getIdentifierInfo()->getName() ==
"version") {
730 clang::Token start =
tok;
732 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::l_paren)) {
733 Error(
"Error: missing left parenthesis after version.", start,
PP);
737 clang::Token number =
tok;
738 if (
tok.isNot(clang::tok::eod))
PP.Lex(
tok);
739 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::r_paren)) {
740 Error(
"Error: missing right parenthesis after version.", start,
PP);
743 if (!number.isLiteral()) {
744 std::cerr <<
"Error: Malformed version option, the value is not a non-negative number!";
747 std::string
verStr(number.getLiteralData(), number.getLength());
749 for (std::string::size_type i = 0; i <
verStr.size(); ++i)
753 std::cerr <<
"Error: Malformed version option! \"" <<
verStr <<
"\" is not a non-negative number!";
758 Error(
"Warning: ignoring unknown #pragma link option=",
tok,
PP);
761 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::comma)) {
781 clang::Token &
tok)
override {
786 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
787 if (!
tok.getIdentifierInfo())
return;
788 if (
tok.getIdentifierInfo()->getName() !=
"extra_include")
return;
794 if (
tok.is(clang::tok::eod)) {
795 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
798 const clang::SourceManager &
SM =
PP.getSourceManager();
799 const char *start =
SM.getCharacterData(
tok.getLocation());
802 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
806 if (
tok.isNot(clang::tok::semi)) {
807 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
810 if (end.is(clang::tok::unknown)) {
813 llvm::StringRef
include(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
831 clang::Token &
tok)
override {
836 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
837 if (!
tok.getIdentifierInfo())
return;
838 if (
tok.getIdentifierInfo()->getName() !=
"read")
return;
844 if (
tok.is(clang::tok::eod)) {
845 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
848 const clang::SourceManager&
SM =
PP.getSourceManager();
849 const char *start =
SM.getCharacterData(
tok.getLocation());
852 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
861 if (end.is(clang::tok::unknown)) {
864 llvm::StringRef
rule_text(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
891 clang::Token &
tok)
override {
896 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
897 if (!
tok.getIdentifierInfo())
return;
898 if (
tok.getIdentifierInfo()->getName() !=
"link")
return;
904 if (
tok.is(clang::tok::eod)) {
905 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
909 if (
tok.isAnyIdentifier()) {
910 if ((
tok.getIdentifierInfo()->getName() ==
"off")) {
912 }
else if ((
tok.getIdentifierInfo()->getName() ==
"C")) {
915 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::plusplus)) {
916 Error(
"Error ++ expected after '#pragma link C' at ",
tok,
PP);
920 Error(
"Error #pragma link should be followed by off or C",
tok,
PP);
929 if (
tok.is(clang::tok::eod)) {
930 Error(
"Error no arguments after #pragma link C++/off: ",
tok,
PP);
935 if (
linkOn)
Error(
"Error #pragma link C++ should be followed by identifier",
tok,
PP);
936 else Error(
"Error #pragma link off should be followed by identifier",
tok,
PP);
942 std::unique_ptr<LinkdefReader::Options> options;
943 if (
type ==
"options" ||
type ==
"option") {
948 if (
tok.getIdentifierInfo())
type =
tok.getIdentifierInfo()->getName();
951 PP.LexUnexpandedToken(
tok);
952 const clang::SourceManager &
SM =
PP.getSourceManager();
953 const char *start =
SM.getCharacterData(
tok.getLocation());
956 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
960 PP.LexUnexpandedToken(
tok);
963 if (
tok.isNot(clang::tok::semi)) {
964 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
968 if (end.is(clang::tok::unknown)) {
973 llvm::StringRef
identifier(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
997 clang::Token &
tok)
override {
1002 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
1003 if (!
tok.getIdentifierInfo())
return;
1004 if (
tok.getIdentifierInfo()->getName() !=
"create")
return;
1010 if (
tok.is(clang::tok::eod)) {
1011 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
1014 if ((
tok.getIdentifierInfo()->getName() !=
"TClass")) {
1015 Error(
"Error: currently only supporting TClass after '#pragma create':",
tok,
PP);
1020 const clang::SourceManager &
SM =
PP.getSourceManager();
1021 const char *start =
SM.getCharacterData(
tok.getLocation());
1022 clang::Token end =
tok;
1023 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
1028 if (
tok.isNot(clang::tok::semi)) {
1029 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
1033 llvm::StringRef
identifier(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
1055 for (
size_t i = 0,
n =
parserArgs.size(); i <
n; ++i) {
1060 std::unique_ptr<llvm::MemoryBuffer>
memBuf = llvm::MemoryBuffer::getMemBuffer(code,
"CLING #pragma extraction");
1065 clang::Preprocessor &
PP =
pragmaCI->getPreprocessor();
1081 PP.EnterMainSourceFile();
1085 }
while (
tok.isNot(clang::tok::annot_repl_input_end));
1088 return 0 ==
DClient.getNumErrors();
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
bool ProcessOptions(LinkdefReader::Options &options, clang::Preprocessor &PP, clang::Token &tok)
LinkdefReaderPragmaHandler(const char *which, LinkdefReader &owner)
void Error(const char *message, const clang::Token &tok, const clang::Preprocessor &PP, bool source=true)
bool ProcessOperators(std::string &pattern)
bool LoadIncludes(std::string &extraInclude)
SelectionRules * fSelectionRules
LinkdefReader(cling::Interpreter &interp, ROOT::TMetaUtils::RConstructorTypes &IOConstructorTypes)
bool ProcessFunctionPrototype(std::string &proto, bool &name)
static std::map< std::string, ECppNames > fgMapCppNames
cling::Interpreter & fInterp
bool IsPatternRule(const std::string &rule_token)
bool AddInclude(const std::string &include)
bool Parse(SelectionRules &sr, llvm::StringRef code, const std::vector< std::string > &parserArgs, const char *llvmdir)
static std::map< std::string, EPragmaNames > fgMapPragmaNames
static void PopulatePragmaMap()
static void PopulateCppMap()
bool AddRule(const std::string &ruletype, const std::string &identifier, bool linkOn, bool requestOnlyTClass, Options *option=nullptr)
ROOT::TMetaUtils::RConstructorTypes * fIOConstructorTypesPtr
void HandlePragma(clang::Preprocessor &PP, clang::PragmaIntroducer Introducer, clang::Token &tok) override
PragmaCreateCollector(LinkdefReader &owner)
void HandlePragma(clang::Preprocessor &PP, clang::PragmaIntroducer Introducer, clang::Token &tok) override
PragmaIoReadInclude(LinkdefReader &owner)
PragmaLinkCollector(LinkdefReader &owner)
void HandlePragma(clang::Preprocessor &PP, clang::PragmaIntroducer Introducer, clang::Token &tok) override
const_iterator end() const
The class representing the collection of selection rules.
void AddVariableSelectionRule(const VariableSelectionRule &varSel)
void AddClassSelectionRule(const ClassSelectionRule &classSel)
bool GetHasFileNameRule() const
void AddEnumSelectionRule(const EnumSelectionRule &enumSel)
void AddFunctionSelectionRule(const FunctionSelectionRule &funcSel)
void SetHasFileNameRule(bool file_rule)
void ProcessReadPragma(const char *args, std::string &error_string)
I am being called when a read pragma is encountered.
int fRNTupleSerializationMode