diff --git a/kdevplatform/language/duchain/classmemberdeclaration.h b/kdevplatform/language/duchain/classmemberdeclaration.h --- a/kdevplatform/language/duchain/classmemberdeclaration.h +++ b/kdevplatform/language/duchain/classmemberdeclaration.h @@ -71,6 +71,38 @@ bool isMutable() const; void setMutable(bool isMutable); + /** + * \returns The size in bytes or -1 if unknown. + */ + int64_t sizeOf() const; + + /** + * Set the size to given number of bytes. Use -1 to represent unknown size. + */ + void setSizeOf(int64_t sizeOf); + + /** + * \returns The offset of the field in bits or -1 if unknown or not applicable. + */ + int64_t bitOffsetOf() const; + + /** + * Set the offset to given number of bits. Use -1 to represent unknown offset. + */ + void setBitOffsetOf(int64_t bitOffsetOf); + + /** + * \returns The alignment in bytes or -1 if unknown. + */ + int64_t alignOf() const; + + /** + * Set the alignment to given number of bytes. + * + * The value must be non-negative power of 2 or -1 to represent unknown alignment. + */ + void setAlignOf(int64_t alignedTo); + enum { Identity = 9 }; diff --git a/kdevplatform/language/duchain/classmemberdeclaration.cpp b/kdevplatform/language/duchain/classmemberdeclaration.cpp --- a/kdevplatform/language/duchain/classmemberdeclaration.cpp +++ b/kdevplatform/language/duchain/classmemberdeclaration.cpp @@ -29,12 +29,15 @@ ClassMemberDeclarationData::ClassMemberDeclarationData() : m_accessPolicy(Declaration::Public) + , m_alignOfExponent(ClassMemberDeclarationData::MaxAlignOfExponent) , m_isStatic(false) , m_isAuto(false) , m_isFriend(false) , m_isRegister(false) , m_isExtern(false) , m_isMutable(false) + , m_sizeOf(-1) + , m_bitOffsetOf(-1) { } @@ -150,4 +153,48 @@ d->m_isExtern = specifiers & ExternSpecifier; d->m_isMutable = specifiers & MutableSpecifier; } + + +int64_t ClassMemberDeclaration::sizeOf() const +{ + return d_func()->m_sizeOf; +} + +void ClassMemberDeclaration::setSizeOf(int64_t sizeOf) +{ + d_func_dynamic()->m_sizeOf = sizeOf; +} + +int64_t ClassMemberDeclaration::bitOffsetOf() const +{ + return d_func()->m_bitOffsetOf; +} + +void ClassMemberDeclaration::setBitOffsetOf(int64_t bitOffsetOf) +{ + d_func_dynamic()->m_bitOffsetOf = bitOffsetOf; +} + +int64_t ClassMemberDeclaration::alignOf() const +{ + if (d_func()->m_alignOfExponent == ClassMemberDeclarationData::MaxAlignOfExponent) { + return -1; + } else { + return 1 << d_func()->m_alignOfExponent; + } +} + +void ClassMemberDeclaration::setAlignOf(int64_t alignedTo) +{ + if (alignedTo <= 0) { + d_func_dynamic()->m_alignOfExponent = ClassMemberDeclarationData::MaxAlignOfExponent; + return; + } + + unsigned int alignOfExponent = 0; + while (alignedTo >>= 1) + alignOfExponent++; + d_func_dynamic()->m_alignOfExponent = alignOfExponent; +} + } diff --git a/kdevplatform/language/duchain/classmemberdeclarationdata.h b/kdevplatform/language/duchain/classmemberdeclarationdata.h --- a/kdevplatform/language/duchain/classmemberdeclarationdata.h +++ b/kdevplatform/language/duchain/classmemberdeclarationdata.h @@ -35,12 +35,26 @@ ClassMemberDeclarationData( const ClassMemberDeclarationData& rhs ) = default; Declaration::AccessPolicy m_accessPolicy; + + /** + * Since alignOf must be integral power of 2, we only need to store the power. + * The max value (63) represents unknown alignment. + */ + unsigned m_alignOfExponent : 6; + static constexpr unsigned MaxAlignOfExponent = 63; + bool m_isStatic: 1; bool m_isAuto: 1; bool m_isFriend: 1; bool m_isRegister: 1; bool m_isExtern: 1; bool m_isMutable: 1; + + /// Stores sizeOf in bytes or -1 if unknown. + int64_t m_sizeOf; + + /// Stores bitOffsetOf in bits or -1 if unknown. + int64_t m_bitOffsetOf; }; } diff --git a/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.h b/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.h --- a/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.h +++ b/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.h @@ -67,6 +67,7 @@ static QString stringFromAccess(const DeclarationPointer& decl); QString declarationName( const DeclarationPointer& decl ) const; static QStringList declarationDetails(const DeclarationPointer& decl); + static QString declarationSizeInformation(const DeclarationPointer& decl); ///This can be used for example to resolve typedefs within the type. ///All types that are visualized in the navigation-context are/should be mangled through this. diff --git a/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp b/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp --- a/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp +++ b/kdevplatform/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp @@ -330,6 +330,10 @@ } } + if(!shorten) { + modifyHtml() += declarationSizeInformation(d->m_declaration); + } + if(!shorten && doc) { modifyHtml() += QLatin1String("

") + i18n("Show documentation for "); makeLink(prettyQualifiedName(d->m_declaration), @@ -784,4 +788,37 @@ return details; } +QString AbstractDeclarationNavigationContext::declarationSizeInformation(const DeclarationPointer& decl) +{ + // Note that ClassMemberDeclaration also includes ClassDeclaration, which uses the sizeOf and alignOf fields, + // but normally leaves the bitOffsetOf unset (-1). + const ClassMemberDeclaration* memberDecl = dynamic_cast(decl.data()); + if (memberDecl && (memberDecl->bitOffsetOf() > 0 || memberDecl->sizeOf() > 0 || memberDecl->alignOf() > 0)) { + QString sizeInfo = "

"; + + if (memberDecl->bitOffsetOf() >= 0) { + const auto byteOffset = memberDecl->bitOffsetOf() / 8; + const auto bitOffset = memberDecl->bitOffsetOf() % 8; + const QString byteOffsetStr = i18np("1 Byte", "%1 Bytes", byteOffset); + const QString bitOffsetStr = bitOffset ? i18np("1 Bit", "%1 Bits", bitOffset) : QString(); + sizeInfo += i18n("offset in parent: %1", bitOffset ? i18nc("%1: bytes, %2: bits", "%1, %2", byteOffsetStr, bitOffsetStr) : byteOffsetStr); + sizeInfo += "; "; + } + + if (memberDecl->sizeOf() >= 0) { + sizeInfo += i18n("size: %1 Bytes", memberDecl->sizeOf()); + sizeInfo += "; "; + } + + if (memberDecl->alignOf() >= 0) { + sizeInfo += i18n("aligned to: %1 Bytes", memberDecl->alignOf()); + } + + sizeInfo += "

"; + + return sizeInfo; + } + return QString(); +} + } diff --git a/plugins/clang/duchain/builder.cpp b/plugins/clang/duchain/builder.cpp --- a/plugins/clang/duchain/builder.cpp +++ b/plugins/clang/duchain/builder.cpp @@ -1032,23 +1032,18 @@ #endif #if CINDEX_VERSION_MINOR >= 30 - if (!jsonTestRun()) { - auto offset = clang_Cursor_getOffsetOfField(cursor); - if (offset >= 0) { // don't add this info to the json tests, it invalidates the comment structure - auto type = clang_getCursorType(cursor); - auto sizeOf = clang_Type_getSizeOf(type); - auto alignedTo = clang_Type_getAlignOf(type); - const auto byteOffset = offset / 8; - const auto bitOffset = offset % 8; - const QString byteOffsetStr = i18np("1 Byte", "%1 Bytes", byteOffset); - const QString bitOffsetStr = bitOffset ? i18np("1 Bit", "%1 Bits", bitOffset) : QString(); - const QString offsetStr = bitOffset ? i18nc("%1: bytes, %2: bits", "%1, %2", byteOffsetStr, bitOffsetStr) : byteOffsetStr; - - decl->setComment(decl->comment() - + i18n("

offset in parent: %1; " - "size: %2 Bytes; " - "aligned to: %3 Bytes

", offsetStr, sizeOf, alignedTo).toUtf8()); - } + auto offset = clang_Cursor_getOffsetOfField(cursor); + if (offset >= 0) { // don't add this info to the json tests, it invalidates the comment structure + auto type = clang_getCursorType(cursor); + auto sizeOf = clang_Type_getSizeOf(type); + auto alignOf = clang_Type_getAlignOf(type); + + if (sizeOf >= 0) + decl->setSizeOf(sizeOf); + if (offset >= 0) + decl->setBitOffsetOf(offset); + if (alignOf >= 0) + decl->setAlignOf(alignOf); } #endif } @@ -1079,16 +1074,17 @@ if (clang_isCursorDefinition(cursor)) { decl->setDeclarationIsDefinition(true); } - if (!jsonTestRun()) { // don't add this info to the json tests, it invalidates the comment structure - auto type = clang_getCursorType(cursor); - auto sizeOf = clang_Type_getSizeOf(type); - auto alignOf = clang_Type_getAlignOf(type); - if (sizeOf >= 0 && alignOf >= 0) { - decl->setComment(decl->comment() - + i18n("

size: %1 Bytes; " - "aligned to: %2 Bytes

", sizeOf, alignOf).toUtf8()); - } - } + +#if CINDEX_VERSION_MINOR >= 30 + auto type = clang_getCursorType(cursor); + auto sizeOf = clang_Type_getSizeOf(type); + auto alignOf = clang_Type_getAlignOf(type); + + if (sizeOf >= 0) + decl->setSizeOf(sizeOf); + if (alignOf >= 0) + decl->setAlignOf(alignOf); +#endif } template