diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index f5caca8572cbce188c18920a80195a0cb91aef16..5792effea59be61ad12a1e48ba811a6d5b36efeb 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -1476,18 +1476,6 @@ 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. @@ -1896,21 +1884,6 @@ 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.""" @@ -2807,7 +2780,6 @@ 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 = [ @@ -3395,10 +3367,6 @@ functionList = [ [Cursor, c_uint], c_ulonglong), - ("clang_Cursor_isAnonymous", - [Cursor], - bool), - ("clang_Cursor_isBitField", [Cursor], bool), @@ -3413,10 +3381,6 @@ functionList = [ _CXString, _CXString.from_result), - ("clang_Cursor_getOffsetOfField", - [Cursor], - c_longlong), - ("clang_Type_getAlignOf", [Type], c_longlong), @@ -3437,10 +3401,6 @@ functionList = [ ("clang_Type_getCXXRefQualifier", [Type], c_uint), - - ("clang_Type_visitFields", - [Type, callbacks['fields_visit'], py_object], - c_uint), ] class LibclangError(Exception): diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py index f3dadf999bd84492a8a55910710c27217c70e181..a02c06fe5a13f817973da5643898c78e77cc40f3 100644 --- a/bindings/python/tests/cindex/test_type.py +++ b/bindings/python/tests/cindex/test_type.py @@ -363,7 +363,6 @@ def test_offset(): """Ensure Cursor.get_record_field_offset works in anonymous records""" source=""" struct Test { - struct {int a;} typeanon; struct { int bariton; union { @@ -372,23 +371,15 @@ struct Test { }; int bar; };""" - 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))] + 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))] for flags, values in tries: - align,total,f1,bariton,foo,bar = values + align,total,bariton,foo,bar = values tu = get_tu(source) teststruct = get_cursor(tu, 'Test') - 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 + fields = list(teststruct.get_children()) assert teststruct.type.get_offset("bariton") == bariton assert teststruct.type.get_offset("foo") == foo assert teststruct.type.get_offset("bar") == bar diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index acee05b630c3997ae216f74d351c1bc28e2fde49..ac8ce1c85ef8ef17d9fbbb39894d7976e2a8ba48 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 30 +#define CINDEX_VERSION_MINOR 29 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -3281,28 +3281,6 @@ CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T); */ 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, @@ -5690,44 +5668,6 @@ CINDEX_LINKAGE void clang_indexLoc_getFileLocation(CXIdxLoc loc, 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); - - /** * @} */ diff --git a/test/Index/print-type-size.cpp b/test/Index/print-type-size.cpp index 45de93f308244a9b36ee6eaec0920a6f2d4a365e..58f2e14c33a4a7b60c7bd1f93c2ef2d14d782d81 100644 --- a/test/Index/print-type-size.cpp +++ b/test/Index/print-type-size.cpp @@ -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/0] +//CHECK64: FieldDecl=bar:[[@LINE+1]]:11 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=32] int bar; }; struct { struct { -//CHECK64: FieldDecl=foobar:[[@LINE+1]]:15 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=64/0] +//CHECK64: FieldDecl=foobar:[[@LINE+1]]:15 (Definition) [type=int] [typekind=Int] [sizeof=4] [alignof=4] [offsetof=64] int foobar; }; }; @@ -160,7 +160,6 @@ 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; }; }; diff --git a/test/Index/print-type.cpp b/test/Index/print-type.cpp index 7dbb39f930376d3ccfb51bbcf375e214eb73fbd2..af5c556c4dc6f00aa35de73bee99c9098cd9853d 100644 --- a/test/Index/print-type.cpp +++ b/test/Index/print-type.cpp @@ -44,7 +44,6 @@ void foo(int i, int incomplete_array[]) { int variable_array[i]; } struct Blob { int i; - int j; }; int Blob::*member_pointer; @@ -59,7 +58,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] [nbFields=3] +// CHECK: StructDecl=Bar:16:8 (Definition) [type=outer::inner::Bar] [typekind=Record] [isPOD=0] // 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] @@ -116,6 +115,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] [nbFields=2] +// CHECK: StructDecl=Blob:45:8 (Definition) [type=Blob] [typekind=Record] [isPOD=1] // 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] diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index a49f758e8e92b349ed39851fe052783ac6fbd569..56e4101399a53ad78c131e4744d1d30801819eb4 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1250,12 +1250,6 @@ static void PrintTypeAndTypeKind(CXType T, const char *Format) { 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))) { @@ -1326,22 +1320,6 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, 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"); } @@ -1375,29 +1353,28 @@ static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p, { CXString FieldSpelling = clang_getCursorSpelling(cursor); const char *FieldName = clang_getCString(FieldSpelling); - /* recurse to get the first parent record that is not anonymous. */ - CXCursor Parent, Record; - unsigned RecordIsAnonymous = 0; + /* recurse to get the root anonymous record parent */ + CXCursor Parent, Root; if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) { - Record = Parent = p; + CXString RootParentSpelling; + const char *RootParentName = 0; + Parent = p; do { - 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); + 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. */ { - long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Record), + long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Root), FieldName); - 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); - } + printf(" [offsetof=%lld]", Offset); } } clang_disposeString(FieldSpelling); diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 94f770c34b963e985ff0ef4cd9e1c61e0db4d668..4d526fbd59f64feb6d6c0ba761df6f6be883e218 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -775,12 +775,13 @@ static long long visitRecordForValidation(const RecordDecl *RD) { return 0; } -static long long validateFieldParentType(CXCursor PC, CXType PT){ +long long clang_Type_getOffsetOf(CXType PT, const char *S) { + // check that PT is not incomplete/dependent + CXCursor PC = clang_getTypeDeclaration(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(); @@ -788,7 +789,6 @@ static long long validateFieldParentType(CXCursor PC, CXType PT){ return CXTypeLayoutError_Incomplete; if (RD->isInvalidDecl()) return CXTypeLayoutError_Invalid; - // validate parent type QualType RT = GetQualType(PT); if (RT->isIncompleteType()) return CXTypeLayoutError_Incomplete; @@ -796,15 +796,6 @@ static long long validateFieldParentType(CXCursor PC, CXType PT){ return CXTypeLayoutError_Dependent; // We recurse into all record fields to detect incomplete and dependent types. 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) @@ -813,10 +804,6 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) { 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. @@ -832,25 +819,6 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) { 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()) @@ -940,41 +908,4 @@ CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned i) { 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: - 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" diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index f78f9981a98bd9ec47b25123ff47124d021684a3..fa2c0e70bf32135cf4f07cd02e549f11feb3849c 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -21,11 +21,9 @@ 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 @@ -79,7 +77,6 @@ clang_Type_getOffsetOf clang_Type_getNumTemplateArguments clang_Type_getTemplateArgumentAsType clang_Type_getCXXRefQualifier -clang_Type_visitFields clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString