r227432 - libclang: Add three functions useful for dealing with anonymous fields:

Sean Silva chisophugis at gmail.com
Thu Jan 29 06:28:33 PST 2015


I'm seeing the following warning on Mac.

*/Users/ssilva/pg/llvm/tools/clang/tools/libclang/CXType.cpp:965:5: **warning:
**default label in switch which covers all enumeration values
[-Wcovered-switch-default]*

    default:

*    ^*

1 warning generated.

On Thu, Jan 29, 2015 at 12:45 PM, Francois Pichet <pichet2000 at gmail.com>
wrote:

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


More information about the cfe-commits mailing list