<div dir="ltr">I'm seeing the following warning on Mac.<div><br></div><div><p style="margin:0px;font-size:12px;font-family:Menlo"><b>/Users/ssilva/pg/llvm/tools/clang/tools/libclang/CXType.cpp:965:5: </b><span style="color:rgb(213,59,211)"><b>warning: </b></span><b>default label in switch which covers all enumeration values [-Wcovered-switch-default]</b></p>
<p style="margin:0px;font-size:12px;font-family:Menlo">    default:</p>
<p style="margin:0px;font-size:12px;font-family:Menlo;color:rgb(52,189,38)"><b>    ^</b></p>
<p style="margin:0px;font-size:12px;font-family:Menlo">1 warning generated.</p></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jan 29, 2015 at 12:45 PM, Francois Pichet <span dir="ltr"><<a href="mailto:pichet2000@gmail.com" target="_blank">pichet2000@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: fpichet<br>
Date: Thu Jan 29 06:45:29 2015<br>
New Revision: 227432<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=227432&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=227432&view=rev</a><br>
Log:<br>
libclang: Add three functions useful for dealing with anonymous fields:<br>
   clang_Cursor_getOffsetOfField<br>
   clang_Cursor_isAnonymous<br>
   clang_Type_visitFields<br>
Python: Add corresponding methods for dealing with anonymous fields.<br>
<br>
Patch by Loïc Jaquemet<br>
<br>
Modified:<br>
    cfe/trunk/bindings/python/clang/cindex.py<br>
    cfe/trunk/bindings/python/tests/cindex/test_type.py<br>
    cfe/trunk/include/clang-c/Index.h<br>
    cfe/trunk/test/Index/print-type-size.cpp<br>
    cfe/trunk/test/Index/print-type.cpp<br>
    cfe/trunk/tools/c-index-test/c-index-test.c<br>
    cfe/trunk/tools/libclang/CXType.cpp<br>
    cfe/trunk/tools/libclang/libclang.exports<br>
<br>
Modified: cfe/trunk/bindings/python/clang/cindex.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/bindings/python/clang/cindex.py (original)<br>
+++ cfe/trunk/bindings/python/clang/cindex.py Thu Jan 29 06:45:29 2015<br>
@@ -1476,6 +1476,18 @@ class Cursor(Structure):<br>
         """<br>
         return TokenGroup.get_tokens(self._tu, self.extent)<br>
<br>
+    def get_field_offsetof(self):<br>
+        """Returns the offsetof the FIELD_DECL pointed by this Cursor."""<br>
+        return conf.lib.clang_Cursor_getOffsetOfField(self)<br>
+<br>
+    def is_anonymous(self):<br>
+        """<br>
+        Check if the record is anonymous.<br>
+        """<br>
+        if self.kind == CursorKind.FIELD_DECL:<br>
+            return self.type.get_declaration().is_anonymous()<br>
+        return conf.lib.clang_Cursor_isAnonymous(self)<br>
+<br>
     def is_bitfield(self):<br>
         """<br>
         Check if the field is a bitfield.<br>
@@ -1884,6 +1896,21 @@ class Type(Structure):<br>
         return RefQualifierKind.from_id(<br>
                 conf.lib.clang_Type_getCXXRefQualifier(self))<br>
<br>
+    def get_fields(self):<br>
+        """Return an iterator for accessing the fields of this type."""<br>
+<br>
+        def visitor(field, children):<br>
+            assert field != conf.lib.clang_getNullCursor()<br>
+<br>
+            # Create reference to TU so it isn't GC'd before Cursor.<br>
+            field._tu = self._tu<br>
+            fields.append(field)<br>
+            return 1 # continue<br>
+        fields = []<br>
+        conf.lib.clang_Type_visitFields(self,<br>
+                            callbacks['fields_visit'](visitor), fields)<br>
+        return iter(fields)<br>
+<br>
     @property<br>
     def spelling(self):<br>
         """Retrieve the spelling of this Type."""<br>
@@ -2780,6 +2807,7 @@ class Token(Structure):<br>
 callbacks['translation_unit_includes'] = CFUNCTYPE(None, c_object_p,<br>
         POINTER(SourceLocation), c_uint, py_object)<br>
 callbacks['cursor_visit'] = CFUNCTYPE(c_int, Cursor, Cursor, py_object)<br>
+callbacks['fields_visit'] = CFUNCTYPE(c_int, Cursor, py_object)<br>
<br>
 # Functions strictly alphabetical order.<br>
 functionList = [<br>
@@ -3367,6 +3395,10 @@ functionList = [<br>
    [Cursor, c_uint],<br>
    c_ulonglong),<br>
<br>
+  ("clang_Cursor_isAnonymous",<br>
+   [Cursor],<br>
+   bool),<br>
+<br>
   ("clang_Cursor_isBitField",<br>
    [Cursor],<br>
    bool),<br>
@@ -3381,6 +3413,10 @@ functionList = [<br>
    _CXString,<br>
    _CXString.from_result),<br>
<br>
+  ("clang_Cursor_getOffsetOfField",<br>
+   [Cursor],<br>
+   c_longlong),<br>
+<br>
   ("clang_Type_getAlignOf",<br>
    [Type],<br>
    c_longlong),<br>
@@ -3401,6 +3437,10 @@ functionList = [<br>
   ("clang_Type_getCXXRefQualifier",<br>
    [Type],<br>
    c_uint),<br>
+<br>
+  ("clang_Type_visitFields",<br>
+   [Type, callbacks['fields_visit'], py_object],<br>
+   c_uint),<br>
 ]<br>
<br>
 class LibclangError(Exception):<br>
<br>
Modified: cfe/trunk/bindings/python/tests/cindex/test_type.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/cindex/test_type.py?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/cindex/test_type.py?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/bindings/python/tests/cindex/test_type.py (original)<br>
+++ cfe/trunk/bindings/python/tests/cindex/test_type.py Thu Jan 29 06:45:29 2015<br>
@@ -363,6 +363,7 @@ def test_offset():<br>
     """Ensure Cursor.get_record_field_offset works in anonymous records"""<br>
     source="""<br>
 struct Test {<br>
+  struct {int a;} typeanon;<br>
   struct {<br>
     int bariton;<br>
     union {<br>
@@ -371,15 +372,23 @@ struct Test {<br>
   };<br>
   int bar;<br>
 };"""<br>
-    tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64)),<br>
-           (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64)),<br>
-           (['-target','i386-pc-win32'],(8,16,0,32,64)),<br>
-           (['-target','msp430-none-none'],(2,14,0,32,64))]<br>
+    tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64,96)),<br>
+           (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64,96)),<br>
+           (['-target','i386-pc-win32'],(8,16,0,32,64,96)),<br>
+           (['-target','msp430-none-none'],(2,14,0,32,64,96))]<br>
     for flags, values in tries:<br>
-        align,total,bariton,foo,bar = values<br>
+        align,total,f1,bariton,foo,bar = values<br>
         tu = get_tu(source)<br>
         teststruct = get_cursor(tu, 'Test')<br>
-        fields = list(teststruct.get_children())<br>
+        children = list(teststruct.get_children())<br>
+        fields = list(teststruct.type.get_fields())<br>
+        assert children[0].kind == CursorKind.STRUCT_DECL<br>
+        assert children[0].spelling != "typeanon"<br>
+        assert children[1].spelling == "typeanon"<br>
+        assert fields[0].kind == CursorKind.FIELD_DECL<br>
+        assert fields[1].kind == CursorKind.FIELD_DECL<br>
+        assert fields[1].is_anonymous()<br>
+        assert teststruct.type.get_offset("typeanon") == f1<br>
         assert teststruct.type.get_offset("bariton") == bariton<br>
         assert teststruct.type.get_offset("foo") == foo<br>
         assert teststruct.type.get_offset("bar") == bar<br>
<br>
Modified: cfe/trunk/include/clang-c/Index.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang-c/Index.h (original)<br>
+++ cfe/trunk/include/clang-c/Index.h Thu Jan 29 06:45:29 2015<br>
@@ -32,7 +32,7 @@<br>
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.<br>
  */<br>
 #define CINDEX_VERSION_MAJOR 0<br>
-#define CINDEX_VERSION_MINOR 29<br>
+#define CINDEX_VERSION_MINOR 30<br>
<br>
 #define CINDEX_VERSION_ENCODE(major, minor) ( \<br>
       ((major) * 10000)                       \<br>
@@ -3281,6 +3281,28 @@ CINDEX_LINKAGE long long clang_Type_getS<br>
  */<br>
 CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S);<br>
<br>
+/**<br>
+ * \brief Return the offset of the field represented by the Cursor.<br>
+ *<br>
+ * If the cursor is not a field declaration, -1 is returned.<br>
+ * If the cursor semantic parent is not a record field declaration,<br>
+ *   CXTypeLayoutError_Invalid is returned.<br>
+ * If the field's type declaration is an incomplete type,<br>
+ *   CXTypeLayoutError_Incomplete is returned.<br>
+ * If the field's type declaration is a dependent type,<br>
+ *   CXTypeLayoutError_Dependent is returned.<br>
+ * If the field's name S is not found,<br>
+ *   CXTypeLayoutError_InvalidFieldName is returned.<br>
+ */<br>
+CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C);<br>
+<br>
+/**<br>
+ * \brief Determine whether the given cursor represents an anonymous record<br>
+ * declaration.<br>
+ */<br>
+CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C);<br>
+<br>
+<br>
 enum CXRefQualifierKind {<br>
   /** \brief No ref-qualifier was provided. */<br>
   CXRefQualifier_None = 0,<br>
@@ -5669,6 +5691,44 @@ CINDEX_LINKAGE<br>
 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc);<br>
<br>
 /**<br>
+ * \brief Visitor invoked for each field found by a traversal.<br>
+ *<br>
+ * This visitor function will be invoked for each field found by<br>
+ * clang_visitCursorFields(). Its first argument is the cursor being<br>
+ * visited, its second argument is the client data provided to<br>
+ * clang_visitCursorFields().<br>
+ *<br>
+ * The visitor should return one of the \c CXVisitorResult values<br>
+ * to direct clang_visitCursorFields().<br>
+ */<br>
+typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C,<br>
+                                                  CXClientData client_data);<br>
+<br>
+/**<br>
+ * \brief Visit the fields of a particular type.<br>
+ *<br>
+ * This function visits all the direct fields of the given cursor,<br>
+ * invoking the given \p visitor function with the cursors of each<br>
+ * visited field. The traversal may be ended prematurely, if<br>
+ * the visitor returns \c CXFieldVisit_Break.<br>
+ *<br>
+ * \param T the record type whose field may be visited.<br>
+ *<br>
+ * \param visitor the visitor function that will be invoked for each<br>
+ * field of \p T.<br>
+ *<br>
+ * \param client_data pointer data supplied by the client, which will<br>
+ * be passed to the visitor each time it is invoked.<br>
+ *<br>
+ * \returns a non-zero value if the traversal was terminated<br>
+ * prematurely by the visitor returning \c CXFieldVisit_Break.<br>
+ */<br>
+CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,<br>
+                                               CXFieldVisitor visitor,<br>
+                                               CXClientData client_data);<br>
+<br>
+<br>
+/**<br>
  * @}<br>
  */<br>
<br>
<br>
Modified: cfe/trunk/test/Index/print-type-size.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/print-type-size.cpp?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/print-type-size.cpp?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Index/print-type-size.cpp (original)<br>
+++ cfe/trunk/test/Index/print-type-size.cpp Thu Jan 29 06:45:29 2015<br>
@@ -65,12 +65,12 @@ struct Test2 {<br>
       int foo;<br>
     };<br>
     struct {<br>
-//CHECK64: FieldDecl=bar:[[@LINE+1]]:11 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=32]<br>
+//CHECK64: FieldDecl=bar:[[@LINE+1]]:11 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=32/0]<br>
       int bar;<br>
     };<br>
     struct {<br>
         struct {<br>
-//CHECK64: FieldDecl=foobar:[[@LINE+1]]:15 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=64]<br>
+//CHECK64: FieldDecl=foobar:[[@LINE+1]]:15 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=64/0]<br>
           int foobar;<br>
         };<br>
     };<br>
@@ -160,6 +160,7 @@ struct s4a {<br>
       struct {<br>
         struct {<br>
           struct {<br>
+//CHECK64: FieldDecl=s4_e1:[[@LINE+1]]:17 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=-1/0]<br>
             int s4_e1;<br>
           };<br>
         };<br>
<br>
Modified: cfe/trunk/test/Index/print-type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/print-type.cpp?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/print-type.cpp?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Index/print-type.cpp (original)<br>
+++ cfe/trunk/test/Index/print-type.cpp Thu Jan 29 06:45:29 2015<br>
@@ -44,6 +44,7 @@ void foo(int i, int incomplete_array[])<br>
<br>
 struct Blob {<br>
   int i;<br>
+  int j;<br>
 };<br>
 int Blob::*member_pointer;<br>
<br>
@@ -58,7 +59,7 @@ int Blob::*member_pointer;<br>
 // CHECK: NonTypeTemplateParameter=U:8:32 (Definition) [type=unsigned int] [typekind=UInt] [isPOD=1]<br>
 // CHECK: TemplateTemplateParameter=W:8:60 (Definition) [type=] [typekind=Invalid] [isPOD=0]<br>
 // CHECK: Namespace=inner:14:11 (Definition) [type=] [typekind=Invalid] [isPOD=0]<br>
-// CHECK: StructDecl=Bar:16:8 (Definition) [type=outer::inner::Bar] [typekind=Record] [isPOD=0]<br>
+// CHECK: StructDecl=Bar:16:8 (Definition) [type=outer::inner::Bar] [typekind=Record] [isPOD=0] [nbFields=1]<br>
 // CHECK: CXXConstructor=Bar:17:3 (Definition) [type=void (outer::Foo<bool> *){{.*}}] [typekind=FunctionProto] [canonicaltype=void (outer::Foo<bool> *){{.*}}] [canonicaltypekind=FunctionProto] [resulttype=void] [resulttypekind=Void] [args= [outer::Foo<bool> *] [Pointer]] [isPOD=0]<br>
 // CHECK: ParmDecl=foo:17:25 (Definition) [type=outer::Foo<bool> *] [typekind=Pointer] [canonicaltype=outer::Foo<bool> *] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=outer::Foo<bool>] [pointeekind=Unexposed]<br>
 // CHECK: NamespaceRef=outer:1:11 [type=] [typekind=Invalid] [isPOD=0]<br>
@@ -115,6 +116,6 @@ int Blob::*member_pointer;<br>
 // CHECK: DeclStmt= [type=] [typekind=Invalid] [isPOD=0]<br>
 // CHECK: VarDecl=variable_array:43:47 (Definition) [type=int [i]] [typekind=VariableArray] [isPOD=1]<br>
 // CHECK: DeclRefExpr=i:43:14 [type=int] [typekind=Int] [isPOD=1]<br>
-// CHECK: StructDecl=Blob:45:8 (Definition) [type=Blob] [typekind=Record] [isPOD=1]<br>
+// CHECK: StructDecl=Blob:45:8 (Definition) [type=Blob] [typekind=Record] [isPOD=1] [nbFields=2]<br>
 // CHECK: FieldDecl=i:46:7 (Definition) [type=int] [typekind=Int] [isPOD=1]<br>
 // CHECK: VarDecl=member_pointer:48:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [isPOD=1]<br>
<br>
Modified: cfe/trunk/tools/c-index-test/c-index-test.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)<br>
+++ cfe/trunk/tools/c-index-test/c-index-test.c Thu Jan 29 06:45:29 2015<br>
@@ -1250,6 +1250,12 @@ static void PrintTypeAndTypeKind(CXType<br>
   clang_disposeString(TypeKindSpelling);<br>
 }<br>
<br>
+static enum CXVisitorResult FieldVisitor(CXCursor C,<br>
+                                         CXClientData client_data) {<br>
+    (*(int *) client_data)+=1;<br>
+    return CXVisit_Continue;<br>
+}<br>
+<br>
 static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,<br>
                                          CXClientData d) {<br>
   if (!clang_isInvalid(clang_getCursorKind(cursor))) {<br>
@@ -1320,6 +1326,22 @@ static enum CXChildVisitResult PrintType<br>
         PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]");<br>
       }<br>
     }<br>
+    /* Print the number of fields if they exist. */<br>
+    {<br>
+      int numFields = 0;<br>
+      if (clang_Type_visitFields(T, FieldVisitor, &numFields)){<br>
+        if (numFields != 0) {<br>
+          printf(" [nbFields=%d]", numFields);<br>
+        }<br>
+        /* Print if it is an anonymous record. */<br>
+        {<br>
+          unsigned isAnon = clang_Cursor_isAnonymous(cursor);<br>
+          if (isAnon != 0) {<br>
+            printf(" [isAnon=%d]", isAnon);<br>
+          }<br>
+        }<br>
+      }<br>
+    }<br>
<br>
     printf("\n");<br>
   }<br>
@@ -1353,28 +1375,29 @@ static enum CXChildVisitResult PrintType<br>
   {<br>
     CXString FieldSpelling = clang_getCursorSpelling(cursor);<br>
     const char *FieldName = clang_getCString(FieldSpelling);<br>
-    /* recurse to get the root anonymous record parent */<br>
-    CXCursor Parent, Root;<br>
+    /* recurse to get the first parent record that is not anonymous. */<br>
+    CXCursor Parent, Record;<br>
+    unsigned RecordIsAnonymous = 0;<br>
     if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) {<br>
-      CXString RootParentSpelling;<br>
-      const char *RootParentName = 0;<br>
-      Parent = p;<br>
+      Record = Parent = p;<br>
       do {<br>
-        if (RootParentName != 0)<br>
-          clang_disposeString(RootParentSpelling);<br>
-<br>
-        Root = Parent;<br>
-        RootParentSpelling = clang_getCursorSpelling(Root);<br>
-        RootParentName = clang_getCString(RootParentSpelling);<br>
-        Parent = clang_getCursorSemanticParent(Root);<br>
-      } while (clang_getCursorType(Parent).kind == CXType_Record &&<br>
-               !strcmp(RootParentName, ""));<br>
-      clang_disposeString(RootParentSpelling);<br>
-      /* if RootParentName is "", record is anonymous. */<br>
+        Record = Parent;<br>
+        Parent = clang_getCursorSemanticParent(Record);<br>
+        RecordIsAnonymous = clang_Cursor_isAnonymous(Record);<br>
+        /* Recurse as long as the parent is a CXType_Record and the Record<br>
+           is anonymous */<br>
+      } while ( clang_getCursorType(Parent).kind == CXType_Record &&<br>
+                RecordIsAnonymous > 0);<br>
       {<br>
-        long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Root),<br>
+        long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Record),<br>
                                                   FieldName);<br>
-        printf(" [offsetof=%lld]", Offset);<br>
+        long long Offset2 = clang_Cursor_getOffsetOfField(cursor);<br>
+        if (Offset == Offset2){<br>
+            printf(" [offsetof=%lld]", Offset);<br>
+        } else {<br>
+            /* Offsets will be different in anonymous records. */<br>
+            printf(" [offsetof=%lld/%lld]", Offset, Offset2);<br>
+        }<br>
       }<br>
     }<br>
     clang_disposeString(FieldSpelling);<br>
<br>
Modified: cfe/trunk/tools/libclang/CXType.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXType.cpp?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXType.cpp?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/tools/libclang/CXType.cpp (original)<br>
+++ cfe/trunk/tools/libclang/CXType.cpp Thu Jan 29 06:45:29 2015<br>
@@ -775,13 +775,12 @@ static long long visitRecordForValidatio<br>
   return 0;<br>
 }<br>
<br>
-long long clang_Type_getOffsetOf(CXType PT, const char *S) {<br>
-  // check that PT is not incomplete/dependent<br>
-  CXCursor PC = clang_getTypeDeclaration(PT);<br>
+static long long validateFieldParentType(CXCursor PC, CXType PT){<br>
   if (clang_isInvalid(PC.kind))<br>
     return CXTypeLayoutError_Invalid;<br>
   const RecordDecl *RD =<br>
         dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));<br>
+  // validate parent declaration<br>
   if (!RD || RD->isInvalidDecl())<br>
     return CXTypeLayoutError_Invalid;<br>
   RD = RD->getDefinition();<br>
@@ -789,6 +788,7 @@ long long clang_Type_getOffsetOf(CXType<br>
     return CXTypeLayoutError_Incomplete;<br>
   if (RD->isInvalidDecl())<br>
     return CXTypeLayoutError_Invalid;<br>
+  // validate parent type<br>
   QualType RT = GetQualType(PT);<br>
   if (RT->isIncompleteType())<br>
     return CXTypeLayoutError_Incomplete;<br>
@@ -798,12 +798,25 @@ long long clang_Type_getOffsetOf(CXType<br>
   long long Error = visitRecordForValidation(RD);<br>
   if (Error < 0)<br>
     return Error;<br>
+  return 0;<br>
+}<br>
+<br>
+long long clang_Type_getOffsetOf(CXType PT, const char *S) {<br>
+  // check that PT is not incomplete/dependent<br>
+  CXCursor PC = clang_getTypeDeclaration(PT);<br>
+  long long Error = validateFieldParentType(PC,PT);<br>
+  if (Error < 0)<br>
+    return Error;<br>
   if (!S)<br>
     return CXTypeLayoutError_InvalidFieldName;<br>
   // lookup field<br>
   ASTContext &Ctx = cxtu::getASTUnit(GetTU(PT))->getASTContext();<br>
   IdentifierInfo *II = &Ctx.Idents.get(S);<br>
   DeclarationName FieldName(II);<br>
+  const RecordDecl *RD =<br>
+        dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));<br>
+  // verified in validateFieldParentType<br>
+  RD = RD->getDefinition();<br>
   RecordDecl::lookup_const_result Res = RD->lookup(FieldName);<br>
   // If a field of the parent record is incomplete, lookup will fail.<br>
   // and we would return InvalidFieldName instead of Incomplete.<br>
@@ -819,6 +832,25 @@ long long clang_Type_getOffsetOf(CXType<br>
   return CXTypeLayoutError_InvalidFieldName;<br>
 }<br>
<br>
+long long clang_Cursor_getOffsetOfField(CXCursor C) {<br>
+  if (clang_isDeclaration(C.kind)) {<br>
+    // we need to validate the parent type<br>
+    CXCursor PC = clang_getCursorSemanticParent(C);<br>
+    CXType PT = clang_getCursorType(PC);<br>
+    long long Error = validateFieldParentType(PC,PT);<br>
+    if (Error < 0)<br>
+      return Error;<br>
+    // proceed with the offset calculation<br>
+    const Decl *D = cxcursor::getCursorDecl(C);<br>
+    ASTContext &Ctx = cxcursor::getCursorContext(C);<br>
+    if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D))<br>
+      return Ctx.getFieldOffset(FD);<br>
+    if (const IndirectFieldDecl *IFD = dyn_cast_or_null<IndirectFieldDecl>(D))<br>
+      return Ctx.getFieldOffset(IFD);<br>
+  }<br>
+  return -1;<br>
+}<br>
+<br>
 enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) {<br>
   QualType QT = GetQualType(T);<br>
   if (QT.isNull())<br>
@@ -908,4 +940,42 @@ CXType clang_Type_getTemplateArgumentAsT<br>
   return MakeCXType(A.getAsType(), GetTU(CT));<br>
 }<br>
<br>
+unsigned clang_Type_visitFields(CXType PT,<br>
+                                CXFieldVisitor visitor,<br>
+                                CXClientData client_data){<br>
+  CXCursor PC = clang_getTypeDeclaration(PT);<br>
+  if (clang_isInvalid(PC.kind))<br>
+    return false;<br>
+  const RecordDecl *RD =<br>
+        dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));<br>
+  if (!RD || RD->isInvalidDecl())<br>
+    return false;<br>
+  RD = RD->getDefinition();<br>
+  if (!RD || RD->isInvalidDecl())<br>
+    return false;<br>
+<br>
+  for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();<br>
+       I != E; ++I){<br>
+    const FieldDecl *FD = dyn_cast_or_null<FieldDecl>((*I));<br>
+    // Callback to the client.<br>
+    switch (visitor(cxcursor::MakeCXCursor(FD, GetTU(PT)), client_data)){<br>
+    case CXVisit_Break:<br>
+      return true;<br>
+    case CXVisit_Continue:<br>
+    default:<br>
+      break;<br>
+    }<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+unsigned clang_Cursor_isAnonymous(CXCursor C){<br>
+  if (!clang_isDeclaration(C.kind))<br>
+    return 0;<br>
+  const Decl *D = cxcursor::getCursorDecl(C);<br>
+  if (const RecordDecl *FD = dyn_cast_or_null<RecordDecl>(D))<br>
+    return FD->isAnonymousStructOrUnion();<br>
+  return 0;<br>
+}<br>
+<br>
 } // end: extern "C"<br>
<br>
Modified: cfe/trunk/tools/libclang/libclang.exports<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=227432&r1=227431&r2=227432&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=227432&r1=227431&r2=227432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/tools/libclang/libclang.exports (original)<br>
+++ cfe/trunk/tools/libclang/libclang.exports Thu Jan 29 06:45:29 2015<br>
@@ -21,9 +21,11 @@ clang_Cursor_getNumArguments<br>
 clang_Cursor_getObjCDeclQualifiers<br>
 clang_Cursor_getObjCPropertyAttributes<br>
 clang_Cursor_getObjCSelectorIndex<br>
+clang_Cursor_getOffsetOfField<br>
 clang_Cursor_getSpellingNameRange<br>
 clang_Cursor_getTranslationUnit<br>
 clang_Cursor_getReceiverType<br>
+clang_Cursor_isAnonymous<br>
 clang_Cursor_isBitField<br>
 clang_Cursor_isDynamicCall<br>
 clang_Cursor_isNull<br>
@@ -77,6 +79,7 @@ clang_Type_getOffsetOf<br>
 clang_Type_getNumTemplateArguments<br>
 clang_Type_getTemplateArgumentAsType<br>
 clang_Type_getCXXRefQualifier<br>
+clang_Type_visitFields<br>
 clang_VerbatimBlockLineComment_getText<br>
 clang_VerbatimLineComment_getText<br>
 clang_HTMLTagComment_getAsString<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>