6
#include "clang/Basic/MemoryBufferCache.h"
7
#include "clang/Basic/TargetOptions.h"
8
#include "clang/Basic/TargetInfo.h"
10
#include "clang/Lex/Preprocessor.h"
11
#include "clang/Lex/PreprocessorOptions.h"
12
#include "clang/Lex/HeaderSearch.h"
13
#include "clang/Lex/HeaderSearchOptions.h"
15
#include "clang/Frontend/CompilerInstance.h"
16
#include "clang/Frontend/TextDiagnosticPrinter.h"
18
#include "kdlib/typedvar.h"
19
#include "kdlib/exceptions.h"
22
#include "kdlib/strconvert.h"
23
#include "exprparser.h"
27
TypedValue getNumericConst(const clang::Token& token);
29
TypedValue getCharConst(const clang::Token& token);
31
std::string getIdentifier(const clang::Token& token);
33
kdlib::TypeInfoPtr getStandardIntType(const std::string& name);
35
bool isBinOperation(const clang::Token& token);
39
TypedValue evalExpr(const std::wstring& expr, const ScopePtr& scope, const TypeInfoProviderPtr& typeInfoProvider)
41
return evalExpr(wstrToStr(expr), scope, typeInfoProvider);
46
TypedValue evalExpr(const std::string& expr, const ScopePtr& scope, const TypeInfoProviderPtr& typeInfoProvider)
48
auto preprocessorOptions = std::make_shared<clang::PreprocessorOptions>();
50
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagnosticIDs(new clang::DiagnosticIDs());
52
auto diagnosticOptions = new clang::DiagnosticOptions();
56
auto diagnosticConsumer = new clang::IgnoringDiagConsumer();
58
clang::DiagnosticsEngine diagnosticEngine(diagnosticIDs, diagnosticOptions, diagnosticConsumer);
60
clang::LangOptions langOptions;
62
llvm::IntrusiveRefCntPtr<clang::vfs::InMemoryFileSystem> memoryFileSystem(new clang::vfs::InMemoryFileSystem());
64
memoryFileSystem->addFile("<input>", 0, llvm::MemoryBuffer::getMemBuffer(expr));
66
clang::FileSystemOptions fileSystemOptions;
67
clang::FileManager fileManager(fileSystemOptions, memoryFileSystem);
68
clang::SourceManager sourceManager(diagnosticEngine, fileManager);
70
const clang::FileEntry *pFile = fileManager.getFile("<input>");
71
clang::FileID fileID = sourceManager.getOrCreateFileID(pFile, clang::SrcMgr::C_User);
72
sourceManager.setMainFileID(fileID);
74
clang::MemoryBufferCache memoryBufferCache;
76
auto headerSearchOptions = std::make_shared<clang::HeaderSearchOptions>();
77
auto targetOptions = std::make_shared<clang::TargetOptions>();
78
targetOptions->Triple = llvm::sys::getDefaultTargetTriple();
79
clang::TargetInfo* targetInfo = clang::TargetInfo::CreateTargetInfo(diagnosticEngine, targetOptions);
80
clang::HeaderSearch headerSearch(headerSearchOptions, sourceManager, diagnosticEngine, langOptions, targetInfo);
82
clang::CompilerInstance compilerInstance;
84
clang::Preprocessor preprocessor(
93
preprocessor.Initialize(*targetInfo);
95
preprocessor.EnterMainSourceFile();
96
diagnosticConsumer->BeginSourceFile(langOptions, &preprocessor);
100
std::list<clang::Token> tokens;
104
preprocessor.Lex(token);
106
if (diagnosticEngine.hasErrorOccurred())
111
tokens.push_back(token);
113
} while (!token.is(clang::tok::eof));
115
diagnosticConsumer->EndSourceFile();
117
ExprEval exprEval(scope, typeInfoProvider, &tokens);
119
return exprEval.getResult();
124
TypeInfoPtr evalType(const std::wstring& expr, const TypeInfoProviderPtr typeInfoProvider)
126
return evalType(wstrToStr(expr), typeInfoProvider);
131
TypeInfoPtr evalType(const std::string& expr, const TypeInfoProviderPtr typeInfoProvider)
133
auto preprocessorOptions = std::make_shared<clang::PreprocessorOptions>();
135
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagnosticIDs(new clang::DiagnosticIDs());
137
auto diagnosticOptions = new clang::DiagnosticOptions();
141
auto diagnosticConsumer = new clang::IgnoringDiagConsumer();
143
clang::DiagnosticsEngine diagnosticEngine(diagnosticIDs, diagnosticOptions, diagnosticConsumer);
145
clang::LangOptions langOptions;
147
llvm::IntrusiveRefCntPtr<clang::vfs::InMemoryFileSystem> memoryFileSystem(new clang::vfs::InMemoryFileSystem());
148
memoryFileSystem->addFile("<input>", 0, llvm::MemoryBuffer::getMemBuffer(expr.c_str()));
150
clang::FileSystemOptions fileSystemOptions;
151
clang::FileManager fileManager(fileSystemOptions, memoryFileSystem);
152
clang::SourceManager sourceManager(diagnosticEngine, fileManager);
154
const clang::FileEntry *pFile = fileManager.getFile("<input>");
155
clang::FileID fileID = sourceManager.getOrCreateFileID(pFile, clang::SrcMgr::C_User);
156
sourceManager.setMainFileID(fileID);
158
clang::MemoryBufferCache memoryBufferCache;
160
auto headerSearchOptions = std::make_shared<clang::HeaderSearchOptions>();
161
auto targetOptions = std::make_shared<clang::TargetOptions>();
162
targetOptions->Triple = llvm::sys::getDefaultTargetTriple();
163
clang::TargetInfo* targetInfo = clang::TargetInfo::CreateTargetInfo(diagnosticEngine, targetOptions);
164
clang::HeaderSearch headerSearch(headerSearchOptions, sourceManager, diagnosticEngine, langOptions, targetInfo);
166
clang::CompilerInstance compilerInstance;
168
clang::Preprocessor preprocessor(
177
preprocessor.Initialize(*targetInfo);
179
preprocessor.EnterMainSourceFile();
180
diagnosticConsumer->BeginSourceFile(langOptions, &preprocessor);
184
std::list<clang::Token> tokens;
188
preprocessor.Lex(token);
190
if (diagnosticEngine.hasErrorOccurred())
195
tokens.push_back(token);
197
} while (!token.is(clang::tok::eof));
199
diagnosticConsumer->EndSourceFile();
201
TypeEval exprEval(ScopePtr(new ScopeList()), typeInfoProvider, &tokens);
203
return exprEval.getResult();
208
ExprEval::ExprEval(const ScopePtr& scope,
209
const TypeInfoProviderPtr& typeInfoProvider,
210
std::list<clang::Token>* tokens,
211
clang::tok::TokenKind endToken)
214
m_typeInfoProvider = typeInfoProvider;
216
m_endToken = endToken;
221
TypedValue ExprEval::getResult()
223
std::list<TypedValue> operands;
224
std::list<BinOperation*> operations;
226
std::unique_ptr<UnaryOperation> ternaryOp;
230
UnaryOperation* preOp = 0;
231
std::list<UnaryOperation*> preOperations;
232
while (0 != (preOp = getPreUnaryOperation()))
234
preOperations.push_front(preOp);
237
auto val = getOperand();
239
UnaryOperation* postOp = 0;
240
std::list<UnaryOperation*> postOperations;
241
while (0 != (postOp = getPostUnaryOperation()))
243
postOperations.push_back(postOp);
246
for (auto op : postOperations)
248
val = op->getResult(val);
252
for (auto op : preOperations)
254
val = op->getResult(val);
258
operands.push_back(val);
260
auto token = m_tokens->front();
262
if (token.is(clang::tok::question))
264
ternaryOp.reset(getTernaryOperation());
268
if (token.is(m_endToken))
270
m_tokens->pop_front();
274
operations.push_back(getOperation());
277
while (!operations.empty())
279
auto op = std::max_element(operations.begin(), operations.end(),
280
[](const BinOperation* op1, const BinOperation* op2)
282
return op1->getPriority() > op2->getPriority();
285
auto op1 = operands.begin();
286
std::advance(op1, std::distance(operations.begin(), op));
288
auto op2 = operands.begin();
289
std::advance(op2, std::distance(operations.begin(), op) + 1);
291
auto res = (*op)->getResult(*op1, *op2);
294
operations.erase(op);
301
return ternaryOp->getResult(operands.front());
303
return operands.front();
308
TypedValue ExprEval::getOperand()
310
if (m_tokens->empty())
311
throw ExprException(L"error syntax");
313
auto token = m_tokens->front();
315
if (token.is(clang::tok::identifier))
317
return getIdentifierValue();
320
m_tokens->pop_front();
322
if (token.is(clang::tok::numeric_constant))
324
return getNumericConst(token);
327
if (token.isOneOf(clang::tok::char_constant, clang::tok::wide_char_constant))
329
return getCharConst(token);
332
if (token.is(clang::tok::l_paren))
334
return ExprEval(m_scope, m_typeInfoProvider, m_tokens, clang::tok::r_paren).getResult();
337
if (token.is(clang::tok::kw_sizeof))
342
throw ExprException(L"error syntax");
347
BinOperation* ExprEval::getOperation()
349
if (m_tokens->empty())
350
throw ExprException(L"error syntax");
352
auto token = m_tokens->front();
354
if (!isBinOperation(token))
355
throw ExprException(L"error syntax");
357
m_tokens->pop_front();
359
if (token.is(clang::tok::plus))
360
return new AddExprOperation();
362
if (token.is(clang::tok::star))
363
return new MultExprOperation();
365
if (token.is(clang::tok::minus))
366
return new SubExprOperation();
368
if (token.is(clang::tok::slash))
369
return new DivExprOperation();
371
if (token.is(clang::tok::percent))
372
return new ModExprOperation();
374
if (token.is(clang::tok::equalequal))
375
return new EqualOperation();
377
if (token.is(clang::tok::exclaimequal))
378
return new NotEqualOperation();
380
if (token.is(clang::tok::less))
381
return new LessOperation();
383
if (token.is(clang::tok::lessequal))
384
return new LessEqualOperation();
386
if (token.is(clang::tok::greater))
387
return new GreaterOperation();
389
if (token.is(clang::tok::greaterequal))
390
return new GreaterEqualOperation();
392
if (token.is(clang::tok::lessless))
393
return new LeftShiftOperation();
395
if (token.is(clang::tok::greatergreater))
396
return new RightShiftOperation();
398
if (token.is(clang::tok::amp))
399
return new BitwiseAndOperation();
401
if (token.is(clang::tok::pipe))
402
return new BitwiseOrOperation();
404
if (token.is(clang::tok::caret))
405
return new BitwiseXorOperation();
407
if (token.is(clang::tok::pipepipe))
408
return new BoolOrOperation();
410
if (token.is(clang::tok::ampamp))
411
return new BoolAndOperation();
413
throw ExprException(L"error syntax");
418
UnaryOperation* ExprEval::getPreUnaryOperation()
420
if (m_tokens->empty())
421
throw ExprException(L"error syntax");
423
auto token = m_tokens->front();
425
if (token.isOneOf(clang::tok::numeric_constant,
426
clang::tok::identifier,
427
clang::tok::char_constant,
428
clang::tok::wide_char_constant) )
431
if (token.is(clang::tok::l_paren))
432
return getTypeCastOperation();
434
if (token.is(clang::tok::kw_sizeof))
435
return getSizeofOperation();
437
if (isBaseTypeKeyWord(token))
440
m_tokens->pop_front();
442
if (token.is(clang::tok::minus))
443
return new UnMinusOperation();
445
if (token.is(clang::tok::plus))
446
return new UnPlusOperation();
448
if (token.is(clang::tok::star))
449
return new DerefOperation();
451
if (token.is(clang::tok::tilde))
452
return new BitwiseNotOperation();
454
if (token.is(clang::tok::exclaim))
455
return new BooleanNotOperation();
457
if (token.is(clang::tok::amp))
458
return new RefOperation();
460
throw ExprException(L"error syntax");
466
UnaryOperation* ExprEval::getPostUnaryOperation()
468
assert(!m_tokens->empty());
470
auto token = m_tokens->front();
472
if (token.isOneOf(m_endToken, clang::tok::question))
475
if (isBinOperation(token))
478
if (token.is(clang::tok::l_square))
479
return getArrayOperation();
481
if (token.is(clang::tok::period))
482
return getAttributeOperation();
484
if (token.is(clang::tok::arrow))
485
return getAttributeOperationPtr();
487
throw ExprException(L"error syntax");
492
UnaryOperation* ExprEval::getArrayOperation()
494
auto token = m_tokens->front();
496
if (!token.is(clang::tok::l_square))
497
throw ExprException(L"error syntax");
499
m_tokens->pop_front();
501
auto indexVal = ExprEval(m_scope, m_typeInfoProvider, m_tokens, clang::tok::r_square).getResult();
503
return new ArrayValueOperation(indexVal);
508
UnaryOperation* ExprEval::getAttributeOperation()
510
auto token = m_tokens->front();
512
if (!token.is(clang::tok::period))
513
throw ExprException(L"error syntax");
515
m_tokens->pop_front();
517
if (m_tokens->front().is(m_endToken))
518
throw ExprException(L"error syntax");
520
token = m_tokens->front();
522
if (!token.is(clang::tok::identifier))
523
throw ExprException(L"error syntax");
525
std::string name(token.getIdentifierInfo()->getNameStart(), token.getLength());
527
m_tokens->pop_front();
529
return new AttributeOperation(name);
534
UnaryOperation* ExprEval::getAttributeOperationPtr()
536
auto token = m_tokens->front();
538
if (!token.is(clang::tok::arrow))
539
throw ExprException(L"error syntax");
541
m_tokens->pop_front();
543
if (m_tokens->front().is(m_endToken))
544
throw ExprException(L"error syntax");
546
token = m_tokens->front();
548
if (!token.is(clang::tok::identifier))
549
throw ExprException(L"error syntax");
551
std::string name(token.getIdentifierInfo()->getNameStart(), token.getLength());
553
m_tokens->pop_front();
555
return new AttributeOperation(name);
560
UnaryOperation* ExprEval::getSizeofOperation()
562
auto token = m_tokens->front();
564
if ( !token.is( clang::tok::kw_sizeof ) )
565
throw ExprException(L"error syntax");
567
if ( std::next(m_tokens->begin())->is( m_endToken) )
568
throw ExprException(L"error syntax");
570
if (std::next(m_tokens->begin())->is(clang::tok::l_paren))
573
m_tokens->pop_front();
575
return new SizeofOperation();
580
UnaryOperation* ExprEval::getTypeCastOperation()
582
auto token = m_tokens->front();
584
if (!token.is(clang::tok::l_paren))
585
throw ExprException(L"error syntax");
589
std::list<clang::Token> exprCopy(m_tokens->begin(), m_tokens->end());
591
exprCopy.pop_front();
593
TypeInfoPtr typeCast = TypeEval(m_scope, m_typeInfoProvider, &exprCopy, clang::tok::r_paren).getResult();
595
*m_tokens = exprCopy;
597
return new TypeCastOperation(typeCast);
599
catch (DbgException&)
609
UnaryOperation* ExprEval::getTernaryOperation()
611
auto token = m_tokens->front();
613
if (!token.is(clang::tok::question))
614
throw ExprException(L"error syntax");
616
m_tokens->pop_front();
618
TypedValue val1 = ExprEval(m_scope, m_typeInfoProvider, m_tokens, clang::tok::colon).getResult();
620
TypedValue val2 = ExprEval(m_scope, m_typeInfoProvider, m_tokens, m_endToken).getResult();
622
return new TrenaryOperation(val1, val2);
627
size_t ExprEval::getSizeof()
629
auto token = m_tokens->front();
631
if (!token.is(clang::tok::l_paren))
632
throw ExprException(L"error syntax");
634
m_tokens->pop_front();
636
if (m_tokens->front().is(m_endToken))
637
throw ExprException(L"error syntax");
640
std::list<clang::Token> exprCopy(m_tokens->begin(), m_tokens->end());
641
TypedValue exprResult = ExprEval(m_scope, m_typeInfoProvider, &exprCopy, clang::tok::r_paren).getResult();
642
*m_tokens = exprCopy;
643
return exprResult.getType()->getSize();
645
catch (DbgException&)
648
TypeInfoPtr typeInfo = TypeEval(m_scope, m_typeInfoProvider, m_tokens, clang::tok::r_paren).getResult();
650
throw ExprException(L"error syntax");
652
return typeInfo->getSize();
657
TypedValue ExprEval::getIdentifierValue()
659
std::string fullName;
663
if (m_tokens->front().is(m_endToken))
666
auto token = m_tokens->front();
668
if (token.is(clang::tok::identifier))
670
m_tokens->pop_front();
671
std::string name(token.getIdentifierInfo()->getNameStart(), token.getLength());
674
else if ( token.is(clang::tok::colon) )
676
m_tokens->pop_front();
687
if (fullName == "true")
688
return TypedValue(true);
690
if (fullName == "false")
691
return TypedValue(false);
693
if (fullName == "nullptr")
694
return TypedValue(nullptr);
697
std::wstring wname = strToWStr(fullName);
698
if (m_scope->find(wname, result))
702
return evalType(fullName, m_typeInfoProvider)->getValue();
704
catch (DbgException&)
708
throw ExprException(L"error syntax");
714
TypeInfoPtr applyComplexModifierRecursive(const parser::ComplexMatcher& matcher, TypeInfoPtr& typeInfo_)
716
TypeInfoPtr typeInfo = typeInfo_;
718
if (matcher.isReference())
720
if (typeInfo->isVoid() )
721
throw ExprException(L"error syntax");
724
if (matcher.isPointer())
726
for ( auto p : matcher.getPointerMatcher().getPointerMatchers() )
727
typeInfo = typeInfo->ptrTo();
730
if (matcher.isArray())
732
auto indices = matcher.getArrayMatcher().getArrayIndices();
733
for (auto it = indices.rbegin(); it != indices.rend(); ++it)
735
if (it->isIndexComplete())
737
auto i = getNumericConst(*it->getIndexMatcher().getMatchResult().begin()).getValue().asLongLong();
738
typeInfo = typeInfo->arrayOf(i);
742
typeInfo = typeInfo->arrayOf();
747
if (matcher.isNestedMatcher())
749
typeInfo = applyComplexModifierRecursive(matcher.getNestedMatcher().getInnerMatcher(), typeInfo);
757
std::string getTypeModifierRecursive(const parser::ComplexMatcher& matcher)
759
std::stringstream sstr;
761
if (matcher.isPointer())
763
bool needSpace = false;
764
for (auto p : matcher.getPointerMatcher().getPointerMatchers())
780
if (matcher.isReference())
782
if (matcher.getRefMatcher().isLvalue())
788
if (matcher.isNestedMatcher())
790
sstr << '(' << getTypeModifierRecursive(matcher.getNestedMatcher().getInnerMatcher()) << ')';
793
if (matcher.isArray())
795
auto indices = matcher.getArrayMatcher().getArrayIndices();
796
for (auto it = indices.rbegin(); it != indices.rend(); ++it)
798
if (it->isIndexComplete())
800
auto i = getNumericConst(*it->getIndexMatcher().getMatchResult().begin()).getValue().asLongLong();
801
sstr << '[' << std::dec << i << ']';
815
TypeInfoPtr TypeEval::getResult()
817
using namespace parser;
819
QualifiedTypeMatcher typeMatcher;
821
auto matcher = all_of(typeMatcher, token_is(m_endToken));
822
auto matchResult = matcher.match(std::make_pair(m_tokens->cbegin(), m_tokens->cend()));
824
if (!matchResult.isMatched())
825
throw ExprException(L"error syntax");
827
TypeInfoPtr typeInfo;
829
if (typeMatcher.isBasedType())
831
typeInfo = typeMatcher.getBaseTypeMatcher().getBaseType();
833
else if (typeMatcher.isStandardIntType())
835
typeInfo = getStandardIntType(typeMatcher.getStandardIntMatcher());
837
else if (typeMatcher.isCustomType())
839
typeInfo = getCustomType(typeMatcher.getCustomMatcher());
847
throw ExprException(L"error syntax");
849
if (typeMatcher.isComplexType() )
851
typeInfo = applyComplexModifierRecursive(typeMatcher.getComplexMather(), typeInfo);
854
m_tokens->erase(matchResult.begin(), matchResult.end());
861
std::list<std::string> TypeEval::getTemplateArgList()
863
using namespace parser;
865
TypeMatcher typeMatcher;
867
auto matcher = all_of(typeMatcher, token_is(m_endToken));
868
auto matchResult = matcher.match(std::make_pair(m_tokens->cbegin(), m_tokens->cend()));
870
if (!matchResult.isMatched())
871
throw ExprException(L"error syntax");
873
if (!typeMatcher.isCustomType())
874
throw ExprException(L"error syntax");
876
const auto& customMatcher = typeMatcher.getCustomMatcher();
878
if (customMatcher.isTemplate())
880
const auto& argListMatcher = customMatcher.getTemplateMatcher().getTemplateArgs();
882
return getTemplateArgList(argListMatcher);
885
if (customMatcher.isNestedTemplate())
887
const auto& templateMatcher = customMatcher.getNestedTemplateMatcher();
888
const auto& argListMatcher = templateMatcher.getTemplateArgs1();
890
std::list<std::string> argStrList = getTemplateArgList(argListMatcher);
892
std::string templateName = templateMatcher.getNestedTemplateName();
896
const auto& nestedArgList = getTemplateArgList(templateMatcher.getTemplateArgs2());
899
for (const auto& arg : nestedArgList)
901
if (!argsStr.empty())
906
templateName += argsStr;
910
argStrList.push_back(templateName);
915
throw ExprException(L"error syntax");
920
std::list<std::string> TypeEval::getTemplateArgList(const parser::ListMatcher<parser::TemplateArgMatcher>& argList)
922
std::list<std::string> argStrList;
924
for (auto& arg : argList)
928
argStrList.push_back(getTypeName(arg.getTypeMatcher()));
930
else if (arg.isExpression())
932
auto value = ExprEval2(m_scope, m_typeInfoProvider, arg.getExpressionMatcher().getMatchResult().getMatchedRange()).getResult();
933
argStrList.push_back(std::to_string(value.getValue().asLongLong()));
937
throw ExprException(L"error syntax");
946
std::string TypeEval::getTemplateArgs(const parser::ListMatcher<parser::TemplateArgMatcher>& argListMatcher)
948
const auto& argList = getTemplateArgList(argListMatcher);
951
for (const auto& arg : argList)
953
if (!argsStr.empty())
963
std::string TypeEval::getTemplateName(const parser::TemplateMatcher& templateMatcher)
965
std::string templateName = getTemplateArgs(templateMatcher.getTemplateArgs());
967
templateName.insert(templateName.begin(), '<');
968
if (templateName.back() == '>')
969
templateName.insert(templateName.end(), ' ');
970
templateName.insert(templateName.end(), '>');
977
std::string TypeEval::getNestedTemplateName(const parser::DoubleTemplateMatcher& templateMatcher)
979
std::string templateName = getTemplateArgs(templateMatcher.getTemplateArgs1());
981
if (!templateName.empty())
984
auto nestedTemplate = templateMatcher.getNestedTemplateName();
986
nestedTemplate += '<';
988
nestedTemplate += getTemplateArgs(templateMatcher.getTemplateArgs2());
990
if (nestedTemplate.back() == '>')
991
nestedTemplate += " >";
993
nestedTemplate += '>';
995
auto fullNestedTypeName = m_typeInfoProvider->makeTypeName(strToWStr(nestedTemplate), L"", templateMatcher.isNetstedTemplateConst());
997
templateName += wstrToStr(fullNestedTypeName);
999
templateName += " >";
1001
templateName.insert(templateName.begin(), '<');
1016
return templateName;
1021
TypeInfoPtr TypeEval::getCustomType(const parser::CustomTypeMatcher& customMatcher)
1023
TypeInfoPtr typeInfo;
1025
std::string typeName = customMatcher.getTypeNameMatcher().getName();
1027
if (customMatcher.isTemplate() || customMatcher.isNestedTemplate() )
1029
for (auto namespaceMatcher : customMatcher.getTypeNameMatcher().getNamespaces())
1032
typeName += namespaceMatcher.getName();
1035
if (customMatcher.isTemplate())
1037
typeName += getTemplateName(customMatcher.getTemplateMatcher());
1039
else if (customMatcher.isNestedTemplate())
1041
typeName += getNestedTemplateName(customMatcher.getNestedTemplateMatcher());
1044
typeInfo = m_typeInfoProvider->getTypeByName(strToWStr(typeName));
1046
for (auto fieldMatcher : customMatcher.getFields())
1048
auto fieldName = fieldMatcher.getName();
1049
typeInfo = typeInfo->getElement(strToWStr(fieldName));
1056
typeInfo = m_typeInfoProvider->getTypeByName(strToWStr(typeName));
1058
catch (SymbolException&)
1061
for (auto namespaceMatcher : customMatcher.getTypeNameMatcher().getNamespaces())
1066
auto fieldName = namespaceMatcher.getName();
1067
typeInfo = typeInfo->getElement(strToWStr(fieldName));
1072
typeName += namespaceMatcher.getName();
1076
typeInfo = m_typeInfoProvider->getTypeByName(strToWStr(typeName));
1078
catch (SymbolException&)
1089
std::string TypeEval::getTypeName(const parser::QualifiedTypeMatcher& typeMatcher)
1091
std::string typeName;
1092
std::string typeQualifier;
1094
if (typeMatcher.isBasedType())
1096
typeName = typeMatcher.getBaseTypeMatcher().getTypeName();
1099
if (typeMatcher.isStandardIntType())
1101
auto& token = typeMatcher.getStandardIntMatcher().getMatchResult().begin();
1102
typeName = std::string(token->getIdentifierInfo()->getNameStart(), token->getLength());
1105
if (typeMatcher.isCustomType())
1107
typeName = getCustomTypeName(typeMatcher.getCustomMatcher());
1111
throw ExprException(L"error syntax");
1114
if (typeMatcher.isComplexType())
1116
typeQualifier = getTypeModifierRecursive(typeMatcher.getComplexMather());
1119
auto fullTypeName = m_typeInfoProvider->makeTypeName(strToWStr(typeName), strToWStr(typeQualifier), typeMatcher.isConst());
1121
return wstrToStr(fullTypeName);
1126
std::string TypeEval::getCustomTypeName(const parser::CustomTypeMatcher& customMatcher)
1128
std::string typeName = customMatcher.getTypeNameMatcher().getName();
1130
if (customMatcher.isTemplate() || customMatcher.isNestedTemplate())
1132
for (auto namespaceMatcher : customMatcher.getTypeNameMatcher().getNamespaces())
1135
typeName += namespaceMatcher.getName();
1138
if (customMatcher.isTemplate())
1140
typeName += getTemplateName(customMatcher.getTemplateMatcher());
1142
else if (customMatcher.isNestedTemplate())
1144
typeName += getNestedTemplateName(customMatcher.getNestedTemplateMatcher());
1147
for (auto fieldMatcher : customMatcher.getFields())
1150
typeName += fieldMatcher.getName();
1155
for (auto namespaceMatcher : customMatcher.getTypeNameMatcher().getNamespaces())
1158
typeName += namespaceMatcher.getName();
1167
TypeInfoPtr TypeEval::getStandardIntType(const parser::StandardIntMatcher& stdIntMatcher)
1169
auto& token = stdIntMatcher.getMatchResult().begin();
1170
std::string name(token->getIdentifierInfo()->getNameStart(), token->getLength());
1171
return kdlib::getStandardIntType(name);
1176
static const std::regex integralLiteralRe("(0x[0-9a-f]+|0[0-7]+|[1-9][0-9]*|0)((l)|(u)|(ul|lu)|(ll)|(ull|llu))?", std::regex::icase);
1177
static const std::regex floatLiteralRe("\\d*((\\.(\\d+(e[+\\-]?\\d+)?)?)|(e[+\\-]?\\d+))((f)|(l))?", std::regex::icase);
1179
TypedValue getNumericConst(const clang::Token& token)
1181
if (token.is(clang::tok::identifier))
1183
std::string strVal = token.getIdentifierInfo()->getName();
1185
if (strVal == "false")
1186
return TypedValue(false);
1187
if (strVal == "true")
1188
return TypedValue(true);
1190
throw ExprException(L"error syntax");
1193
if (token.isOneOf(clang::tok::char_constant, clang::tok::wide_char_constant))
1194
return getCharConst(token);
1196
std::string strVal(token.getLiteralData(), token.getLength());
1200
if (std::regex_match(strVal, smatch, integralLiteralRe))
1202
bool isSuffix = smatch[2].matched;
1203
bool isLong = smatch[3].matched;
1204
bool isUnsigned = smatch[4].matched;
1205
bool isULong = smatch[5].matched;
1206
bool isLongLong = smatch[6].matched;
1207
bool isULongLong = smatch[7].matched;
1209
if (!isSuffix || isLong )
1212
return std::stol(strVal, nullptr, 0);
1214
catch (std::out_of_range&)
1218
return std::stoul(strVal, nullptr, 0);
1220
catch (std::out_of_range&)
1224
return std::stoll(strVal, nullptr, 0);
1226
catch (std::out_of_range&)
1230
return std::stoull(strVal, nullptr, 0);
1232
catch (std::out_of_range&)
1235
throw ExprException(L"error syntax");
1239
if (isUnsigned || isULong )
1243
return std::stoul(strVal, nullptr, 0);
1245
catch (std::out_of_range&)
1249
return std::stoull(strVal, nullptr, 0);
1251
catch (std::out_of_range&)
1254
throw ExprException(L"error syntax");
1256
else if (isLongLong)
1259
return std::stoll(strVal, nullptr, 0);
1261
catch (std::out_of_range&)
1265
throw ExprException(L"error syntax");
1267
else if (isULongLong)
1270
return std::stoull(strVal, nullptr, 0);
1272
catch (std::out_of_range&)
1276
throw ExprException(L"error syntax");
1282
else if (std::regex_match(strVal, smatch, floatLiteralRe))
1284
bool isLong = !smatch[7].matched;
1288
return std::stod(strVal);
1290
return std::stof(strVal);
1292
catch (std::exception&)
1296
throw ExprException(L"error syntax");
1299
throw ExprException(L"error syntax");
1304
static const std::regex charLiteralRe("(L'(.).*')|('(.{1,4})')", std::regex::icase);
1306
TypedValue getCharConst(const clang::Token& token)
1308
std::string strVal(token.getLiteralData(), token.getLength());
1314
if (std::regex_match(strVal, smatch, charLiteralRe))
1316
if (smatch[1].matched)
1318
return strToWStr(smatch[2].str())[0];
1321
auto bytesSeq = smatch[4].str();
1322
if (bytesSeq.size() == 1)
1326
for (auto byte : bytesSeq)
1327
intRes = ( intRes << 8 ) | byte;
1332
throw ExprException(L"error syntax");
1337
std::string tokenToStr(const clang::Token& token)
1339
switch (token.getKind())
1341
case clang::tok::identifier:
1342
return std::string(token.getIdentifierInfo()->getNameStart(), token.getLength());
1343
case clang::tok::numeric_constant:
1344
return std::string(token.getLiteralData(), token.getLength());
1345
case clang::tok::less:
1347
case clang::tok::greater:
1349
case clang::tok::kw_bool:
1351
case clang::tok::kw_char:
1353
case clang::tok::kw_char16_t:
1355
case clang::tok::kw_char32_t:
1357
case clang::tok::kw_double:
1359
case clang::tok::kw_float:
1361
case clang::tok::kw_int:
1363
case clang::tok::kw_long:
1365
case clang::tok::kw_short:
1367
case clang::tok::kw_signed:
1369
case clang::tok::kw_unsigned:
1371
case clang::tok::kw_void:
1373
case clang::tok::kw_wchar_t:
1375
case clang::tok::kw_struct:
1377
case clang::tok::minus:
1379
case clang::tok::plus:
1381
case clang::tok::colon:
1383
case clang::tok::star:
1385
case clang::tok::l_square:
1387
case clang::tok::r_square:
1389
case clang::tok::l_paren:
1391
case clang::tok::r_paren:
1393
case clang::tok::amp:
1395
case clang::tok::ampamp:
1397
case clang::tok::comma:
1406
bool isBaseTypeKeyWord(const clang::Token& token)
1409
clang::tok::kw_bool,
1410
clang::tok::kw_char,
1411
clang::tok::kw_char16_t,
1412
clang::tok::kw_char32_t,
1413
clang::tok::kw_double,
1414
clang::tok::kw_float,
1416
clang::tok::kw_long,
1417
clang::tok::kw_short,
1418
clang::tok::kw_signed,
1419
clang::tok::kw_unsigned,
1420
clang::tok::kw_void,
1421
clang::tok::kw_wchar_t
1424
return isInt64KeyWord(token);
1429
static const std::map< std::string, std::function<kdlib::TypeInfoPtr(void)> > standardIntTypes = {
1430
{ "wchar_t", []() { return kdlib::loadType(L"Int2B"); } },
1431
{ "int8_t", []() { return kdlib::loadType(L"Int1B"); } },
1432
{ "uint8_t", []() { return kdlib::loadType(L"UInt1B"); } },
1433
{ "int16_t", []() { return kdlib::loadType(L"Int2B"); } },
1434
{ "uint16_t",[]() { return kdlib::loadType(L"UInt2B"); } },
1435
{ "int32_t", []() { return kdlib::loadType(L"Int4B"); } },
1436
{ "uint32_t", []() { return kdlib::loadType(L"UInt4B"); } },
1437
{ "int64_t", []() { return kdlib::loadType(L"Int8B"); } },
1438
{ "uint64_t", []() { return kdlib::loadType(L"UInt8B"); } },
1439
{ "size_t", []() { return kdlib::ptrSize() == 4 ? kdlib::loadType(L"UInt4B") : kdlib::loadType(L"UInt8B"); } },
1440
{ "intptr_t", []() { return kdlib::ptrSize() == 4 ? kdlib::loadType(L"Int4B") : kdlib::loadType(L"Int8B"); } },
1441
{ "uintptr_t", []() { return kdlib::ptrSize() == 4 ? kdlib::loadType(L"UInt4B") : kdlib::loadType(L"UInt8B"); } },
1442
{ "bool", []() { return kdlib::loadType(L"Bool"); } },
1443
{ "void", []() { return kdlib::loadType(L"Void"); } }
1446
bool isStandardIntType(const clang::Token& token)
1448
if (token.is(clang::tok::identifier))
1450
std::string name(token.getIdentifierInfo()->getNameStart(), token.getLength());
1452
return standardIntTypes.find(name) != standardIntTypes.end();
1458
bool isTrueFalse(const clang::Token& token)
1460
if (token.is(clang::tok::identifier))
1462
std::string name(token.getIdentifierInfo()->getNameStart(), token.getLength());
1464
return name == "true" || name == "false";
1470
kdlib::TypeInfoPtr getStandardIntType(const std::string& name)
1472
return standardIntTypes.at(name)();
1477
bool isBinOperation(const clang::Token& token)
1479
return token.isOneOf(
1484
clang::tok::percent,
1485
clang::tok::equalequal,
1486
clang::tok::exclaimequal,
1488
clang::tok::lessequal,
1489
clang::tok::greater,
1490
clang::tok::greaterequal,
1491
clang::tok::lessless,
1492
clang::tok::greatergreater,
1496
clang::tok::pipepipe,
1503
bool isOperationToken(const clang::Token& token)
1505
return isBinOperation(token) ||
1507
clang::tok::exclaim,
1508
clang::tok::plusplus,
1509
clang::tok::minusminus,
1511
clang::tok::l_paren,
1519
bool isInt64KeyWord(const clang::Token& token)
1521
if (token.is(clang::tok::identifier))
1523
std::string name(token.getIdentifierInfo()->getNameStart(), token.getLength());
1524
return name == "__int64";
1533
std::string getIdentifier(const clang::Token& token)
1535
return std::string(token.getIdentifierInfo()->getNameStart(), token.getLength());
1541
TypedValue ExprEval2::getResult()
1543
using namespace parser;
1545
ConstExpressionMatcher exprMatcher;
1547
auto matchResult = exprMatcher.match(m_tokenRange);
1549
if (!matchResult.isMatched() || matchResult.end() != m_tokenRange.second)
1550
throw ExprException(L"error syntax");
1552
return getResultForMatcher(exprMatcher);
1557
TypedValue ExprEval2::getResultForMatcher(const parser::ConstExpressionMatcher& matcher)
1559
std::list< std::unique_ptr<BinOperation>> operations;
1561
std::list<TypedValue> operands;
1564
matcher.getOperationMatchers().begin(),
1565
matcher.getOperationMatchers().end(),
1566
std::back_inserter(operations),
1567
[](auto& operationMatcher) {
1568
if (operationMatcher.isAdd())
1569
return std::unique_ptr<BinOperation>(new AddExprOperation());
1570
if (operationMatcher.isMinus())
1571
return std::unique_ptr<BinOperation>(new SubExprOperation());
1572
if (operationMatcher.isStar())
1573
return std::unique_ptr<BinOperation>(new MultExprOperation());
1574
if (operationMatcher.isSlash())
1575
return std::unique_ptr<BinOperation>(new DivExprOperation());
1576
if (operationMatcher.isPercent())
1577
return std::unique_ptr<BinOperation>(new ModExprOperation());
1578
if (operationMatcher.isGreaterGreater())
1579
return std::unique_ptr<BinOperation>(new RightShiftOperation());
1580
if (operationMatcher.isLessLess())
1581
return std::unique_ptr<BinOperation>(new LeftShiftOperation());
1582
if (operationMatcher.isAmp())
1583
return std::unique_ptr<BinOperation>(new BitwiseAndOperation());
1584
if (operationMatcher.isPipe())
1585
return std::unique_ptr<BinOperation>(new BitwiseOrOperation());
1586
if (operationMatcher.isCaret())
1587
return std::unique_ptr<BinOperation>(new BitwiseXorOperation());
1588
if (operationMatcher.isEqualequal())
1589
return std::unique_ptr<BinOperation>(new EqualOperation());
1590
if (operationMatcher.isExclaimequal())
1591
return std::unique_ptr<BinOperation>(new NotEqualOperation());
1592
if (operationMatcher.isLess())
1593
return std::unique_ptr<BinOperation>(new LessOperation());
1594
if (operationMatcher.isLessEqual())
1595
return std::unique_ptr<BinOperation>(new LessEqualOperation());
1596
if (operationMatcher.isGreater())
1597
return std::unique_ptr<BinOperation>(new GreaterOperation());
1598
if (operationMatcher.isGreaterEqual())
1599
return std::unique_ptr<BinOperation>(new GreaterEqualOperation());
1600
if (operationMatcher.isPipePipe())
1601
return std::unique_ptr<BinOperation>(new BoolOrOperation());
1602
if (operationMatcher.isAmpAmp())
1603
return std::unique_ptr<BinOperation>(new BoolAndOperation());
1604
throw ExprException(L"error syntax");
1608
matcher.getOperandMatchers().begin(),
1609
matcher.getOperandMatchers().end(),
1610
std::back_inserter(operands),
1611
[](auto& operandMatcher) -> TypedValue
1613
if (operandMatcher.isNumericMatcher())
1615
auto val = getNumericConst(*operandMatcher.getNumericMatcher().getMatchResult().begin());
1618
operandMatcher.getUnaryOperations().begin(),
1619
operandMatcher.getUnaryOperations().end(),
1620
[&val](auto& unaryOperationMatcher)
1622
if (unaryOperationMatcher.isPlus())
1623
val = UnPlusOperation().getResult(val);
1624
else if (unaryOperationMatcher.isMinus())
1625
val = UnMinusOperation().getResult(val);
1626
else if (unaryOperationMatcher.isExclaim())
1627
val = BooleanNotOperation().getResult(val);
1628
else if (unaryOperationMatcher.isTilde())
1629
val = BitwiseNotOperation().getResult(val);
1631
throw ExprException(L"error syntax");
1637
if (operandMatcher.isNestedExpression())
1639
return getResultForMatcher(operandMatcher.getNestedExpressionMatcher().getExprMatcher());
1641
throw ExprException(L"error syntax");
1644
while (!operations.empty())
1646
auto op = std::max_element(operations.begin(), operations.end(),
1647
[](const auto& op1, const auto& op2)
1649
return op1->getPriority() > op2->getPriority();
1652
auto op1 = operands.begin();
1653
std::advance(op1, std::distance(operations.begin(), op));
1655
auto op2 = operands.begin();
1656
std::advance(op2, std::distance(operations.begin(), op) + 1);
1662
res = (*op)->getResult(*op1, *op2);
1664
catch (DbgException&)
1666
throw ExprException(L"error syntax");
1669
operations.erase(op);
1672
operands.erase(op2);
1677
return operands.front();
1682
TypedValue TypeCastOperation::getResult(const TypedValue& val)
1684
if (m_type->isBase())
1686
return castToBase(val);
1688
else if (m_type->isPointer())
1690
return castToPtr(val);
1692
else if (m_type->isArray())
1694
throw ExprException(L"error syntax");
1696
else if (m_type->isUserDefined())
1698
throw ExprException(L"error syntax");
1706
TypedValue TypeCastOperation::castToBase(const TypedValue& val)
1708
NumVariant srcValue;
1709
if (val.getType()->isBase())
1710
srcValue = val.getValue();
1711
else if (val.getType()->isPointer())
1712
srcValue = val.getValue();
1713
else if (val.getType()->isArray())
1714
srcValue = val.getAddress();
1716
throw ExprException(L"error syntax");
1718
if (m_type->getName() == L"Char")
1719
return srcValue.asChar();
1721
if (m_type->getName() == L"WChar")
1722
return srcValue.asShort();
1724
if (m_type->getName() == L"Long")
1725
return srcValue.asLong();
1727
if (m_type->getName() == L"ULong")
1728
return srcValue.asULong();
1730
if (m_type->getName() == L"Int1B")
1731
return srcValue.asChar();
1733
if (m_type->getName() == L"UInt1B")
1734
return srcValue.asUChar();
1736
if (m_type->getName() == L"Int2B")
1737
return srcValue.asShort();
1739
if (m_type->getName() == L"UInt2B")
1740
return srcValue.asUShort();
1742
if (m_type->getName() == L"Int4B")
1743
return srcValue.asLong();
1745
if (m_type->getName() == L"UInt4B")
1746
return srcValue.asULong();
1748
if (m_type->getName() == L"Int8B")
1749
return srcValue.asLongLong();
1751
if (m_type->getName() == L"UInt8B")
1752
return srcValue.asULongLong();
1754
if (m_type->getName() == L"Float")
1755
return srcValue.asFloat();
1757
if (m_type->getName() == L"Double")
1758
return srcValue.asDouble();
1760
if (m_type->getName() == L"Bool")
1761
return srcValue.asBool();
1768
TypedValue TypeCastOperation::castToPtr(const TypedValue& val)
1770
NumVariant srcValue;
1771
if (val.getType()->isBase())
1773
return TypedValue(val.getValue().asULongLong()).castTo(m_type);
1776
if (val.getType()->isPointer())
1778
return val.castTo(m_type);
1781
if (val.getType()->isArray())
1783
return TypedValue(val.getAddress()).castTo(m_type);
1791
TypedValue AddExprOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1793
if (val1.getType()->isBase() && val2.getType()->isBase())
1796
if (val1.getType()->isPointer() || val1.getType()->isArray())
1798
if (val2.getType()->isBase())
1799
return TypedValue(val1 + val1.getType()->deref()->getSize() * val2).castTo(val1.getType()->deref()->ptrTo());
1800
throw ExprException(L"error syntax");
1803
if (val2.getType()->isPointer() || val2.getType()->isArray())
1805
if (val1.getType()->isBase())
1806
return TypedValue(val2 + val2.getType()->deref()->getSize() * val1).castTo(val2.getType()->deref()->ptrTo());
1807
throw ExprException(L"error syntax");
1810
throw ExprException(L"error syntax");
1815
TypedValue SubExprOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1817
if (val1.getType()->isBase() && val2.getType()->isBase())
1820
if (val1.getType()->isPointer() || val1.getType()->isArray())
1822
if (val2.getType()->isBase())
1823
return TypedValue(val1 - val1.getType()->deref()->getSize() * val2).castTo(val1.getType()->deref()->ptrTo());
1825
if (val2.getType()->isPointer() || val2.getType()->isArray())
1826
return (val1 - val2) / (val1.getType()->deref()->getSize());
1828
throw ExprException(L"error syntax");
1831
throw ExprException(L"error syntax");
1837
TypedValue MultExprOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1839
if (val1.getType()->isBase() && val2.getType()->isBase())
1842
throw ExprException(L"error syntax");
1847
TypedValue DivExprOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1850
throw DbgException("expression division error");
1852
if (val1.getType()->isBase() && val2.getType()->isBase())
1855
throw ExprException(L"error syntax");
1860
TypedValue ModExprOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1862
if (val1.getType()->isBase() && val2.getType()->isBase())
1865
throw ExprException(L"error syntax");
1870
TypedValue LeftShiftOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1872
if (val1.getType()->isBase() && val2.getType()->isBase())
1873
return val1 << val2;
1875
throw ExprException(L"error syntax");
1881
TypedValue RightShiftOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1883
if (val1.getType()->isBase() && val2.getType()->isBase())
1884
return val1 >> val2;
1886
throw ExprException(L"error syntax");
1891
TypedValue BitwiseOrOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1893
if (val1.getType()->isBase() && val2.getType()->isBase())
1896
throw ExprException(L"error syntax");
1901
TypedValue BitwiseAndOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1903
if (val1.getType()->isBase() && val2.getType()->isBase())
1906
throw ExprException(L"error syntax");
1911
TypedValue BitwiseXorOperation::getResult(const TypedValue& val1, const TypedValue& val2)
1913
if (val1.getType()->isBase() && val2.getType()->isBase())
1916
throw ExprException(L"error syntax");
1921
TypedValue UnMinusOperation::getResult(const TypedValue& val)
1923
if (val.getType()->isBase())
1926
throw ExprException(L"error syntax");
1931
TypedValue BitwiseNotOperation::getResult(const TypedValue& val)
1933
if (val.getType()->isBase())
1936
throw ExprException(L"error syntax");
1941
TypedValue BooleanNotOperation::getResult(const TypedValue& val)
1943
if (val.getType()->isBase())
1944
return !val.getValue();
1946
throw ExprException(L"error syntax");