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"
46 std::map<std::string, LinkdefReader::EPragmaNames> LinkdefReader::fgMapPragmaNames;
47 std::map<std::string, LinkdefReader::ECppNames> LinkdefReader::fgMapCppNames;
49 struct LinkdefReader::Options {
50 Options() : fNoStreamer(0), fNoInputOper(0), fUseByteCount(0), fVersionNumber(-1) {}
56 int fRequestStreamerInfo;
64 void LinkdefReader::PopulatePragmaMap()
66 if (!(fgMapPragmaNames.empty()))
return;
68 LinkdefReader::fgMapPragmaNames[
"TClass"] = kClass;
69 LinkdefReader::fgMapPragmaNames[
"class"] = kClass;
70 LinkdefReader::fgMapPragmaNames[
"typedef"] = kTypeDef;
71 LinkdefReader::fgMapPragmaNames[
"namespace"] = kNamespace;
72 LinkdefReader::fgMapPragmaNames[
"function"] = kFunction;
73 LinkdefReader::fgMapPragmaNames[
"global"] = kGlobal;
74 LinkdefReader::fgMapPragmaNames[
"enum"] = kEnum;
75 LinkdefReader::fgMapPragmaNames[
"union"] = kUnion;
76 LinkdefReader::fgMapPragmaNames[
"struct"] = kStruct;
77 LinkdefReader::fgMapPragmaNames[
"all"] = kAll;
78 LinkdefReader::fgMapPragmaNames[
"defined_in"] = kDefinedIn;
79 LinkdefReader::fgMapPragmaNames[
"ioctortype"] = kIOCtorType;
80 LinkdefReader::fgMapPragmaNames[
"nestedclass"] = kNestedclasses;
81 LinkdefReader::fgMapPragmaNames[
"nestedclasses"] = kNestedclasses;
82 LinkdefReader::fgMapPragmaNames[
"nestedclasses;"] = kNestedclasses;
83 LinkdefReader::fgMapPragmaNames[
"operators"] = kOperators;
84 LinkdefReader::fgMapPragmaNames[
"operator"] = kOperators;
86 LinkdefReader::fgMapPragmaNames[
"nestedtypedefs"] = kIgnore;
87 LinkdefReader::fgMapPragmaNames[
"nestedtypedef"] = kIgnore;
90 void LinkdefReader::PopulateCppMap()
92 if (!(fgMapCppNames.empty()))
return;
94 LinkdefReader::fgMapCppNames[
"#pragma"] = kPragma;
95 LinkdefReader::fgMapCppNames[
"#ifdef"] = kIfdef;
96 LinkdefReader::fgMapCppNames[
"#endif"] = kEndif;
97 LinkdefReader::fgMapCppNames[
"#if"] = kIf;
98 LinkdefReader::fgMapCppNames[
"#else"] = kElse;
101 LinkdefReader::LinkdefReader(cling::Interpreter &interp,
102 ROOT::TMetaUtils::RConstructorTypes &IOConstructorTypes):
103 fLine(1), fCount(0), fSelectionRules(nullptr), fIOConstructorTypesPtr(&IOConstructorTypes), fInterp(interp)
113 bool LinkdefReader::AddInclude(
const std::string& include)
115 fIncludes +=
"#include ";
116 fIncludes += include;
127 bool LinkdefReader::AddRule(
const std::string& ruletype,
128 const std::string& identifier,
130 bool request_only_tclass,
131 LinkdefReader::Options *options )
134 EPragmaNames name = kUnknown;
135 ROOT::TMetaUtils::Info(
"LinkdefReader::AddRule",
"Ruletype is %s with the identifier %s\n", ruletype.c_str(), identifier.c_str());
136 auto it = fgMapPragmaNames.find(ruletype);
137 if (it != fgMapPragmaNames.end()) {
143 if (identifier ==
"globals" || identifier ==
"global") {
144 VariableSelectionRule vsr(fCount++, fInterp);
146 vsr.SetAttributeValue(
"pattern",
"*");
147 vsr.SetSelected(BaseSelectionRule::kYes);
148 fSelectionRules->AddVariableSelectionRule(vsr);
150 if (fSelectionRules->GetHasFileNameRule()) {
154 vsr.SetAttributeValue(
"pattern",
"*");
155 vsr.SetSelected(BaseSelectionRule::kNo);
156 fSelectionRules->AddVariableSelectionRule(vsr);
162 EnumSelectionRule esr(fCount++, fInterp);
164 esr.SetSelected(BaseSelectionRule::kYes);
165 esr.SetAttributeValue(
"pattern",
"*");
166 fSelectionRules->AddEnumSelectionRule(esr);
169 EnumSelectionRule esr2(fCount++, fInterp);
170 esr2.SetSelected(BaseSelectionRule::kNo);
171 esr2.SetAttributeValue(
"pattern",
"*::*");
172 fSelectionRules->AddEnumSelectionRule(esr2);
174 if (fSelectionRules->GetHasFileNameRule()) {
175 esr.SetAttributeValue(
"pattern",
"*");
176 esr.SetSelected(BaseSelectionRule::kNo);
177 fSelectionRules->AddEnumSelectionRule(esr);
180 }
else if (identifier ==
"functions" || identifier ==
"function") {
181 FunctionSelectionRule fsr(fCount++, fInterp);
182 fsr.SetAttributeValue(
"pattern",
"*");
184 fsr.SetSelected(BaseSelectionRule::kYes);
185 fSelectionRules->AddFunctionSelectionRule(fsr);
187 if (fSelectionRules->GetHasFileNameRule()) {
188 fsr.SetSelected(BaseSelectionRule::kNo);
189 fSelectionRules->AddFunctionSelectionRule(fsr);
192 }
else if (identifier ==
"classes" || identifier ==
"namespaces" ||
193 identifier ==
"class" || identifier ==
"namespace") {
196 ClassSelectionRule csr3(fCount++, fInterp);
197 csr3.SetSelected(BaseSelectionRule::kNo);
198 csr3.SetAttributeValue(
"pattern",
"__va_*");
199 fSelectionRules->AddClassSelectionRule(csr3);
201 ClassSelectionRule csr(fCount++, fInterp), csr2(fCount++, fInterp);
202 csr.SetAttributeValue(
"pattern",
"*");
203 csr2.SetAttributeValue(
"pattern",
"*::*");
204 csr.SetSelected(BaseSelectionRule::kYes);
205 csr2.SetSelected(BaseSelectionRule::kYes);
207 fSelectionRules->AddClassSelectionRule(csr);
208 fSelectionRules->AddClassSelectionRule(csr2);
210 if (fSelectionRules->GetHasFileNameRule()) {
211 ClassSelectionRule csr(fCount++, fInterp), csr2(fCount++, fInterp);
212 csr.SetAttributeValue(
"pattern",
"*");
213 csr2.SetAttributeValue(
"pattern",
"*::*");
215 csr.SetSelected(BaseSelectionRule::kNo);
216 csr2.SetSelected(BaseSelectionRule::kNo);
217 fSelectionRules->AddClassSelectionRule(csr);
218 fSelectionRules->AddClassSelectionRule(csr2);
221 }
else if (identifier ==
"typedefs" || identifier ==
"typedef") {
224 ROOT::TMetaUtils::Warning(
"Unimplemented pragma statement: %s\n",identifier.c_str());
229 case kNestedclasses: {
234 fSelectionRules->SetHasFileNameRule(
true);
237 std::string localIdentifier(identifier);
238 if (localIdentifier.length() && localIdentifier[0] ==
'"' && localIdentifier[localIdentifier.length() - 1] ==
'"') {
239 localIdentifier = localIdentifier.substr(1, localIdentifier.length() - 2);
242 VariableSelectionRule vsr(fCount++, fInterp);
243 vsr.SetAttributeValue(
"pattern",
"*");
244 vsr.SetAttributeValue(
"file_name", localIdentifier);
245 if (linkOn) vsr.SetSelected(BaseSelectionRule::kYes);
246 else vsr.SetSelected(BaseSelectionRule::kNo);
247 fSelectionRules->AddVariableSelectionRule(vsr);
249 EnumSelectionRule esr(fCount++, fInterp);
250 esr.SetAttributeValue(
"pattern",
"*");
251 esr.SetAttributeValue(
"file_name", localIdentifier);
252 if (linkOn) esr.SetSelected(BaseSelectionRule::kYes);
253 else esr.SetSelected(BaseSelectionRule::kNo);
254 fSelectionRules->AddEnumSelectionRule(esr);
256 FunctionSelectionRule fsr(fCount++, fInterp);
257 fsr.SetAttributeValue(
"pattern",
"*");
258 fsr.SetAttributeValue(
"file_name", localIdentifier);
259 if (linkOn) fsr.SetSelected(BaseSelectionRule::kYes);
260 else fsr.SetSelected(BaseSelectionRule::kNo);
261 fSelectionRules->AddFunctionSelectionRule(fsr);
263 ClassSelectionRule csr(fCount++, fInterp), csr2(fCount++, fInterp);
264 csr.SetAttributeValue(
"pattern",
"*");
265 csr2.SetAttributeValue(
"pattern",
"*::*");
267 csr.SetAttributeValue(
"file_name", localIdentifier);
268 csr2.SetAttributeValue(
"file_name", localIdentifier);
270 csr.SetSelected(BaseSelectionRule::kYes);
271 csr2.SetSelected(BaseSelectionRule::kYes);
273 csr.SetSelected(BaseSelectionRule::kNo);
274 csr2.SetSelected(BaseSelectionRule::kNo);
276 csr.SetRequestStreamerInfo(
true);
277 csr2.SetRequestStreamerInfo(
true);
278 fSelectionRules->AddClassSelectionRule(csr);
279 fSelectionRules->AddClassSelectionRule(csr2);
285 std::string localIdentifier(identifier);
286 bool name_or_proto =
false;
287 if (!ProcessFunctionPrototype(localIdentifier, name_or_proto)) {
290 FunctionSelectionRule fsr(fCount++, fInterp);
291 if (linkOn) fsr.SetSelected(BaseSelectionRule::kYes);
292 else fsr.SetSelected(BaseSelectionRule::kNo);
293 if (localIdentifier.at(localIdentifier.length() - 1) ==
'*') fsr.SetAttributeValue(
"pattern", localIdentifier);
294 else if (name_or_proto) fsr.SetAttributeValue(
"name", localIdentifier);
296 int pos = localIdentifier.find(
"(*)");
297 if (pos > -1) fsr.SetAttributeValue(
"proto_pattern", localIdentifier);
300 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
"\\\n",
"",
true);
303 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
"ULong_t",
"unsigned long");
304 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
"Long_t",
"long");
305 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
"Int_t",
"int");
307 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
", ",
",",
true);
308 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
" ,",
",",
true);
310 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
" (",
"(",
true);
311 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
"( ",
"(",
true);
312 ROOT::TMetaUtils::ReplaceAll(localIdentifier,
" )",
")",
true);
313 fsr.SetAttributeValue(
"proto_name", localIdentifier);
316 fSelectionRules->AddFunctionSelectionRule(fsr);
322 std::string localIdentifier(identifier);
323 if (!ProcessOperators(localIdentifier))
326 FunctionSelectionRule fsr(fCount++, fInterp);
327 if (linkOn) fsr.SetSelected(BaseSelectionRule::kYes);
328 else fsr.SetSelected(BaseSelectionRule::kNo);
329 fsr.SetAttributeValue(
"proto_pattern", localIdentifier);
330 fSelectionRules->AddFunctionSelectionRule(fsr);
334 VariableSelectionRule vsr(fCount++, fInterp);
335 if (linkOn) vsr.SetSelected(BaseSelectionRule::kYes);
336 else vsr.SetSelected(BaseSelectionRule::kNo);
337 if (IsPatternRule(identifier)) vsr.SetAttributeValue(
"pattern", identifier);
338 else vsr.SetAttributeValue(
"name", identifier);
339 fSelectionRules->AddVariableSelectionRule(vsr);
344 EnumSelectionRule esr(fCount++, fInterp);
345 if (linkOn) esr.SetSelected(BaseSelectionRule::kYes);
346 else esr.SetSelected(BaseSelectionRule::kNo);
347 if (IsPatternRule(identifier)) esr.SetAttributeValue(
"pattern", identifier);
348 else esr.SetAttributeValue(
"name", identifier);
349 fSelectionRules->AddEnumSelectionRule(esr);
357 std::string localIdentifier(identifier);
358 ClassSelectionRule csr(fCount++, fInterp);
360 if (request_only_tclass) {
361 csr.SetRequestOnlyTClass(
true);
363 int len = localIdentifier.length();
365 const std::string protStr(
"+protected");
366 const std::string privStr(
"+private");
368 if (localIdentifier.compare(0, protStr.length(), protStr) == 0) {
369 csr.SetRequestProtected(
true);
370 localIdentifier.erase(0, protStr.length() + 1);
371 len = localIdentifier.length();
372 }
else if (localIdentifier.compare(0, privStr.length(), privStr) == 0) {
373 csr.SetRequestPrivate(
true);
374 localIdentifier.erase(0, privStr.length() + 1);
375 len = localIdentifier.length();
382 while (!ending && where < len) {
383 char last = localIdentifier.at(len - where);
388 csr.SetRequestStreamerInfo(
true);
391 csr.SetRequestNoInputOperator(
true);
394 csr.SetRequestNoStreamer(
true);
405 if (options->fNoStreamer) csr.SetRequestNoStreamer(
true);
406 if (options->fNoInputOper) csr.SetRequestNoInputOperator(
true);
407 if (options->fRequestStreamerInfo) csr.SetRequestStreamerInfo(
true);
408 if (options->fVersionNumber >= 0) csr.SetRequestedVersionNumber(options->fVersionNumber);
410 if (csr.RequestStreamerInfo() && csr.RequestNoStreamer()) {
411 std::cerr <<
"Warning: " << localIdentifier <<
" option + mutual exclusive with -, + prevails\n";
412 csr.SetRequestNoStreamer(
false);
415 localIdentifier.erase(len - (where - 2));
417 localIdentifier.erase(len - (where - 1));
422 csr.SetSelected(BaseSelectionRule::kYes);
424 if (localIdentifier ==
"*") {
425 ClassSelectionRule csr2(fCount++, fInterp);
426 csr2.SetSelected(BaseSelectionRule::kYes);
427 csr2.SetAttributeValue(
"pattern",
"*::*");
428 fSelectionRules->AddClassSelectionRule(csr2);
430 ClassSelectionRule csr3(fCount++, fInterp);
431 csr3.SetSelected(BaseSelectionRule::kNo);
432 csr3.SetAttributeValue(
"pattern",
"__va_*");
433 fSelectionRules->AddClassSelectionRule(csr3);
436 csr.SetSelected(BaseSelectionRule::kNo);
437 if (localIdentifier ==
"*") {
438 ClassSelectionRule csr2(fCount++, fInterp);
439 csr2.SetSelected(BaseSelectionRule::kNo);
440 csr2.SetAttributeValue(
"pattern",
"*::*");
441 fSelectionRules->AddClassSelectionRule(csr2);
443 EnumSelectionRule esr(fCount++, fInterp);
444 esr.SetSelected(BaseSelectionRule::kNo);
445 esr.SetAttributeValue(
"pattern",
"*::*");
446 fSelectionRules->AddEnumSelectionRule(esr);
467 if (IsPatternRule(localIdentifier)) {
468 csr.SetAttributeValue(
"pattern", localIdentifier);
470 csr.SetAttributeValue(
"name", localIdentifier);
472 if (name == kTypeDef) {
473 csr.SetAttributeValue(
"fromTypedef",
"true");
476 fSelectionRules->AddClassSelectionRule(csr);
482 fIOConstructorTypesPtr->push_back(ROOT::TMetaUtils::RConstructorType(identifier.c_str(), fInterp));
489 ROOT::TMetaUtils::Warning(
"Unimplemented pragma statement - it has no effect: %s\n", identifier.c_str());
497 bool LinkdefReader::IsPatternRule(
const std::string &rule_token)
499 int pos = rule_token.find(
"*");
500 if (pos > -1)
return true;
508 bool LinkdefReader::LoadIncludes(std::string &extraIncludes)
510 extraIncludes += fIncludes;
511 return cling::Interpreter::kSuccess == fInterp.declare(fIncludes);
514 bool LinkdefReader::ProcessFunctionPrototype(std::string &proto,
bool &name)
516 int pos1, pos1_1, pos2, pos2_1;
518 pos1 = proto.find_first_of(
"(");
519 pos1_1 = proto.find_last_of(
"(");
521 if (pos1 != pos1_1) {
522 std::cout <<
"Error at line " << fLine <<
" - too many ( in function prototype!" << std::endl;
526 pos2 = proto.find_first_of(
")");
527 pos2_1 = proto.find_last_of(
")");
529 if (pos2 != pos2_1) {
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;
547 pos3 = proto.find(
" ", pos3);
549 proto.erase(pos3, 1);
556 std::cout <<
"Error at line " << fLine <<
" - missing ( in function prototype" << std::endl;
569 bool LinkdefReader::ProcessOperators(std::string &pattern)
572 int pos1 = -1, pos2 = -1;
573 int open_br = 0, close_br = 0;
577 pos = pattern.find(
" ", pos + 1);
578 pos1 = pattern.find(
"<", pos1 + 1);
579 pos2 = pattern.find(
">", pos2 + 1);
581 if ((pos < 0) && (pos1 < 0) && (pos2 < 0))
break;
583 if (pos1 > -1) ++open_br;
584 if (pos2 > -1) ++close_br;
586 if (pos < 0)
continue;
592 if (pos > 0) before = pattern.at(pos - 1);
593 if (pos < (
int)(pattern.length() - 1)) after = pattern.at(pos + 1);
617 std::cout <<
"Error at line " << fLine - 1 <<
" - extra space" << std::endl;
620 pattern.erase(pos, 1);
623 if (open_br != close_br) {
624 std::cout <<
"Error at line " << fLine <<
" - number of < doesn't match number of >" << std::endl;
627 pattern =
"operator*(*" + pattern +
"*)";
631 class LinkdefReaderPragmaHandler :
public clang::PragmaHandler {
633 LinkdefReader &fOwner;
634 clang::SourceManager &fSourceManager;
636 LinkdefReaderPragmaHandler(
const char *which, LinkdefReader &owner, clang::SourceManager &sm) :
638 clang::PragmaHandler(which), fOwner(owner), fSourceManager(sm) {
641 void Error(
const char *message,
const clang::Token &tok,
bool source =
true) {
643 std::cerr << message <<
" at ";
644 tok.getLocation().dump(fSourceManager);
647 std::cerr << fSourceManager.getCharacterData(tok.getLocation());
652 bool ProcessOptions(LinkdefReader::Options &options,
653 clang::Preprocessor &PP,
670 if (tok.is(clang::tok::eod) || tok.isNot(clang::tok::equal)) {
671 Error(
"Error: the 'options' keyword must be followed by an '='", tok);
676 while (tok.isNot(clang::tok::eod) && tok.isNot(clang::tok::semi)) {
677 if (!tok.getIdentifierInfo()) {
678 Error(
"Error: Malformed version option.", tok);
679 }
else if (tok.getIdentifierInfo()->getName() ==
"nomap") {
682 }
else if (tok.getIdentifierInfo()->getName() ==
"nostreamer") options.fNoStreamer = 1;
683 else if (tok.getIdentifierInfo()->getName() ==
"noinputoper") options.fNoInputOper = 1;
684 else if (tok.getIdentifierInfo()->getName() ==
"evolution") options.fRequestStreamerInfo = 1;
685 else if (tok.getIdentifierInfo()->getName() ==
"stub") {
688 }
else if (tok.getIdentifierInfo()->getName() ==
"version") {
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 version.", start);
696 clang::Token number = tok;
697 if (tok.isNot(clang::tok::eod)) PP.Lex(tok);
698 if (tok.is(clang::tok::eod) || tok.isNot(clang::tok::r_paren)) {
699 Error(
"Error: missing right parenthesis after version.", start);
702 if (!number.isLiteral()) {
703 std::cerr <<
"Error: Malformed version option, the value is not a non-negative number!";
706 std::string verStr(number.getLiteralData(), number.getLength());
707 bool noDigit =
false;
708 for (std::string::size_type i = 0; i < verStr.size(); ++i)
709 if (!isdigit(verStr[i])) noDigit =
true;
712 std::cerr <<
"Error: Malformed version option! \"" << verStr <<
"\" is not a non-negative number!";
715 options.fVersionNumber = atoi(verStr.c_str());
717 Error(
"Warning: ignoring unknown #pragma link option=", tok);
720 if (tok.is(clang::tok::eod) || tok.isNot(clang::tok::comma)) {
731 class PragmaExtraInclude :
public LinkdefReaderPragmaHandler {
733 PragmaExtraInclude(LinkdefReader &owner, clang::SourceManager &sm) :
735 LinkdefReaderPragmaHandler(
"extra_include", owner, sm) {
738 void HandlePragma(clang::Preprocessor &PP,
739 clang::PragmaIntroducerKind Introducer,
745 if (Introducer != clang::PIK_HashPragma)
return;
746 if (!tok.getIdentifierInfo())
return;
747 if (tok.getIdentifierInfo()->getName() !=
"extra_include")
return;
753 if (tok.is(clang::tok::eod)) {
754 Error(
"Warning - lonely pragma statement: ", tok);
757 const char *start = fSourceManager.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,
false);
768 if (end.is(clang::tok::unknown)) {
769 Error(
"Error: Unknown token!", tok);
771 llvm::StringRef include(start, fSourceManager.getCharacterData(end.getLocation()) - start + end.getLength());
773 if (!fOwner.AddInclude(include)) {
780 class PragmaIoReadInclude :
public LinkdefReaderPragmaHandler {
782 PragmaIoReadInclude(LinkdefReader &owner, clang::SourceManager &sm) :
784 LinkdefReaderPragmaHandler(
"read", owner, sm) {
787 void HandlePragma(clang::Preprocessor &PP,
788 clang::PragmaIntroducerKind Introducer,
794 if (Introducer != 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);
806 const char *start = fSourceManager.getCharacterData(tok.getLocation());
809 while (tok.isNot(clang::tok::eod) && tok.isNot(clang::tok::semi)) {
818 if (end.is(clang::tok::unknown)) {
819 Error(
"Error: unknown token", tok);
821 llvm::StringRef rule_text(start, fSourceManager.getCharacterData(end.getLocation()) - start + end.getLength());
823 std::string error_string;
824 ROOT::ProcessReadPragma(rule_text.str().c_str(), error_string);
825 if (!error_string.empty())
826 std::cerr << error_string;
836 class PragmaLinkCollector :
public LinkdefReaderPragmaHandler {
841 PragmaLinkCollector(LinkdefReader &owner, clang::SourceManager &sm) :
843 LinkdefReaderPragmaHandler(
"link", owner, sm) {
846 void HandlePragma(clang::Preprocessor &PP,
847 clang::PragmaIntroducerKind Introducer,
853 if (Introducer != clang::PIK_HashPragma)
return;
854 if (!tok.getIdentifierInfo())
return;
855 if (tok.getIdentifierInfo()->getName() !=
"link")
return;
861 if (tok.is(clang::tok::eod)) {
862 Error(
"Warning - lonely pragma statement: ", tok);
866 if (tok.isAnyIdentifier()) {
867 if ((tok.getIdentifierInfo()->getName() ==
"off")) {
869 }
else if ((tok.getIdentifierInfo()->getName() ==
"C")) {
872 if (tok.is(clang::tok::eod) || tok.isNot(clang::tok::plusplus)) {
873 Error(
"Error ++ expected after '#pragma link C' at ", tok);
877 Error(
"Error #pragma link should be followed by off or C", tok);
881 Error(
"Error bad #pragma format. ", tok);
886 if (tok.is(clang::tok::eod)) {
887 Error(
"Error no arguments after #pragma link C++/off: ", tok);
890 auto identifier = tok.getIdentifierInfo();
891 if (identifier ==
nullptr) {
892 if (linkOn) Error(
"Error #pragma link C++ should be followed by identifier", tok);
893 else Error(
"Error #pragma link off should be followed by identifier", tok);
897 llvm::StringRef type = identifier->getName();
899 std::unique_ptr<LinkdefReader::Options> options;
900 if (type ==
"options" || type ==
"option") {
901 options.reset(
new LinkdefReader::Options());
902 if (!ProcessOptions(*options, PP, tok)) {
905 if (tok.getIdentifierInfo()) type = tok.getIdentifierInfo()->getName();
908 PP.LexUnexpandedToken(tok);
909 const char *start = fSourceManager.getCharacterData(tok.getLocation());
912 while (tok.isNot(clang::tok::eod) && tok.isNot(clang::tok::semi)) {
916 PP.LexUnexpandedToken(tok);
919 if (tok.isNot(clang::tok::semi)) {
920 Error(
"Error: missing ; at end of rule", tok,
false);
924 if (end.is(clang::tok::unknown)) {
925 if (!fOwner.AddRule(type.data(),
"", linkOn,
false, options.get())) {
926 Error(type.data(), tok,
false);
929 llvm::StringRef identifier(start, fSourceManager.getCharacterData(end.getLocation()) - start + end.getLength());
931 if (!fOwner.AddRule(type, identifier, linkOn,
false, options.get())) {
932 Error(type.data(), tok,
false);
944 class PragmaCreateCollector :
public LinkdefReaderPragmaHandler {
946 PragmaCreateCollector(LinkdefReader &owner, clang::SourceManager &sm) :
948 LinkdefReaderPragmaHandler(
"create", owner, sm) {
951 void HandlePragma(clang::Preprocessor &PP,
952 clang::PragmaIntroducerKind Introducer,
958 if (Introducer != clang::PIK_HashPragma)
return;
959 if (!tok.getIdentifierInfo())
return;
960 if (tok.getIdentifierInfo()->getName() !=
"create")
return;
966 if (tok.is(clang::tok::eod)) {
967 Error(
"Warning - lonely pragma statement: ", tok);
970 if ((tok.getIdentifierInfo()->getName() !=
"TClass")) {
971 Error(
"Error: currently only supporting TClass after '#pragma create':", tok);
976 const char *start = fSourceManager.getCharacterData(tok.getLocation());
977 clang::Token end = tok;
978 while (tok.isNot(clang::tok::eod) && tok.isNot(clang::tok::semi)) {
983 if (tok.isNot(clang::tok::semi)) {
984 Error(
"Error: missing ; at end of rule", tok,
false);
988 llvm::StringRef identifier(start, fSourceManager.getCharacterData(end.getLocation()) - start + end.getLength());
990 if (!fOwner.AddRule(
"class", identifier,
true,
true)) {
1005 bool LinkdefReader::Parse(SelectionRules &sr, llvm::StringRef code,
const std::vector<std::string> &parserArgs,
const char *llvmdir)
1007 fSelectionRules = &sr;
1009 std::vector<const char *> parserArgsC;
1010 for (
size_t i = 0, n = parserArgs.size(); i < n; ++i) {
1011 parserArgsC.push_back(parserArgs[i].c_str());
1015 std::unique_ptr<llvm::MemoryBuffer> memBuf = llvm::MemoryBuffer::getMemBuffer(code,
"CLING #pragma extraction");
1016 clang::CompilerInstance *pragmaCI = cling::CIFactory::createCI(std::move(memBuf), parserArgsC.size(),
1017 &parserArgsC[0], llvmdir,
nullptr ,
1020 clang::Preprocessor &PP = pragmaCI->getPreprocessor();
1021 clang::DiagnosticConsumer &DClient = pragmaCI->getDiagnosticClient();
1022 DClient.BeginSourceFile(pragmaCI->getLangOpts(), &PP);
1024 PragmaLinkCollector pragmaLinkCollector(*
this, pragmaCI->getASTContext().getSourceManager());
1025 PragmaCreateCollector pragmaCreateCollector(*
this, pragmaCI->getASTContext().getSourceManager());
1026 PragmaExtraInclude pragmaExtraInclude(*
this, pragmaCI->getASTContext().getSourceManager());
1027 PragmaIoReadInclude pragmaIoReadInclude(*
this, pragmaCI->getASTContext().getSourceManager());
1029 PP.AddPragmaHandler(&pragmaLinkCollector);
1030 PP.AddPragmaHandler(&pragmaCreateCollector);
1031 PP.AddPragmaHandler(&pragmaExtraInclude);
1032 PP.AddPragmaHandler(&pragmaIoReadInclude);
1035 PP.EnterMainSourceFile();
1039 }
while (tok.isNot(clang::tok::eof));
1041 fSelectionRules = 0;
1042 return 0 == DClient.getNumErrors();