[libclang] clang_Type_getOffsetOf returns incorrect result for type with flexible array.

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[libclang] clang_Type_getOffsetOf returns incorrect result for type with flexible array.

Bakhvalov, Denis via cfe-dev
Hi,

For project Panama [1] we are using libclang to parse header files and
generate layout descriptors for structs. But, we're having some trouble
when in comes to structs with flexible arrays.

For instance, for the following struct declaration:

struct Foo {
     int size;
     void *data[];
};

trying to get the offset of any of the fields returns
CXTypeLayoutError_Incomplete (-2). However, it should be possible to
find the offset of the fields. When using the offsetof macro [2], this
does return the correct result; offsetof(struct Foo, size) = 0, and
offsetof(struct Foo, data) = 8. clang_Type_getSizeOf returns the correct
size for Foo as well.

See the following example program:

```
#include <iostream>
#include <string>
#include <clang-c/Index.h>
#include <cstddef>

#include "a.h"

int main() {
     CXIndex index = clang_createIndex(0, 0);
     CXTranslationUnit unit = clang_parseTranslationUnit(
         index,
         "a.h", nullptr, 0,
         nullptr, 0,
         CXTranslationUnit_None);

     CXCursor cursor = clang_getTranslationUnitCursor(unit);
     clang_visitChildren(
         cursor,
         [](CXCursor c, CXCursor, CXClientData) {
             CXType type = clang_getCursorType(c);
             std::string spelling =
clang_getCString(clang_getTypeSpelling(type));
             if(spelling == "struct Foo") {
                 long long size = clang_Type_getSizeOf(type);
                 std::cout << "size of 'Foo': " << size << std::endl;

                 long long offset_size = clang_Type_getOffsetOf(type,
"size");
                 std::cout << "offset of 'size': " << offset_size <<
std::endl;
                 std::cout << "offset of 'size' with operator: " <<
offsetof(struct Foo, size) << std::endl;

                 long long offset_data = clang_Type_getOffsetOf(type,
"data");
                 std::cout << "offset of 'data': " << offset_data <<
std::endl;
                 std::cout << "offset of 'size' with operator: " <<
offsetof(struct Foo, data) << std::endl;
             }
             return CXChildVisit_Recurse;
         },
         nullptr
     );

     clang_disposeTranslationUnit(unit);
     clang_disposeIndex(index);
     return 0;
}
```

where a.h is just:

```
struct Foo {
     int size;
     void * data[];
};
```

The inability to report the field offset seems to be a bug/shortcoming.
Bugzilla doesn't seem to know about this [3], and since it currently
doesn't allow new user self-registration, I thought I'd try on here
first.

I've looked into the source here:
https://github.com/llvm-mirror/clang/blob/master/tools/libclang/CXType.cpp#L985 
. But, I don't really see where exactly the problem would be, or how to
fix it. We are currently using the binary distribution of LLVM found
here: http://releases.llvm.org/download.html . I've tried with the
latest version (7.0.1 at the time of writing), which also has the
problem.

I'm hoping someone here can help.

Best regards,
Jorn Vernee

[1] : http://openjdk.java.net/projects/panama/
[2] : https://en.cppreference.com/w/cpp/types/offsetof
[3] : https://bugs.llvm.org/buglist.cgi?quicksearch=flexible%20array
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev