Commit d2f918fd authored by ussrhero's avatar ussrhero
Browse files

reworked getTemplateArg method

parent 92e9d98b
......@@ -2,6 +2,7 @@
#include <string>
#include <list>
#include <map>
#pragma pack( push, 4 )
......@@ -448,6 +449,7 @@ extern TemplateStruct<TemplateStruct<int>[4]> g_template4;
////////////////////////////////////////////////////////////////////////////////
extern std::list<int> g_stdIntList;
extern std::map<int, TemplateStruct<int> > g_stdMap;
template<typename T>
struct TestStructTemplate
......
......@@ -205,93 +205,6 @@ TypeInfoPtr evalType(const std::string& expr, const TypeInfoProviderPtr typeInfo
///////////////////////////////////////////////////////////////////////////////
std::list<std::string> getTempalteArgs(const std::string& expr)
{
auto preprocessorOptions = std::make_shared<clang::PreprocessorOptions>();
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagnosticIDs(new clang::DiagnosticIDs());
auto diagnosticOptions = new clang::DiagnosticOptions();
auto diagnosticConsumer = new clang::IgnoringDiagConsumer();
clang::DiagnosticsEngine diagnosticEngine(diagnosticIDs, diagnosticOptions, diagnosticConsumer);
clang::LangOptions langOptions;
llvm::IntrusiveRefCntPtr<clang::vfs::InMemoryFileSystem> memoryFileSystem(new clang::vfs::InMemoryFileSystem());
memoryFileSystem->addFile("<input>", 0, llvm::MemoryBuffer::getMemBuffer(expr.c_str()));
clang::FileSystemOptions fileSystemOptions;
clang::FileManager fileManager(fileSystemOptions, memoryFileSystem);
clang::SourceManager sourceManager(diagnosticEngine, fileManager);
const clang::FileEntry *pFile = fileManager.getFile("<input>");
clang::FileID fileID = sourceManager.getOrCreateFileID(pFile, clang::SrcMgr::C_User);
sourceManager.setMainFileID(fileID);
clang::MemoryBufferCache memoryBufferCache;
auto headerSearchOptions = std::make_shared<clang::HeaderSearchOptions>();
auto targetOptions = std::make_shared<clang::TargetOptions>();
targetOptions->Triple = llvm::sys::getDefaultTargetTriple();
clang::TargetInfo* targetInfo = clang::TargetInfo::CreateTargetInfo(diagnosticEngine, targetOptions);
clang::HeaderSearch headerSearch(headerSearchOptions, sourceManager, diagnosticEngine, langOptions, targetInfo);
clang::CompilerInstance compilerInstance;
clang::Preprocessor preprocessor(
preprocessorOptions,
diagnosticEngine,
langOptions,
sourceManager,
memoryBufferCache,
headerSearch,
compilerInstance
);
preprocessor.Initialize(*targetInfo);
preprocessor.EnterMainSourceFile();
diagnosticConsumer->BeginSourceFile(langOptions, &preprocessor);
clang::Token token;
std::list<clang::Token> tokens;
do {
preprocessor.Lex(token);
if (diagnosticEngine.hasErrorOccurred())
{
NOT_IMPLEMENTED();
}
tokens.push_back(token);
} while (!token.is(clang::tok::eof));
diagnosticConsumer->EndSourceFile();
TypeEval exprEval(getDefaultScope(), getDefaultTypeInfoProvider(), &tokens);
return exprEval.getTemplateArgList();
}
///////////////////////////////////////////////////////////////////////////////
std::list<std::wstring> getTempalteArgs(const std::wstring& typeName)
{
const std::list<std::string>& argList = getTempalteArgs(wstrToStr(typeName));
std::list<std::wstring> wargLst;
std::for_each(argList.begin(), argList.end(), [&wargLst](const auto& arg) {
wargLst.push_back(strToWStr(arg));
});
return wargLst;
}
///////////////////////////////////////////////////////////////////////////////
ExprEval::ExprEval(const ScopePtr& scope,
const TypeInfoProviderPtr& typeInfoProvider,
std::list<clang::Token>* tokens,
......
#include "stdafx.h"
#include <sstream>
#include <iomanip>
#include <boost/regex.hpp>
#include <regex>
#include "kdlib/exceptions.h"
#include "kdlib/dbgengine.h"
......@@ -20,13 +18,13 @@ namespace {
///////////////////////////////////////////////////////////////////////////////
static const boost::wregex complexSymMatch(L"^([\\*]*)([^\\(\\)\\*\\[\\]]*)([\\(\\)\\*\\[\\]\\d]*)$");
static const std::wregex complexSymMatch(L"^([\\*]*)([^\\(\\)\\*\\[\\]]*)([\\(\\)\\*\\[\\]\\d]*)$");
std::wstring getTypeNameFromComplex( const std::wstring &fullTypeName )
{
boost::wsmatch matchResult;
std::wsmatch matchResult;
if ( !boost::regex_match( fullTypeName, matchResult, complexSymMatch ) )
if ( !std::regex_match( fullTypeName, matchResult, complexSymMatch ) )
return L"";
return std::wstring( matchResult[2].first, matchResult[2].second );
......@@ -34,9 +32,9 @@ std::wstring getTypeNameFromComplex( const std::wstring &fullTypeName )
std::wstring getTypeSuffixFromComplex( const std::wstring &fullTypeName )
{
boost::wsmatch matchResult;
std::wsmatch matchResult;
if ( !boost::regex_match( fullTypeName, matchResult, complexSymMatch ) )
if ( !std::regex_match( fullTypeName, matchResult, complexSymMatch ) )
return L"";
return std::wstring( matchResult[3].first, matchResult[3].second );
......@@ -45,13 +43,13 @@ std::wstring getTypeSuffixFromComplex( const std::wstring &fullTypeName )
///////////////////////////////////////////////////////////////////////////////
static const boost::wregex bracketMatch(L"^([^\\(]*)\\((.*)\\)([^\\)]*)$");
static const std::wregex bracketMatch(L"^([^\\(]*)\\((.*)\\)([^\\)]*)$");
void getBracketExpression( std::wstring &suffix, std::wstring &bracketExpression )
{
boost::wsmatch matchResult;
std::wsmatch matchResult;
if ( boost::regex_match( suffix, matchResult, bracketMatch ) )
if ( std::regex_match( suffix, matchResult, bracketMatch ) )
{
bracketExpression = std::wstring( matchResult[2].first, matchResult[2].second );
......@@ -69,13 +67,13 @@ void getBracketExpression( std::wstring &suffix, std::wstring &bracketExpression
///////////////////////////////////////////////////////////////////////////////
static const boost::wregex ptrMatch(L"^\\*(.*)$");
static const std::wregex ptrMatch(L"^\\*(.*)$");
bool getPtrExpression( std::wstring &suffix )
{
boost::wsmatch matchResult;
std::wsmatch matchResult;
if ( boost::regex_match( suffix, matchResult, ptrMatch ) )
if ( std::regex_match( suffix, matchResult, ptrMatch ) )
{
suffix = std::wstring(matchResult[1].first, matchResult[1].second );
......@@ -87,13 +85,13 @@ bool getPtrExpression( std::wstring &suffix )
///////////////////////////////////////////////////////////////////////////////
static const boost::wregex arrayMatch(L"^(.*)\\[(\\d+)\\]$");
static const std::wregex arrayMatch(L"^(.*)\\[(\\d+)\\]$");
bool getArrayExpression( std::wstring &suffix, size_t &arraySize )
{
boost::wsmatch matchResult;
std::wsmatch matchResult;
if ( boost::regex_match( suffix, matchResult, arrayMatch ) )
if ( std::regex_match( suffix, matchResult, arrayMatch ) )
{
std::wstringstream sstr;
sstr << std::wstring(matchResult[2].first, matchResult[2].second );
......@@ -484,26 +482,26 @@ std::wstring getMethodPrototype( kdlib::TypeInfoPtr& methodType )
///////////////////////////////////////////////////////////////////////////////
static const boost::wregex prototypeMatch1(L"(\\w+)\\s*\\(\\s*(\\w+)\\s*\\)\\s*\\((.*)\\)");
static const boost::wregex prototypeMatch2(L"(\\w+)\\s*\\(\\s*(\\w+)\\s+(\\w+)::\\s*\\)\\s*\\((.*)\\)");
static const std::wregex prototypeMatch1(L"(\\w+)\\s*\\(\\s*(\\w+)\\s*\\)\\s*\\((.*)\\)");
static const std::wregex prototypeMatch2(L"(\\w+)\\s*\\(\\s*(\\w+)\\s+(\\w+)::\\s*\\)\\s*\\((.*)\\)");
bool isPrototypeMatch(TypeInfoPtr& methodType, const std::wstring& methodPrototype)
{
boost::wsmatch matchResult;
std::wsmatch matchResult;
std::wstring returnType;
std::wstring callConversion;
std::wstring className;
std::wstring args;
if ( boost::regex_match( methodPrototype, matchResult, prototypeMatch1 ) )
if ( std::regex_match( methodPrototype, matchResult, prototypeMatch1 ) )
{
returnType = std::wstring(matchResult[1].first, matchResult[1].second);
callConversion = std::wstring(matchResult[2].first, matchResult[2].second);
args = std::wstring(matchResult[3].first, matchResult[3].second);
}
else
if ( boost::regex_match( methodPrototype, matchResult, prototypeMatch2 ) )
if ( std::regex_match( methodPrototype, matchResult, prototypeMatch2 ) )
{
returnType = std::wstring(matchResult[1].first, matchResult[1].second);
callConversion = std::wstring(matchResult[2].first, matchResult[2].second);
......@@ -526,7 +524,7 @@ bool isPrototypeMatch(TypeInfoPtr& methodType, const std::wstring& methodProtot
if ( !className.empty() && className != methodType->getClassParent()->getName() )
return false;
args.erase( std::remove_if(args.begin(), args.end(), std::isspace), args.end());
args.erase(std::remove_if(args.begin(), args.end(), [](const auto& c) { return std::isspace(c, std::locale()); }), args.end());
std::wstringstream sargs;
......@@ -552,7 +550,7 @@ bool isPrototypeMatch(TypeInfoPtr& methodType, const std::wstring& methodProtot
///////////////////////////////////////////////////////////////////////////////
static const boost::wregex baseMatch(L"^(Char)|(WChar)|(Int1B)|(UInt1B)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)|(Double)|(Void)|(Hresult)|(NoType)$" );
static const std::wregex baseMatch(L"^(Char)|(WChar)|(Int1B)|(UInt1B)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)|(Double)|(Void)|(Hresult)|(NoType)$" );
bool TypeInfo::isBaseType( const std::wstring &typeName )
{
......@@ -565,8 +563,8 @@ bool TypeInfo::isBaseType( const std::wstring &typeName )
return false;
}
boost::wsmatch baseMatchResult;
return boost::regex_match( name, baseMatchResult, baseMatch );
std::wsmatch baseMatchResult;
return std::regex_match( name, baseMatchResult, baseMatch );
}
///////////////////////////////////////////////////////////////////////////////
......@@ -583,9 +581,9 @@ TypeInfoPtr TypeInfo::getBaseTypeInfo( const std::wstring &typeName, size_t ptrS
if ( isComplexType( typeName ) )
return getComplexTypeInfo( typeName, SymbolPtr() );
boost::wsmatch baseMatchResult;
std::wsmatch baseMatchResult;
if ( boost::regex_match( typeName, baseMatchResult, baseMatch ) )
if ( std::regex_match( typeName, baseMatchResult, baseMatch ) )
{
if ( baseMatchResult[1].matched )
return TypeInfoPtr( new TypeInfoBaseWrapper<char>(L"Char", ptrSize) );
......@@ -839,27 +837,105 @@ bool TypeInfoImp::isTemplate()
size_t TypeInfoImp::getTemplateArgsCount()
{
if ( !isTemplate() )
throw TypeException(getName(), L"type is not a template");
const auto& templateArgs = kdlib::getTempalteArgs(getName());
return templateArgs.size();
return getTempalteArgs().size();
}
///////////////////////////////////////////////////////////////////////////////
std::wstring TypeInfoImp::getTemplateArg(size_t index)
{
if (!isTemplate())
throw TypeException(getName(), L"type is not a template");
const auto& templateArgs = kdlib::getTempalteArgs(getName());
const auto& templateArgs = getTempalteArgs();
if (index >= templateArgs.size())
throw IndexException(index);
return *std::next(templateArgs.begin(), index);
}
///////////////////////////////////////////////////////////////////////////////
namespace {
std::pair<std::wstring::const_iterator, std::wstring::const_iterator> removeSpaces(const std::wstring::const_iterator& it1, const std::wstring::const_iterator& it2)
{
auto result = std::make_pair(it1, it2);
while (result.first != result.second && *result.first == L' ')
{
result.first = std::next(result.first);
}
while (result.first != result.second)
{
auto prev = std::prev(result.second);
if (*prev != L' ')
break;
result.second = prev;
}
return result;
}
static const std::wregex templateMatch(L"^([\\w:]*)<(.*)>$");
}
std::list<std::wstring> TypeInfoImp::getTempalteArgs()
{
std::wsmatch matchResult;
const auto& typeName = getName();
if ( !std::regex_match(typeName, matchResult, templateMatch))
throw TypeException(getName(), L"type is not a template");
std::list<std::wstring> argList;
auto current = matchResult[2].first;
auto argStart = current;
auto end = matchResult[2].second;
int nestedLevel = 0;
while (true)
{
if (nestedLevel == 0)
{
if (current == end)
{
auto arg = removeSpaces(argStart, current);
argList.push_back(std::wstring(arg.first, arg.second));
break;
}
else
if (*current == ',')
{
argList.push_back(std::wstring(argStart, current));
current = std::next(current);
argStart = current;
}
else
if (*current == '<')
{
nestedLevel++;
current = std::next(current);
}
else
{
current = std::next(current);
}
}
else
{
if (current == end)
break;
else if (*current == '<')
nestedLevel++;
else if (*current == '>')
nestedLevel--;
current = std::next(current);
}
}
return argList;
}
///////////////////////////////////////////////////////////////////////////////
......
......@@ -28,9 +28,6 @@ std::wstring printStructType(TypeInfoPtr& structType);
std::wstring printPointerType(TypeInfoPtr& ptrType);
std::wstring printEnumType(TypeInfoPtr& enumType);
std::list<std::wstring> getTempalteArgs(const std::wstring& typeName);
std::list<std::string> getTempalteArgs(const std::string& typeName);
///////////////////////////////////////////////////////////////////////////////
class TypeInfoImp : public TypeInfo, public boost::enable_shared_from_this<TypeInfoImp>
......@@ -399,6 +396,8 @@ protected:
return m_constantValue;
}
std::list<std::wstring> getTempalteArgs();
};
......
......@@ -222,4 +222,6 @@ TestStructTemplate<int> g_testStructTemplate;
TestClassTemplate<int> g_testClassTemplate;
TestTemplateTwoTypes<int,TestClassTemplate<int>> g_testTemplateTwoTypes;
TestTemplateTwoValues<2,10> g_testTemplateTwoValues;
ClassNoField<UnusedStruct> g_templateUnusedStruct;
\ No newline at end of file
ClassNoField<UnusedStruct> g_templateUnusedStruct;
std::map<int, TemplateStruct<int> > g_stdMap;
\ No newline at end of file
......@@ -5,24 +5,27 @@
using namespace kdlib;
class NetTest : public NetProcessFixture
typedef ::testing::Types<NetProcessFixture, NetDumpFixture> NetTargetTypes;
template <typename T>
class NetTest : public T
{
};
TYPED_TEST_CASE(NetTest, NetTargetTypes);
TEST_F(NetTest, ProcessIsManaged)
TYPED_TEST(NetTest, ProcessIsManaged)
{
EXPECT_TRUE(TargetProcess::getCurrent()->isManaged());
}
TEST_F(NetTest, NetModuleIsManaged)
TYPED_TEST(NetTest, NetModuleIsManaged)
{
EXPECT_TRUE(m_targetModule->isManaged());
EXPECT_FALSE( loadModule(L"ntdll")->isManaged());
}
TEST_F(NetTest, NetHeap)
TYPED_TEST(NetTest, NetHeap)
{
kdlib::TargetHeapPtr targetHeap;
ASSERT_NO_THROW(targetHeap = TargetProcess::getCurrent()->getManagedHeap());
......@@ -38,20 +41,18 @@ TEST_F(NetTest, NetHeap)
EXPECT_TRUE( heapEnum->next(address, typeName, size) );
}
//TEST_F(NetTest, NetModuleEnumTypes)
//{
// EXPECT_EQ(
// TypeNameList( { L"managedapp.Class1",
// L"managedapp.Class1.Nested",
// L"managedapp.Program" } ),
// m_targetModule->enumTypes() );
//
// EXPECT_EQ(
// TypeNameList( { L"managedapp.Class1",
// L"managedapp.Class1.Nested" } ),
// m_targetModule->enumTypes(L"*Class1*") );
//
//}
TYPED_TEST(NetTest, NetModuleEnumTypes)
{
auto types = m_targetModule->enumTypes();
EXPECT_NE(types.end(), std::find(types.begin(), types.end(), L"managedapp.Class1.Nested"));
EXPECT_EQ(types.end(), std::find(types.begin(), types.end(), L"managedapp.Notexist"));
}
TYPED_TEST(NetTest, DISABLED_GetType)
{
EXPECT_EQ(L"managedapp.Class1", m_targetModule->getTypeByName(L"managedapp.Class1")->getName());
}
//
//TEST_F(NetTest, ClassField)
//{
......
......@@ -719,7 +719,7 @@ TEST_F(TypedVarTest, GetSource)
ASSERT_NO_THROW(funcptr = loadTypedVar(L"classChild::childMethod"));
funcptr->getSourceLine(funcptr->getAddress(), fileName, lineNo);
EXPECT_EQ(286, lineNo);
EXPECT_EQ(287, lineNo);
}
TEST_F(TypedVarTest, StructNestedEnum)
......
......@@ -669,6 +669,17 @@ TEST_F(TypeInfoTest, TemplateArgStdPair)
EXPECT_EQ(3, loadType(L"g_stdIntList")->getElement(L"_Mypair")->getTemplateArgsCount());
}
TEST_F(TypeInfoTest, TemplateArgStdMap)
{
kdlib::TypeInfoPtr stdMap = loadType(L"g_stdMap");
EXPECT_EQ(4, stdMap->getTemplateArgsCount());
EXPECT_EQ(3, stdMap->getElement(L"_Mypair")->getTemplateArgsCount());
EXPECT_EQ(3, stdMap->getElement(L"_Mypair")->getElement(L"_Myval2")->getTemplateArgsCount());
EXPECT_EQ(L"std::allocator<std::_Tree_node<std::pair<int const ,TemplateStruct<int> >,void *> >", stdMap->getElement(L"_Mypair")->getElement(L"_Myval2")->getTemplateArg(0));
EXPECT_EQ(L"1", stdMap->getElement(L"_Mypair")->getElement(L"_Myval2")->getTemplateArg(2));
}
TEST_F(TypeInfoTest, DISABLED_IncomleteStruct)
{
TypeInfoPtr typeInfo;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment