35#include "llvm/Support/raw_ostream.h"
37#include "clang/AST/ASTContext.h"
39#include "clang/Frontend/CompilerInstance.h"
41#include "clang/Lex/Preprocessor.h"
42#include "clang/Lex/Pragma.h"
44#include "cling/Interpreter/CIFactory.h"
45#include "cling/Interpreter/Interpreter.h"
149 vsr.SetAttributeValue(
"pattern",
"*");
157 vsr.SetAttributeValue(
"pattern",
"*");
168 esr.SetAttributeValue(
"pattern",
"*");
174 esr2.SetAttributeValue(
"pattern",
"*::*");
178 esr.SetAttributeValue(
"pattern",
"*");
185 fsr.SetAttributeValue(
"pattern",
"*");
201 csr3.SetAttributeValue(
"pattern",
"__va_*");
205 csr.SetAttributeValue(
"pattern",
"*");
206 csr2.SetAttributeValue(
"pattern",
"*::*");
215 csr.SetAttributeValue(
"pattern",
"*");
216 csr2.SetAttributeValue(
"pattern",
"*::*");
246 vsr.SetAttributeValue(
"pattern",
"*");
253 esr.SetAttributeValue(
"pattern",
"*");
260 fsr.SetAttributeValue(
"pattern",
"*");
267 csr.SetAttributeValue(
"pattern",
"*");
268 csr2.SetAttributeValue(
"pattern",
"*::*");
279 csr.SetRequestStreamerInfo(
true);
280 csr2.SetRequestStreamerInfo(
true);
364 csr.SetRequestOnlyTClass(
true);
368 const std::string
protStr(
"+protected");
369 const std::string
privStr(
"+private");
372 csr.SetRequestProtected(
true);
376 csr.SetRequestPrivate(
true);
391 csr.SetRequestStreamerInfo(
true);
394 csr.SetRequestNoInputOperator(
true);
397 csr.SetRequestNoStreamer(
true);
416 if (
csr.RequestStreamerInfo() &&
csr.RequestNoStreamer()) {
417 std::cerr <<
"Warning: " <<
localIdentifier <<
" option + mutual exclusive with -, + prevails\n";
418 csr.SetRequestNoStreamer(
false);
433 csr2.SetAttributeValue(
"pattern",
"*::*");
438 csr3.SetAttributeValue(
"pattern",
"__va_*");
446 csr2.SetAttributeValue(
"pattern",
"*::*");
451 esr.SetAttributeValue(
"pattern",
"*::*");
479 csr.SetAttributeValue(
"fromTypedef",
"true");
506 if (pos > -1)
return true;
528 std::cout <<
"Error at line " <<
fLine <<
" - too many ( in function prototype!" << std::endl;
536 std::cout <<
"Error at line " <<
fLine <<
" - too many ) in function prototype!" << std::endl;
542 std::cout <<
"Error at line " <<
fLine <<
" - missing ) in function prototype" << std::endl;
546 std::cout <<
"Error at line " <<
fLine <<
" - wrong order of ( and ) in function prototype" << std::endl;
562 std::cout <<
"Error at line " <<
fLine <<
" - missing ( in function prototype" << std::endl;
581 pos = pattern.find(
" ", pos + 1);
585 if ((pos < 0) && (
pos1 < 0) && (
pos2 < 0))
break;
590 if (pos < 0)
continue;
596 if (pos > 0)
before = pattern.at(pos - 1);
597 if (pos < (
int)(pattern.length() - 1))
after = pattern.at(pos + 1);
621 std::cout <<
"Error at line " <<
fLine - 1 <<
" - extra space" << std::endl;
624 pattern.erase(pos, 1);
628 std::cout <<
"Error at line " <<
fLine <<
" - number of < doesn't match number of >" << std::endl;
631 pattern =
"operator*(*" + pattern +
"*)";
644 void Error(
const char *message,
const clang::Token &
tok,
645 const clang::Preprocessor&
PP,
bool source =
true) {
647 std::cerr << message <<
" at ";
648 const clang::SourceManager &
SM =
PP.getSourceManager();
649 tok.getLocation().dump(
SM);
652 std::cerr <<
SM.getCharacterData(
tok.getLocation());
658 clang::Preprocessor &
PP,
677 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::equal)) {
678 Error(
"Error: the 'options' keyword must be followed by an '='",
tok,
PP);
683 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
684 if (!
tok.getIdentifierInfo()) {
685 Error(
"Error: Malformed version option.",
tok,
PP);
686 }
else if (
tok.getIdentifierInfo()->getName() ==
"nomap") {
689 }
else if (
tok.getIdentifierInfo()->getName() ==
"nostreamer") options.
fNoStreamer = 1;
690 else if (
tok.getIdentifierInfo()->getName() ==
"noinputoper") options.
fNoInputOper = 1;
692 else if (
tok.getIdentifierInfo()->getName() ==
"rntupleStreamerMode") {
693 clang::Token start =
tok;
695 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::l_paren)) {
696 Error(
"Error: missing left parenthesis after rntupleStreamerMode.", start,
PP);
701 if (
tok.isNot(clang::tok::eod))
703 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::r_paren)) {
704 Error(
"Error: missing right parenthesis after rntupleStreamerMode.", start,
PP);
707 if (!
boolval.getIdentifierInfo()) {
708 Error(
"Error: Malformed rntupleStreamerMode option (either 'true' or 'false').",
boolval,
PP);
711 if (
boolval.getIdentifierInfo()->getName() ==
"false") {
713 Error(
"Error: Can only specify a single rntuple option "
714 "(either rntupleStreamerMode(true) or rntupleStreamerMode(false))",
719 }
else if (
boolval.getIdentifierInfo()->getName() ==
"true") {
721 Error(
"Error: Can only specify a single rntuple option "
722 "(either rntupleStreamerMode(true) or rntupleStreamerMode(false))",
726 Error(
"Error: rntupleStreamerMode(true) and rntupleSoARecord are mutually exclusive",
boolval,
PP);
731 Error(
"Error: Malformed rntupleStreamerMode option (either 'true' or 'false').",
boolval,
PP);
733 }
else if (
tok.getIdentifierInfo()->getName() ==
"rntupleSoARecord") {
734 clang::Token start =
tok;
736 if (
tok.isNot(clang::tok::l_paren)) {
737 Error(
"Error: missing left parenthesis after rntupleSoARecord.", start,
PP);
742 if (
tok.isNot(clang::tok::eod))
744 if (
tok.isNot(clang::tok::r_paren)) {
745 Error(
"Error: missing right parenthesis after rntupleSoARecord.", start,
PP);
748 if (!
strval.getIdentifierInfo() ||
strval.getIdentifierInfo()->getName().empty()) {
749 Error(
"Error: Malformed rntupleSoARecord option.",
strval,
PP);
752 Error(
"Error: rntupleStreamerMode(true) and rntupleSoARecord are mutually exclusive",
strval,
PP);
755 }
else if (
tok.getIdentifierInfo()->getName() ==
"stub") {
758 }
else if (
tok.getIdentifierInfo()->getName() ==
"version") {
759 clang::Token start =
tok;
761 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::l_paren)) {
762 Error(
"Error: missing left parenthesis after version.", start,
PP);
766 clang::Token number =
tok;
767 if (
tok.isNot(clang::tok::eod))
PP.Lex(
tok);
768 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::r_paren)) {
769 Error(
"Error: missing right parenthesis after version.", start,
PP);
772 if (!number.isLiteral()) {
773 std::cerr <<
"Error: Malformed version option, the value is not a non-negative number!";
776 std::string
verStr(number.getLiteralData(), number.getLength());
778 for (std::string::size_type i = 0; i <
verStr.size(); ++i)
782 std::cerr <<
"Error: Malformed version option! \"" <<
verStr <<
"\" is not a non-negative number!";
787 Error(
"Warning: ignoring unknown #pragma link option=",
tok,
PP);
790 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::comma)) {
810 clang::Token &
tok)
override {
815 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
816 if (!
tok.getIdentifierInfo())
return;
817 if (
tok.getIdentifierInfo()->getName() !=
"extra_include")
return;
823 if (
tok.is(clang::tok::eod)) {
824 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
827 const clang::SourceManager &
SM =
PP.getSourceManager();
828 const char *start =
SM.getCharacterData(
tok.getLocation());
831 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
835 if (
tok.isNot(clang::tok::semi)) {
836 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
839 if (end.is(clang::tok::unknown)) {
842 llvm::StringRef
include(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
860 clang::Token &
tok)
override {
865 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
866 if (!
tok.getIdentifierInfo())
return;
867 if (
tok.getIdentifierInfo()->getName() !=
"read")
return;
873 if (
tok.is(clang::tok::eod)) {
874 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
877 const clang::SourceManager&
SM =
PP.getSourceManager();
878 const char *start =
SM.getCharacterData(
tok.getLocation());
881 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
890 if (end.is(clang::tok::unknown)) {
893 llvm::StringRef
rule_text(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
920 clang::Token &
tok)
override {
925 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
926 if (!
tok.getIdentifierInfo())
return;
927 if (
tok.getIdentifierInfo()->getName() !=
"link")
return;
933 if (
tok.is(clang::tok::eod)) {
934 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
938 if (
tok.isAnyIdentifier()) {
939 if ((
tok.getIdentifierInfo()->getName() ==
"off")) {
941 }
else if ((
tok.getIdentifierInfo()->getName() ==
"C")) {
944 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::plusplus)) {
945 Error(
"Error ++ expected after '#pragma link C' at ",
tok,
PP);
949 Error(
"Error #pragma link should be followed by off or C",
tok,
PP);
958 if (
tok.is(clang::tok::eod)) {
959 Error(
"Error no arguments after #pragma link C++/off: ",
tok,
PP);
964 if (
linkOn)
Error(
"Error #pragma link C++ should be followed by identifier",
tok,
PP);
965 else Error(
"Error #pragma link off should be followed by identifier",
tok,
PP);
971 std::unique_ptr<LinkdefReader::Options> options;
972 if (
type ==
"options" ||
type ==
"option") {
977 if (
tok.getIdentifierInfo())
type =
tok.getIdentifierInfo()->getName();
980 PP.LexUnexpandedToken(
tok);
981 const clang::SourceManager &
SM =
PP.getSourceManager();
982 const char *start =
SM.getCharacterData(
tok.getLocation());
985 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
989 PP.LexUnexpandedToken(
tok);
992 if (
tok.isNot(clang::tok::semi)) {
993 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
997 if (end.is(clang::tok::unknown)) {
1002 llvm::StringRef
identifier(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
1026 clang::Token &
tok)
override {
1031 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
1032 if (!
tok.getIdentifierInfo())
return;
1033 if (
tok.getIdentifierInfo()->getName() !=
"create")
return;
1039 if (
tok.is(clang::tok::eod)) {
1040 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
1043 if ((
tok.getIdentifierInfo()->getName() !=
"TClass")) {
1044 Error(
"Error: currently only supporting TClass after '#pragma create':",
tok,
PP);
1049 const clang::SourceManager &
SM =
PP.getSourceManager();
1050 const char *start =
SM.getCharacterData(
tok.getLocation());
1051 clang::Token end =
tok;
1052 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
1057 if (
tok.isNot(clang::tok::semi)) {
1058 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
1062 llvm::StringRef
identifier(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
1084 for (
size_t i = 0,
n =
parserArgs.size(); i <
n; ++i) {
1089 std::unique_ptr<llvm::MemoryBuffer>
memBuf = llvm::MemoryBuffer::getMemBuffer(code,
"CLING #pragma extraction");
1090 clang::CompilerInstance *
pragmaCI =
1092 std::nullopt , {} ,
true );
1094 clang::Preprocessor &
PP =
pragmaCI->getPreprocessor();
1110 PP.EnterMainSourceFile();
1114 }
while (
tok.isNot(clang::tok::annot_repl_input_end));
1117 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.
std::string fRNTupleSoARecord
int fRNTupleSerializationMode