...
 
Commits (2)
......@@ -55,6 +55,7 @@ public:
virtual TypeInfoPtr ptrTo( size_t ptrSize = 0 ) = 0;
virtual TypeInfoPtr deref() = 0;
virtual TypeInfoPtr arrayOf( size_t size ) = 0;
virtual TypeInfoPtr arrayOf() = 0; // make incomplete array
virtual bool isArray() = 0;
virtual bool isPointer() = 0;
......@@ -94,6 +95,8 @@ public:
virtual bool isVirtual() = 0;
virtual bool isIncomplete() = 0;
virtual TypeInfoPtr getMethod( const std::wstring &name, const std::wstring& prototype = L"") = 0;
virtual TypeInfoPtr getMethod( const std::wstring &name, TypeInfoPtr prototype) = 0;
virtual TypeInfoPtr getMethod( size_t index ) = 0;
......
......@@ -89,6 +89,9 @@ TypeInfoPtr getTypeForClangType( ClangASTSessionPtr& astSession, const clang::Q
if ( qualType->isArrayType() )
{
const ArrayType* arrayType = qualType->getAsArrayTypeUnsafe();
if (llvm::isa<clang::IncompleteArrayType>(arrayType))
return TypeInfoPtr( new TypeInfoIncompleteClangArray(astSession, arrayType));
return TypeInfoPtr( new TypeInfoClangArray(astSession, arrayType ) );
}
......
......@@ -122,69 +122,76 @@ public:
protected:
virtual bool isUserDefined() {
bool isUserDefined() override {
return true;
}
virtual std::wstring getName() {
std::wstring getName() override {
return m_name;
}
virtual std::wstring str();
std::wstring str() override;
size_t getSize() override {
throw TypeException(L"not complete declaration");
}
virtual TypeInfoPtr getElement( const std::wstring &name ) {
TypeInfoPtr getElement( const std::wstring &name ) override {
throw TypeException(L"not complete declaration");
}
virtual TypeInfoPtr getElement( size_t index ) {
TypeInfoPtr getElement( size_t index ) override {
throw TypeException(L"not complete declaration");
}
virtual MEMOFFSET_REL getElementOffset( const std::wstring &name ) {
MEMOFFSET_REL getElementOffset( const std::wstring &name ) override {
throw TypeException(L"not complete declaration");
}
virtual MEMOFFSET_REL getElementOffset( size_t index ) {
MEMOFFSET_REL getElementOffset( size_t index ) override {
throw TypeException(L"not complete declaration");
}
virtual std::wstring getElementName( size_t index ) {
std::wstring getElementName( size_t index ) override {
throw TypeException(L"not complete declaration");
}
virtual size_t getElementIndex( const std::wstring &name ) {
size_t getElementIndex( const std::wstring &name ) override {
throw TypeException(L"not complete declaration");
}
virtual size_t getElementCount() {
size_t getElementCount() override {
throw TypeException(L"not complete declaration");
}
virtual MEMOFFSET_64 getElementVa( const std::wstring &name ) {
MEMOFFSET_64 getElementVa( const std::wstring &name ) override {
throw TypeException(L"not complete declaration");
}
virtual MEMOFFSET_64 getElementVa( size_t index ) {
MEMOFFSET_64 getElementVa( size_t index ) override {
throw TypeException(L"not complete declaration");
}
virtual bool isStaticMember( const std::wstring &name ) {
bool isStaticMember( const std::wstring &name ) override {
throw TypeException(L"not complete declaration");
}
virtual bool isStaticMember( size_t index ) {
bool isStaticMember( size_t index ) override {
throw TypeException(L"not complete declaration");
}
virtual bool isVirtualMember( const std::wstring &name ) {
bool isVirtualMember( const std::wstring &name ) override {
throw TypeException(L"not complete declaration");
}
virtual bool isVirtualMember( size_t index ) {
bool isVirtualMember( size_t index ) override {
throw TypeException(L"not complete declaration");
}
bool isIncomplete() override {
return true;
}
protected:
std::wstring m_name;
......@@ -225,6 +232,28 @@ protected:
};
class TypeInfoIncompleteClangArray : public TypeInfoClangArray
{
public:
TypeInfoIncompleteClangArray(ClangASTSessionPtr& session, const clang::ArrayType* arrayType) :
TypeInfoClangArray(session, arrayType)
{}
protected:
bool isIncomplete() override
{
return true;
}
size_t getSize() override
{
throw TypeException(L"incomplete array");
}
};
class TypeInfoClangRef : public TypeInfoImp
{
public:
......
......@@ -819,10 +819,17 @@ TypeInfoPtr applyComplexModifierRecursive(const parser::ComplexMatcher& matcher,
if (matcher.isArray())
{
auto indices = matcher.getArrayMatcher().getArrayIndices();
for ( auto it = indices.rbegin(); it != indices.rend(); ++it)
for (auto it = indices.rbegin(); it != indices.rend(); ++it)
{
auto i = getNumericConst(*it->getMatchResult().begin()).getValue().asLongLong();
typeInfo = typeInfo->arrayOf(i);
if (it->isIndexComplete())
{
auto i = getNumericConst(*it->getIndexMatcher().getMatchResult().begin()).getValue().asLongLong();
typeInfo = typeInfo->arrayOf(i);
}
else
{
typeInfo = typeInfo->arrayOf();
}
}
}
......@@ -856,8 +863,15 @@ std::string getTypeModifierRecursive(const parser::ComplexMatcher& matcher)
auto indices = matcher.getArrayMatcher().getArrayIndices();
for (auto it = indices.rbegin(); it != indices.rend(); ++it)
{
auto i = getNumericConst(*it->getMatchResult().begin()).getValue().asLongLong();
sstr << '[' << std::dec << i << ']';
if (it->isIndexComplete())
{
auto i = getNumericConst(*it->getIndexMatcher().getMatchResult().begin()).getValue().asLongLong();
sstr << '[' << std::dec << i << ']';
}
else
{
sstr << "[]";
}
}
}
......
......@@ -74,22 +74,49 @@ private:
};
class ArrayIndexMatcher : public Matcher
{
public:
MatchResult match(const TokenRange& matchRange)
{
auto matcher = all_of(Is<clang::tok::l_square>(), opt(numericMatcher), Is<clang::tok::r_square>());
return matchResult = matcher.match(matchRange);
}
bool isIndexComplete() const
{
return numericMatcher.getMatchResult().isMatched();
}
const auto& getIndexMatcher() const
{
assert(isIndexComplete());
return numericMatcher;
}
private:
NumericMatcher numericMatcher;
};
class ArrayMatcher : public Matcher
{
public:
MatchResult match(const TokenRange& matchRange)
{
return matchResult = rep(all_of(Is<clang::tok::l_square>(), numericMatcher, Is<clang::tok::r_square>()), numericMatcher).match(matchRange);
return matchResult = rep(indexMatcher, indexMatcher).match(matchRange);
}
const auto& getArrayIndices() const {
return numericMatcher;
return indexMatcher;
}
private:
ListMatcher<NumericMatcher> numericMatcher;
ListMatcher<ArrayIndexMatcher> indexMatcher;
};
class ComplexMatcher;
......
......@@ -59,6 +59,10 @@ protected:
NOT_IMPLEMENTED();
}
virtual TypeInfoPtr arrayOf() {
NOT_IMPLEMENTED();
}
virtual bool isArray() {
NOT_IMPLEMENTED();
}
......@@ -183,6 +187,10 @@ protected:
NOT_IMPLEMENTED();
}
virtual bool isIncomplete() {
NOT_IMPLEMENTED();
}
virtual TypeInfoPtr getMethod( const std::wstring &name, const std::wstring& prototype = L"") {
NOT_IMPLEMENTED();
}
......
......@@ -783,11 +783,22 @@ TypeInfoPtr TypeInfoImp::ptrTo( size_t ptrSize )
TypeInfoPtr TypeInfoImp::arrayOf( size_t size )
{
if (isIncomplete())
throw TypeException(getName(), L"can not make array of incomplete type");
return TypeInfoPtr( new TypeInfoArray( shared_from_this(), size ) );
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfoImp::arrayOf()
{
if (isIncomplete())
throw TypeException(getName(), L"can not make array of incomplete type");
return TypeInfoPtr(new TypeInfoIncompleteArray(shared_from_this()));
}
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr TypeInfoImp::getVar(const DataAccessorPtr &dataSource)
{
if ( isBase() )
......@@ -855,32 +866,38 @@ std::wstring TypeInfoImp::getTemplateArg(size_t index)
std::wstring TypeInfoReference::getName()
{
std::wstring name;
TypeInfo *typeInfo = this;
TypeInfoPtr typeInfo = shared_from_this();
std::pair<std::wstring, std::wstring> tiName;
do {
if ( typeInfo->isArray() )
{
std::vector<size_t> indices;
do {
indices.push_back( typeInfo->getElementCount() );
if (!name.empty())
{
name.insert(0, 1, L'(');
name.insert(name.size(), 1, L')');
}
while( ( typeInfo = dynamic_cast<TypeInfoArray*>(typeInfo)->deref().get() )->isArray() );
if ( !name.empty() )
do
{
name.insert( 0, 1, L'(' );
name.insert( name.size(), 1, L')' );
}
if (typeInfo->isIncomplete())
{
name += L"[]";
}
else
{
std::wstringstream sstr;
sstr << L'[' << typeInfo->getElementCount() << L']';
name += sstr.str();
}
std::wstringstream sstr;
typeInfo = typeInfo->deref();
for ( std::vector<size_t>::iterator it = indices.begin(); it != indices.end(); ++it )
sstr << L'[' << *it << L']';
if (!typeInfo->isArray())
break;
name += sstr.str();
} while (true);
continue;
}
......@@ -889,9 +906,7 @@ std::wstring TypeInfoReference::getName()
{
name.insert( 0, 1, L'*' );
TypeInfoPointer *ptrTypeInfo = dynamic_cast<TypeInfoPointer*>(typeInfo);
typeInfo = ptrTypeInfo->deref().get();
typeInfo = typeInfo->deref();
continue;
}
......@@ -909,13 +924,6 @@ std::wstring TypeInfoReference::getName()
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfoArray::getElement( size_t index )
{
return m_derefType;
}
///////////////////////////////////////////////////////////////////////////////
std::wstring TypeInfoFields::print()
{
std::wstringstream sstr;
......
......@@ -76,6 +76,8 @@ protected:
TypeInfoPtr arrayOf( size_t size ) override;
TypeInfoPtr arrayOf() override;
bool isArray() override
{
return false;
......@@ -136,6 +138,11 @@ protected:
throw TypeException( getName(), L"type is not class method" );
}
bool isIncomplete() override
{
return false;
}
bool isTemplate() override;
TypeInfoPtr getElement( const std::wstring &name ) override
......@@ -997,62 +1004,105 @@ protected:
///////////////////////////////////////////////////////////////////////////////
class TypeInfoArray : public TypeInfoReference
class TypeInfoIncompleteArray : public TypeInfoReference
{
public:
TypeInfoArray( const TypeInfoPtr &derefType, size_t count )
{
size_t maxCount = SIZE_MAX / derefType->getSize();
if (count > maxCount)
throw TypeException(L"Failed to create too long array");
m_derefType = derefType;
m_count = count;
}
TypeInfoIncompleteArray(const TypeInfoPtr &derefType) : m_derefType(derefType)
{}
virtual TypeInfoPtr deref() {
TypeInfoPtr deref() override
{
return m_derefType;
}
//TypeInfoPtr getDerefType() {
// return m_derefType;
virtual size_t getAlignReq() {
size_t getAlignReq() override
{
return deref()->getAlignReq();
}
protected:
virtual std::wstring str() {
std::wstring str() override
{
return getName();
}
virtual bool isArray()
bool isArray() override
{
return true;
}
virtual size_t getElementCount() {
return m_count;
bool isIncomplete() override
{
return true;
}
virtual size_t getSize() {
return m_derefType->getSize() * m_count;
size_t getPtrSize() override
{
return m_derefType->getPtrSize();
}
virtual size_t getPtrSize() {
return m_derefType->getPtrSize();
TypeInfoPtr getElement(size_t index) override
{
return m_derefType;
}
TypeInfoPtr getElement( size_t index );
size_t getElementCount() override
{
throw TypeException(getName(), L" array is incomplete");
}
size_t getSize() override
{
throw TypeException(getName(), L" array is incomplete");
}
protected:
TypeInfoPtr m_derefType;
};
///////////////////////////////////////////////////////////////////////////////
class TypeInfoArray : public TypeInfoIncompleteArray
{
public:
TypeInfoArray(const TypeInfoPtr &derefType, size_t count) : TypeInfoIncompleteArray(derefType)
{
size_t maxCount = SIZE_MAX / derefType->getSize();
if (count > maxCount)
throw TypeException(L"Failed to create too long array");
m_count = count;
}
protected:
bool isIncomplete() override
{
return false;
}
size_t getElementCount() override
{
return m_count;
}
size_t getSize() override
{
return m_derefType->getSize() * m_count;
}
protected:
size_t m_count;
};
///////////////////////////////////////////////////////////////////////////////
class TypeInfoSymbolArray : public TypeInfoArray
......
......@@ -539,4 +539,39 @@ TEST_F(ClangTest, NestedEnum)
EXPECT_EQ(1, *testStruct->getElement(L"VAL"));
EXPECT_EQ(2, *testStruct->getElement(L"VAL1"));
}
TEST_F(ClangTest, PtrToIncompleteArray)
{
static const wchar_t srcCode[] = L" \
struct Test { \
int(*a)[]; \
}; \
";
TypeInfoPtr testStruct;
ASSERT_NO_THROW(testStruct = compileType(srcCode, L"Test"));
EXPECT_NO_THROW(testStruct->getElement(L"a")->getSize());
EXPECT_NO_THROW(testStruct->getElement(L"a")->deref());
EXPECT_TRUE(testStruct->getElement(L"a")->deref()->isIncomplete());
EXPECT_THROW(testStruct->getElement(L"a")->deref()->getSize(), TypeException);
}
TEST_F(ClangTest, PtrToIncompleteStruct)
{
static const wchar_t srcCode[] = L" \
struct Test1; \
struct Test2 { \
Test1* t; \
}; \
";
TypeInfoPtr testStruct;
ASSERT_NO_THROW(testStruct = compileType(srcCode, L"Test2"));
EXPECT_NO_THROW(testStruct->getElement(L"t")->getSize());
EXPECT_NO_THROW(testStruct->getElement(L"t")->deref());
EXPECT_TRUE(testStruct->getElement(L"t")->deref()->isIncomplete());
EXPECT_THROW(testStruct->getElement(L"t")->deref()->getSize(), TypeException);
}
\ No newline at end of file
......@@ -125,15 +125,21 @@ TEST(TypeEvalTest, ArrayBaseType)
EXPECT_EQ(L"Int8B[2][3]", evalType("long long[2][3]")->getName());
EXPECT_EQ(L"UInt8B[1]", evalType("uint64_t[1]")->getName());
EXPECT_EQ(sizeof( short[10][2] ), evalType("short[10][2]")->getSize());
EXPECT_THROW(evalType("int[]"), TypeException);
EXPECT_EQ(sizeof(short[10][2]), evalType("short[10][2]")->getSize());
}
TEST(TypeEvalTest, IncpmleteArrayType)
{
EXPECT_NO_THROW(evalType("int[]"));
EXPECT_NO_THROW(evalType("int[][2]"));
EXPECT_THROW(evalType("int[][]"), TypeException);
EXPECT_THROW(evalType("int[2][]"), TypeException);
}
TEST(TypeEvalTest, ComplexBaseType)
{
EXPECT_EQ(L"Int1B(*)[20]", evalType("char (*)[20]")->getName());
EXPECT_EQ(sizeof(char (*)[20]), evalType("char (*)[20]")->getSize());
EXPECT_EQ(sizeof(char(*)[20]), evalType("char (*)[20]")->getSize());
EXPECT_EQ(L"Int1B(*[5])[20]", evalType("char (*[5])[20]")->getName());
EXPECT_EQ(sizeof(char(*[5])[20]), evalType("char (*[5])[20]")->getSize());
......@@ -142,10 +148,14 @@ TEST(TypeEvalTest, ComplexBaseType)
EXPECT_EQ(sizeof(char(*(*)[5])[20]), evalType("char (*(*)[5])[20]")->getSize());
}
TEST(TypeEvalTest, IncompleteComplexType)
{
EXPECT_EQ(sizeof(int(*)[]), evalType("int(*)[]")->getSize());
EXPECT_EQ(sizeof(int(*)[][4]), evalType("int(*)[][4]")->getSize());
}
TEST(TypeEvalTest, StructType)
{
struct TestStruct {
int field1;
char field2;
......@@ -187,7 +197,6 @@ TEST(TypeEvalTest, EnumType)
}; \
";
TypeInfoProviderPtr typeProvider = getTypeInfoProviderFromSource(sourceCode);
EXPECT_EQ(TestEnum::TEN, evalType("TestEnum::TEN", typeProvider)->getValue());
......@@ -451,6 +460,40 @@ TEST(TypeEvalTest, Void)
EXPECT_THROW(evalType("void&"), TypeException);
EXPECT_THROW(evalType("void&&"), TypeException);
EXPECT_THROW(evalType("void[5]"), TypeException);
}
TEST(TypeEvalTest, TemplateIncompleteArray)
{
static const char sourceCode[] = " \
template<typename T1> \
struct TestStruct { \
}; \
TestStruct<int[]> testVal1; \
TestStruct<int*[]> testVal2; \
TestStruct<void*[]> testVal3; \
";
TypeInfoProviderPtr typeProvider = getTypeInfoProviderFromSource(sourceCode);
EXPECT_NO_THROW(evalType("TestStruct<int[]>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<int*[]>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<void*[]>", typeProvider));
}
TEST(TypeEvalTest, TemplateVoid)
{
static const char sourceCode[] = " \
template<typename T1, typename T2, typename T3> \
struct TestStruct { \
}; \
TestStruct<void,void*,void*[1]> testVal1; \
TestStruct<void,void*,void*[]> testVal2; \
";
TypeInfoProviderPtr typeProvider = getTypeInfoProviderFromSource(sourceCode);
EXPECT_NO_THROW(evalType("TestStruct<void,void*,void*[1]>", typeProvider));
EXPECT_NO_THROW(evalType("TestStruct<void,void*,void*[]>", typeProvider));
}
......@@ -667,4 +667,23 @@ TEST_F(TypeInfoTest, TemplateArg)
TEST_F(TypeInfoTest, TemplateArgStdPair)
{
EXPECT_EQ(3, loadType(L"g_stdIntList")->getElement(L"_Mypair")->getTemplateArgsCount());
}
\ No newline at end of file
}
TEST_F(TypeInfoTest, DISABLED_IncomleteStruct)
{
TypeInfoPtr typeInfo;
ASSERT_NO_THROW(typeInfo = loadType(L"g_structAbstract"));
EXPECT_NO_THROW(typeInfo->deref());
EXPECT_THROW(typeInfo->deref()->getSize(), TypeException); //DIA return 0 size, there is no way to know a type in incomplete
}
TEST_F(TypeInfoTest, ArrayOfIncomplete)
{
TypeInfoPtr typeInfo;
ASSERT_NO_THROW(typeInfo = loadType(L"Int1B")->arrayOf());
EXPECT_EQ(L"Int1B[]", typeInfo->getName());
EXPECT_THROW(typeInfo->getSize(), TypeException);
EXPECT_THROW(typeInfo->arrayOf(1), TypeException);
EXPECT_THROW(typeInfo->arrayOf(), TypeException);
}