Commit 39da9f92 authored by ussrhero's avatar ussrhero

added getTemplateArg method

parent b7dc8d26
......@@ -132,6 +132,9 @@ public:
virtual TypedVarPtr getVar(const DataAccessorPtr &dataSource) = 0;
virtual size_t getTemplateArgsCount() = 0;
virtual std::wstring getTemplateArg(size_t index) = 0;
protected:
static bool isBaseType( const std::wstring &typeName );
......
......@@ -481,6 +481,16 @@ class TestTemplateTwoValues
extern TestTemplateTwoValues<2, 10> g_testTemplateTwoValues;
struct UnusedStruct
{
};
template<typename T>
class ClassNoField
{};
extern ClassNoField<UnusedStruct> g_templateUnusedStruct;
////////////////////////////////////////////////////////////////////////////////
#pragma pack ( pop )
......
......@@ -207,6 +207,93 @@ 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,
......@@ -822,6 +909,96 @@ TypeInfoPtr TypeEval::getResult()
///////////////////////////////////////////////////////////////////////////////
std::list<std::string> TypeEval::getTemplateArgList()
{
using namespace parser;
std::list<clang::Token> tokens;
std::copy_if(m_tokens->cbegin(), m_tokens->cend(), std::back_inserter(tokens), [](auto& token) {
return !token.is(clang::tok::kw_const);
});
TypeMatcher typeMatcher;
auto matcher = all_of(typeMatcher, token_is(m_endToken));
auto matchResult = matcher.match(std::make_pair(tokens.cbegin(), tokens.cend()));
if (!matchResult.isMatched())
throw ExprException(L"error syntax");
if (!typeMatcher.isCustomType())
throw ExprException(L"error syntax");
const auto& customMatcher = typeMatcher.getCustomMatcher();
if (customMatcher.isTemplate())
{
const auto& argList = customMatcher.getTemplateMatcher().getTemplateArgs();
std::list<std::string> argStrList;
for (auto& arg : argList)
{
if (arg.isType())
{
argStrList.push_back(getTypeName(arg.getTypeMatcher()));
}
else if (arg.isExpression())
{
auto value = ExprEval2(m_scope, m_typeInfoProvider, arg.getExpressionMatcher().getMatchResult().getMatchedRange()).getResult();
argStrList.push_back(std::to_string(value.getValue().asLongLong()));
}
else
{
throw ExprException(L"error syntax");
}
}
return argStrList;
}
if (customMatcher.isNestedTemplate())
{
const auto& templateMatcher = customMatcher.getNestedTemplateMatcher();
const auto& argList = templateMatcher.getTemplateArgs1();
std::list<std::string> argStrList;
for (auto& arg : argList)
{
if (arg.isType())
{
argStrList.push_back(getTypeName(arg.getTypeMatcher()));
}
else if (arg.isExpression())
{
auto value = ExprEval2(m_scope, m_typeInfoProvider, arg.getExpressionMatcher().getMatchResult().getMatchedRange()).getResult();
argStrList.push_back(std::to_string(value.getValue().asLongLong()));
}
else
{
throw ExprException(L"error syntax");
}
}
std::string templateName = templateMatcher.getNestedTemplateName();
templateName += '<';
templateName += getTemplateArgs(templateMatcher.getTemplateArgs2());
templateName += '>';
argStrList.push_back(templateName);
return argStrList;
}
throw ExprException(L"error syntax");
}
///////////////////////////////////////////////////////////////////////////////
std::string TypeEval::getTemplateArgs(const parser::ListMatcher<parser::TemplateArgMatcher>& argList)
{
std::string argsStr;
......
......@@ -507,7 +507,7 @@ class TypeEval {
public:
TypeEval(const ScopePtr& scope,
const TypeInfoProviderPtr typeInfoProvider,
const TypeInfoProviderPtr& typeInfoProvider,
std::list<clang::Token>* tokens,
clang::tok::TokenKind endToken = clang::tok::eof
) : m_scope(scope), m_typeInfoProvider(typeInfoProvider), m_tokens(tokens), m_endToken(endToken)
......@@ -515,6 +515,8 @@ public:
TypeInfoPtr getResult();
std::list<std::string> getTemplateArgList();
private:
......@@ -522,12 +524,6 @@ private:
TypeInfoPtr getStandardIntType();
//TypeInfoPtr getCustomType();
//TypeInfoPtr getComplexType(TypeInfoPtr& origType);
//void getTypeModifiers(std::list<TypeModifier*>& typeModifiers, clang::tok::TokenKind endToken);
std::string getTemplateArgs(const parser::ListMatcher<parser::TemplateArgMatcher>& argList);
std::string getTemplateName(const parser::TemplateMatcher& templateMatcher);
......
......@@ -286,6 +286,16 @@ protected:
virtual TypedVarPtr getVar(const DataAccessorPtr &dataSource) {
NOT_IMPLEMENTED();
}
size_t getTemplateArgsCount() override
{
NOT_IMPLEMENTED();
}
std::wstring getTemplateArg(size_t index) override
{
NOT_IMPLEMENTED();
}
};
///////////////////////////////////////////////////////////////////////////////
......
......@@ -3,7 +3,6 @@
#include <sstream>
#include <iomanip>
#include <boost/regex.hpp>
#include "kdlib/exceptions.h"
......@@ -11,6 +10,7 @@
#include "kdlib/module.h"
#include "kdlib/typeinfo.h"
#include "typeinfoimp.h"
#include "typedvarimp.h"
#include "processmon.h"
......@@ -826,6 +826,32 @@ 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();
}
///////////////////////////////////////////////////////////////////////////////
std::wstring TypeInfoImp::getTemplateArg(size_t index)
{
if (!isTemplate())
throw TypeException(getName(), L"type is not a template");
const auto& templateArgs = kdlib::getTempalteArgs(getName());
if (index >= templateArgs.size())
throw IndexException(index);
return *std::next(templateArgs.begin(), index);
}
///////////////////////////////////////////////////////////////////////////////
std::wstring TypeInfoReference::getName()
{
std::wstring name;
......
......@@ -28,6 +28,9 @@ 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>
......@@ -295,16 +298,6 @@ protected:
throw TypeException( getName(), L"type is not virtual inherited" );
}
//bool isMethodMember( const std::wstring &name ) override
//{
// throw TypeException( getName(), L"type is not a struct" );
//}
//bool isMethodMember( size_t index ) override
//{
// throw TypeException( getName(), L"type is not a struct" );
//}
void getVirtualDisplacement( const std::wstring& fieldName, MEMOFFSET_32 &virtualBasePtr, size_t &virtualDispIndex, size_t &virtualDispSize ) override
{
throw TypeException( getName(), L"type is not a struct" );
......@@ -357,6 +350,10 @@ protected:
TypedVarPtr getVar(const DataAccessorPtr &dataSource) override;
size_t getTemplateArgsCount() override;
std::wstring getTemplateArg(size_t index) override;
public:
void setConstant( const NumVariant& constVal )
......
......@@ -221,4 +221,5 @@ std::list<int> g_stdIntList;
TestStructTemplate<int> g_testStructTemplate;
TestClassTemplate<int> g_testClassTemplate;
TestTemplateTwoTypes<int,TestClassTemplate<int>> g_testTemplateTwoTypes;
TestTemplateTwoValues<2,10> g_testTemplateTwoValues;
\ No newline at end of file
TestTemplateTwoValues<2,10> g_testTemplateTwoValues;
ClassNoField<UnusedStruct> g_templateUnusedStruct;
\ No newline at end of file
......@@ -426,6 +426,11 @@ TEST_F(ExprEvalTarget, ClassTemplate)
EXPECT_EQ(sizeof(TestClassTemplate<int>), evalExpr("sizeof(TestClassTemplate<int>)", m_targetModule->getScope()));
}
TEST_F(ExprEvalTarget, ClassTemplateUnusedType)
{
EXPECT_EQ(sizeof(ClassNoField<UnusedStruct>), evalExpr("sizeof(ClassNoField<UnusedStruct>)", m_targetModule->getScope()));
}
TEST_F(ExprEvalTarget, Eval1)
{
EXPECT_EQ(g_testArray[1].m_field1, evalExpr("g_testArray[1].m_field1", m_targetModule->getScope()));
......
......@@ -427,3 +427,18 @@ TEST(TypeEvalTest, TemplateClose)
EXPECT_NO_THROW(evalType("TestStruct<int,TestStruct<int,TestStruct<int,int> >>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<int,TestStruct<int,TestStruct<int,int> >>", typeProvider));
}
TEST(TypeEvalTest, TemplateUnusedType)
{
static const char sourceCode[] = " \
template<typename T1, typename T2> \
struct TestStruct { \
}; \
TestStruct<int,TestStruct<int, TestStruct<int,int>>> testVal; \
";
TypeInfoProviderPtr typeProvider = getTypeInfoProviderFromSource(sourceCode);
EXPECT_NO_THROW(evalType("TestStruct<int,TestStruct<int,int>>", typeProvider));
}
......@@ -621,7 +621,7 @@ TEST_F(TypeInfoTest, PdbProviderEnum)
ASSERT_NO_THROW( typeEnum = typeProvider->getTypeEnumerator(L"struct*") );
for ( count = 0; 0 != typeEnum->Next(); ++count);
EXPECT_EQ(16, count);
EXPECT_EQ(14, count);
}
TEST_F(TypeInfoTest, TemplateStruct)
......@@ -648,3 +648,18 @@ TEST_F(TypeInfoTest, isTemplate)
EXPECT_FALSE(loadType(L"structWithNested")->isTemplate());
}
TEST_F(TypeInfoTest, TemplateArgCount)
{
EXPECT_EQ(1, loadType(L"TemplateStruct<int>")->getTemplateArgsCount());
EXPECT_EQ(2, loadType(L"TestTemplateTwoValues<2,10>")->getTemplateArgsCount());
EXPECT_EQ(2, loadType(L"TestTemplateTwoTypes<int,TestClassTemplate<int> >")->getTemplateArgsCount());
EXPECT_THROW(loadType(L"structWithNested")->getTemplateArgsCount(), TypeException);
}
TEST_F(TypeInfoTest, TemplateArg)
{
EXPECT_EQ(L"int", loadType(L"TemplateStruct<int>")->getTemplateArg(0));
EXPECT_EQ(L"10", loadType(L"TestTemplateTwoValues<2,10>")->getTemplateArg(1));
EXPECT_EQ(L"TestClassTemplate<int>", loadType(L"TestTemplateTwoTypes<int,TestClassTemplate<int> >")->getTemplateArg(1));
EXPECT_THROW(loadType(L"TemplateStruct<int>")->getTemplateArg(1), IndexException);
}
\ No newline at end of file
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