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

Jorn Vernee via cfe-dev cfe-dev at lists.llvm.org
Sat Feb 16 06:28:34 PST 2019


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



More information about the cfe-dev mailing list