diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/c-index-test/c-index-test.c | 59 | ||||
-rw-r--r-- | tools/libclang/CXType.cpp | 120 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 4 |
3 files changed, 183 insertions, 0 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index ce9e4910ae..e97cb30589 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1144,6 +1144,61 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, return CXChildVisit_Recurse; } +static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p, + CXClientData d) { + CXType T; + enum CXCursorKind K = clang_getCursorKind(cursor); + if (clang_isInvalid(K)) + return CXChildVisit_Recurse; + T = clang_getCursorType(cursor); + PrintCursor(cursor, NULL); + PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]"); + /* Print the type sizeof if applicable. */ + { + long long Size = clang_Type_getSizeOf(T); + if (Size >= 0 || Size < -1 ) { + printf(" [sizeof=%lld]", Size); + } + } + /* Print the type alignof if applicable. */ + { + long long Align = clang_Type_getAlignOf(T); + if (Align >= 0 || Align < -1) { + printf(" [alignof=%lld]", Align); + } + } + /* Print the record field offset if applicable. */ + { + const char *FieldName = clang_getCString(clang_getCursorSpelling(cursor)); + /* recurse to get the root anonymous record parent */ + CXCursor Parent, Root; + if (clang_getCursorKind(cursor) == CXCursor_FieldDecl ) { + const char *RootParentName; + Root = Parent = p; + do { + Root = Parent; + RootParentName = clang_getCString(clang_getCursorSpelling(Root)); + Parent = clang_getCursorSemanticParent(Root); + } while ( clang_getCursorType(Parent).kind == CXType_Record && + !strcmp(RootParentName, "") ); + /* if RootParentName is "", record is anonymous. */ + { + long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Root), + FieldName); + printf(" [offsetof=%lld]", Offset); + } + } + } + /* Print if its a bitfield */ + { + int IsBitfield = clang_Cursor_isBitField(cursor); + if (IsBitfield) + printf(" [BitFieldSize=%d]", clang_getFieldDeclBitWidth(cursor)); + } + printf("\n"); + return CXChildVisit_Recurse; +} + /******************************************************************************/ /* Bitwidth testing. */ /******************************************************************************/ @@ -3642,6 +3697,7 @@ static void print_usage(void) { fprintf(stderr, " c-index-test -test-print-linkage-source {<args>}*\n" " c-index-test -test-print-type {<args>}*\n" + " c-index-test -test-print-type-size {<args>}*\n" " c-index-test -test-print-bitwidth {<args>}*\n" " c-index-test -print-usr [<CursorKind> {<args>}]*\n" " c-index-test -print-usr-file <file>\n" @@ -3728,6 +3784,9 @@ int cindextest_main(int argc, const char **argv) { else if (argc > 2 && strcmp(argv[1], "-test-print-type") == 0) return perform_test_load_source(argc - 2, argv + 2, "all", PrintType, 0); + else if (argc > 2 && strcmp(argv[1], "-test-print-type-size") == 0) + return perform_test_load_source(argc - 2, argv + 2, "all", + PrintTypeSize, 0); else if (argc > 2 && strcmp(argv[1], "-test-print-bitwidth") == 0) return perform_test_load_source(argc - 2, argv + 2, "all", PrintBitWidth, 0); diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 6f87fc51a4..16009bf47a 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -651,6 +651,126 @@ long long clang_getArraySize(CXType CT) { return result; } +long long clang_Type_getAlignOf(CXType T) { + if (T.kind == CXType_Invalid) + return CXTypeLayoutError_Invalid; + ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext(); + QualType QT = GetQualType(T); + // [expr.alignof] p1: return size_t value for complete object type, reference + // or array. + // [expr.alignof] p3: if reference type, return size of referenced type + if (QT->isReferenceType()) + QT = QT.getNonReferenceType(); + if (QT->isIncompleteType()) + return CXTypeLayoutError_Incomplete; + if (QT->isDependentType()) + return CXTypeLayoutError_Dependent; + // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl + // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1 + // if (QT->isVoidType()) return 1; + return Ctx.getTypeAlignInChars(QT).getQuantity(); +} + +long long clang_Type_getSizeOf(CXType T) { + if (T.kind == CXType_Invalid) + return CXTypeLayoutError_Invalid; + ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext(); + QualType QT = GetQualType(T); + // [expr.sizeof] p2: if reference type, return size of referenced type + if (QT->isReferenceType()) + QT = QT.getNonReferenceType(); + // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete + // enumeration + // Note: We get the cxtype, not the cxcursor, so we can't call + // FieldDecl->isBitField() + // [expr.sizeof] p3: pointer ok, function not ok. + // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error + if (QT->isIncompleteType()) + return CXTypeLayoutError_Incomplete; + if (QT->isDependentType()) + return CXTypeLayoutError_Dependent; + if (!QT->isConstantSizeType()) + return CXTypeLayoutError_NotConstantSize; + // [gcc extension] lib/AST/ExprConstant.cpp:1372 + // HandleSizeof : {voidtype,functype} == 1 + // not handled by ASTContext.cpp:1313 getTypeInfoImpl + if (QT->isVoidType() || QT->isFunctionType()) + return 1; + return Ctx.getTypeSizeInChars(QT).getQuantity(); +} + +static long long visitRecordForValidation(const RecordDecl *RD) { + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I){ + QualType FQT = (*I)->getType(); + if (FQT->isIncompleteType()) + return CXTypeLayoutError_Incomplete; + if (FQT->isDependentType()) + return CXTypeLayoutError_Dependent; + // recurse + if (const RecordType *ChildType = (*I)->getType()->getAs<RecordType>()) { + if (const RecordDecl *Child = ChildType->getDecl()) { + long long ret = visitRecordForValidation(Child); + if (ret < 0) + return ret; + } + } + // else try next field + } + return 0; +} + +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)); + if (!RD) + return CXTypeLayoutError_Invalid; + RD = RD->getDefinition(); + if (!RD) + return CXTypeLayoutError_Incomplete; + QualType RT = GetQualType(PT); + if (RT->isIncompleteType()) + return CXTypeLayoutError_Incomplete; + if (RT->isDependentType()) + 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; + if (!S) + return CXTypeLayoutError_InvalidFieldName; + // lookup field + ASTContext &Ctx = cxtu::getASTUnit(GetTU(PT))->getASTContext(); + IdentifierInfo *II = &Ctx.Idents.get(S); + DeclarationName FieldName(II); + 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. + // But this erroneous results does protects again a hidden assertion failure + // in the RecordLayoutBuilder + if (Res.size() != 1) + return CXTypeLayoutError_InvalidFieldName; + if (const FieldDecl *FD = dyn_cast<FieldDecl>(Res.front())) + return Ctx.getFieldOffset(FD); + if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Res.front())) + return Ctx.getFieldOffset(IFD); + // we don't want any other Decl Type. + return CXTypeLayoutError_InvalidFieldName; +} + +unsigned clang_Cursor_isBitField(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return 0; + const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(cxcursor::getCursorDecl(C)); + if (!FD) + return 0; + return FD->isBitField(); +} + CXString clang_getDeclObjCTypeEncoding(CXCursor C) { if (!clang_isDeclaration(C.kind)) return cxstring::createEmpty(); diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index d99f24ef03..1f179f13bd 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -14,6 +14,7 @@ clang_Cursor_getObjCSelectorIndex clang_Cursor_getSpellingNameRange clang_Cursor_getTranslationUnit clang_Cursor_getReceiverType +clang_Cursor_isBitField clang_Cursor_isDynamicCall clang_Cursor_isNull clang_Cursor_getModule @@ -53,6 +54,9 @@ clang_TParamCommandComment_getParamName clang_TParamCommandComment_isParamPositionValid clang_TParamCommandComment_getDepth clang_TParamCommandComment_getIndex +clang_Type_getAlignOf +clang_Type_getSizeOf +clang_Type_getOffsetOf clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString |