Clang Parser Oddities

Here are some issues I’ve run into when using the new clang parser.

Tested on IDA Version 9.3sp2 on Windows.
The database is a generic MSVC x86 executable.

For these examples I’m using the following clang options (default Windows 32bit preset):

-target i386-pc-win32

All other compiler settings are default. The snippets are parsed using Parse C Header File...

Member function pointer of the wrong size for the platform.

struct Foo
{
    void (Foo::*mptr)();
};

static_assert(sizeof(Foo) == 0x4, "Wrong size");

Expected: Size of Foo is 0x4
Actual: Size of Foo is 0x8

Note that the static_assert is not tripped in this case.

Class templates with nested scoped enumeration produces an empty type.

template <typename T>
struct Foo
{
    enum class Bar { a, b };
};

void Func(Foo<int>::Bar);

Expected: Foo<int>::Bar contains a & b.
Actual: Foo<int>::Bar is empty.

Note that using an unscoped enumeration produces the expected result.

The using directive does not update the resulting typedef if that typedef already exists.

To reproduce this either:

  • Create a typedef named MyType with some other type, then parse the snippet.
  • Parse the snippet once, change the type of MyType, parse the snipped again.
using MyType = int;

struct Foo
{
    MyType a;
};

Expected: MyType is redefined as a typedef to int.
Actual: MyType remains unchanged.

Forward declaration of a class type using an elaborated type specifier silently corrupts the vtable of that type when parsing the same input a second time.

void SomeFunc(class Foo*); // Evil forward declaration

class Base
{
    virtual void VFunc_01();
};

class Foo : public Base
{
    virtual void VFunc_01() override;
    virtual void VFunc_02();
};

class Bar : public Foo
{
    virtual void VFunc_01() override;
    virtual void VFunc_02() override;
};

Parsing this snipped produces the expected vtables at first, however if parsed again VFunc_02 is no longer present in both Foo and Bar.

I have also observed other effects, for instance if Base is forward declared instead of Foo in the snipped above the this pointer type of VFunc_01 changes from Foo/Bar to Base when parsed the second time.

Note that this does not occur when using the compiler option: No IDA specific extensions.

Hi @HSUnit

Thanks for the feedback! I’ll reply in order.

Member function pointer of the wrong size for the platform.

The size of the pointer is determined by the binary, not by the parser options. Can you check whether the app is 32-bit or 64-bit?

Class templates with nested scoped enumeration produces an empty type.

I created an internal ticket. We’re investigating this.

The using directive does not update the resulting typedef if that typedef already exists.

We’ll take care of that.

Forward declaration of a class type using an elaborated type specifier silently corrupts the vtable of that type when parsing the same input a second time.

How did you parse this input? Using Ctrl+F9, or “Insert/Edit Type”.