diff options
| author | Francois Pichet <pichet2000@gmail.com> | 2015-01-29 12:45:29 +0000 |
|---|---|---|
| committer | Francois Pichet <pichet2000@gmail.com> | 2015-01-29 12:45:29 +0000 |
| commit | f3be1cc5a9d5d75665a3d3cff54d51a161608c59 (patch) | |
| tree | 46912475ca949b759b5d1c72a19a102661f4b724 /clang/tools | |
| parent | fad390109502f97f25828a993fd3bc2500fa93f5 (diff) | |
| download | bcm5719-llvm-f3be1cc5a9d5d75665a3d3cff54d51a161608c59.tar.gz bcm5719-llvm-f3be1cc5a9d5d75665a3d3cff54d51a161608c59.zip | |
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
llvm-svn: 227432
Diffstat (limited to 'clang/tools')
| -rw-r--r-- | clang/tools/c-index-test/c-index-test.c | 59 | ||||
| -rw-r--r-- | clang/tools/libclang/CXType.cpp | 76 | ||||
| -rw-r--r-- | clang/tools/libclang/libclang.exports | 3 |
3 files changed, 117 insertions, 21 deletions
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 56e4101399a..a49f758e8e9 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -1250,6 +1250,12 @@ 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))) { @@ -1320,6 +1326,22 @@ 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"); } @@ -1353,28 +1375,29 @@ static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p, { 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); diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 4d526fbd59f..7063077d5e0 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -775,13 +775,12 @@ static long long visitRecordForValidation(const RecordDecl *RD) { 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 PT, const char *S) { 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 PT, const char *S) { 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 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()) @@ -908,4 +940,42 @@ 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: + 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" diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index fa2c0e70bf3..f78f9981a98 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -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 |

