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"
146 vsr.SetAttributeValue(
"pattern",
"*");
154 vsr.SetAttributeValue(
"pattern",
"*");
165 esr.SetAttributeValue(
"pattern",
"*");
171 esr2.SetAttributeValue(
"pattern",
"*::*");
175 esr.SetAttributeValue(
"pattern",
"*");
182 fsr.SetAttributeValue(
"pattern",
"*");
198 csr3.SetAttributeValue(
"pattern",
"__va_*");
202 csr.SetAttributeValue(
"pattern",
"*");
203 csr2.SetAttributeValue(
"pattern",
"*::*");
212 csr.SetAttributeValue(
"pattern",
"*");
213 csr2.SetAttributeValue(
"pattern",
"*::*");
243 vsr.SetAttributeValue(
"pattern",
"*");
250 esr.SetAttributeValue(
"pattern",
"*");
257 fsr.SetAttributeValue(
"pattern",
"*");
264 csr.SetAttributeValue(
"pattern",
"*");
265 csr2.SetAttributeValue(
"pattern",
"*::*");
276 csr.SetRequestStreamerInfo(
true);
277 csr2.SetRequestStreamerInfo(
true);
361 csr.SetRequestOnlyTClass(
true);
365 const std::string
protStr(
"+protected");
366 const std::string
privStr(
"+private");
369 csr.SetRequestProtected(
true);
373 csr.SetRequestPrivate(
true);
388 csr.SetRequestStreamerInfo(
true);
391 csr.SetRequestNoInputOperator(
true);
394 csr.SetRequestNoStreamer(
true);
410 if (
csr.RequestStreamerInfo() &&
csr.RequestNoStreamer()) {
411 std::cerr <<
"Warning: " <<
localIdentifier <<
" option + mutual exclusive with -, + prevails\n";
412 csr.SetRequestNoStreamer(
false);
427 csr2.SetAttributeValue(
"pattern",
"*::*");
432 csr3.SetAttributeValue(
"pattern",
"__va_*");
440 csr2.SetAttributeValue(
"pattern",
"*::*");
445 esr.SetAttributeValue(
"pattern",
"*::*");
473 csr.SetAttributeValue(
"fromTypedef",
"true");
500 if (pos > -1)
return true;
522 std::cout <<
"Error at line " <<
fLine <<
" - too many ( in function prototype!" << std::endl;
530 std::cout <<
"Error at line " <<
fLine <<
" - too many ) in function prototype!" << std::endl;
536 std::cout <<
"Error at line " <<
fLine <<
" - missing ) in function prototype" << std::endl;
540 std::cout <<
"Error at line " <<
fLine <<
" - wrong order of ( and ) in function prototype" << std::endl;
556 std::cout <<
"Error at line " <<
fLine <<
" - missing ( in function prototype" << std::endl;
575 pos = pattern.find(
" ", pos + 1);
579 if ((pos < 0) && (
pos1 < 0) && (
pos2 < 0))
break;
584 if (pos < 0)
continue;
590 if (pos > 0)
before = pattern.at(pos - 1);
591 if (pos < (
int)(pattern.length() - 1))
after = pattern.at(pos + 1);
615 std::cout <<
"Error at line " <<
fLine - 1 <<
" - extra space" << std::endl;
618 pattern.erase(pos, 1);
622 std::cout <<
"Error at line " <<
fLine <<
" - number of < doesn't match number of >" << std::endl;
625 pattern =
"operator*(*" + pattern +
"*)";
638 void Error(
const char *message,
const clang::Token &
tok,
639 const clang::Preprocessor&
PP,
bool source =
true) {
641 std::cerr << message <<
" at ";
642 const clang::SourceManager &
SM =
PP.getSourceManager();
643 tok.getLocation().dump(
SM);
646 std::cerr <<
SM.getCharacterData(
tok.getLocation());
652 clang::Preprocessor &
PP,
669 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::equal)) {
670 Error(
"Error: the 'options' keyword must be followed by an '='",
tok,
PP);
675 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
676 if (!
tok.getIdentifierInfo()) {
677 Error(
"Error: Malformed version option.",
tok,
PP);
678 }
else if (
tok.getIdentifierInfo()->getName() ==
"nomap") {
681 }
else if (
tok.getIdentifierInfo()->getName() ==
"nostreamer") options.
fNoStreamer = 1;
682 else if (
tok.getIdentifierInfo()->getName() ==
"noinputoper") options.
fNoInputOper = 1;
684 else if (
tok.getIdentifierInfo()->getName() ==
"stub") {
687 }
else if (
tok.getIdentifierInfo()->getName() ==
"version") {
688 clang::Token start =
tok;
690 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::l_paren)) {
691 Error(
"Error: missing left parenthesis after version.", start,
PP);
695 clang::Token number =
tok;
696 if (
tok.isNot(clang::tok::eod))
PP.Lex(
tok);
697 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::r_paren)) {
698 Error(
"Error: missing right parenthesis after version.", start,
PP);
701 if (!number.isLiteral()) {
702 std::cerr <<
"Error: Malformed version option, the value is not a non-negative number!";
705 std::string
verStr(number.getLiteralData(), number.getLength());
707 for (std::string::size_type i = 0; i <
verStr.size(); ++i)
711 std::cerr <<
"Error: Malformed version option! \"" <<
verStr <<
"\" is not a non-negative number!";
716 Error(
"Warning: ignoring unknown #pragma link option=",
tok,
PP);
719 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::comma)) {
739 clang::Token &
tok)
override {
744 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
745 if (!
tok.getIdentifierInfo())
return;
746 if (
tok.getIdentifierInfo()->getName() !=
"extra_include")
return;
752 if (
tok.is(clang::tok::eod)) {
753 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
756 const clang::SourceManager &
SM =
PP.getSourceManager();
757 const char *start =
SM.getCharacterData(
tok.getLocation());
760 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
764 if (
tok.isNot(clang::tok::semi)) {
765 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
768 if (end.is(clang::tok::unknown)) {
771 llvm::StringRef
include(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
789 clang::Token &
tok)
override {
794 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
795 if (!
tok.getIdentifierInfo())
return;
796 if (
tok.getIdentifierInfo()->getName() !=
"read")
return;
802 if (
tok.is(clang::tok::eod)) {
803 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
806 const clang::SourceManager&
SM =
PP.getSourceManager();
807 const char *start =
SM.getCharacterData(
tok.getLocation());
810 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
819 if (end.is(clang::tok::unknown)) {
822 llvm::StringRef
rule_text(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
849 clang::Token &
tok)
override {
854 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
855 if (!
tok.getIdentifierInfo())
return;
856 if (
tok.getIdentifierInfo()->getName() !=
"link")
return;
862 if (
tok.is(clang::tok::eod)) {
863 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
867 if (
tok.isAnyIdentifier()) {
868 if ((
tok.getIdentifierInfo()->getName() ==
"off")) {
870 }
else if ((
tok.getIdentifierInfo()->getName() ==
"C")) {
873 if (
tok.is(clang::tok::eod) ||
tok.isNot(clang::tok::plusplus)) {
874 Error(
"Error ++ expected after '#pragma link C' at ",
tok,
PP);
878 Error(
"Error #pragma link should be followed by off or C",
tok,
PP);
887 if (
tok.is(clang::tok::eod)) {
888 Error(
"Error no arguments after #pragma link C++/off: ",
tok,
PP);
893 if (
linkOn)
Error(
"Error #pragma link C++ should be followed by identifier",
tok,
PP);
894 else Error(
"Error #pragma link off should be followed by identifier",
tok,
PP);
900 std::unique_ptr<LinkdefReader::Options> options;
901 if (
type ==
"options" ||
type ==
"option") {
906 if (
tok.getIdentifierInfo())
type =
tok.getIdentifierInfo()->getName();
909 PP.LexUnexpandedToken(
tok);
910 const clang::SourceManager &
SM =
PP.getSourceManager();
911 const char *start =
SM.getCharacterData(
tok.getLocation());
914 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
918 PP.LexUnexpandedToken(
tok);
921 if (
tok.isNot(clang::tok::semi)) {
922 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
926 if (end.is(clang::tok::unknown)) {
931 llvm::StringRef
identifier(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
955 clang::Token &
tok)
override {
960 if (
Introducer.Kind != clang::PIK_HashPragma)
return;
961 if (!
tok.getIdentifierInfo())
return;
962 if (
tok.getIdentifierInfo()->getName() !=
"create")
return;
968 if (
tok.is(clang::tok::eod)) {
969 Error(
"Warning - lonely pragma statement: ",
tok,
PP);
972 if ((
tok.getIdentifierInfo()->getName() !=
"TClass")) {
973 Error(
"Error: currently only supporting TClass after '#pragma create':",
tok,
PP);
978 const clang::SourceManager &
SM =
PP.getSourceManager();
979 const char *start =
SM.getCharacterData(
tok.getLocation());
980 clang::Token end =
tok;
981 while (
tok.isNot(clang::tok::eod) &&
tok.isNot(clang::tok::semi)) {
986 if (
tok.isNot(clang::tok::semi)) {
987 Error(
"Error: missing ; at end of rule",
tok,
PP,
false);
991 llvm::StringRef
identifier(start,
SM.getCharacterData(end.getLocation()) - start + end.getLength());
1013 for (
size_t i = 0,
n =
parserArgs.size(); i <
n; ++i) {
1018 std::unique_ptr<llvm::MemoryBuffer>
memBuf = llvm::MemoryBuffer::getMemBuffer(code,
"CLING #pragma extraction");
1023 clang::Preprocessor &
PP =
pragmaCI->getPreprocessor();
1039 PP.EnterMainSourceFile();
1043 }
while (
tok.isNot(clang::tok::eof));
1046 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.