File indexing completed on 2024-05-12 05:41:00
0001 /* 0002 SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB a KDAB Group company info@kdab.com 0003 SPDX-FileContributor: Sérgio Martins <sergio.martins@kdab.com> 0004 0005 SPDX-FileCopyrightText: 2015-2016 Sergio Martins <smartins@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "missing-typeinfo.h" 0011 #include "QtUtils.h" 0012 #include "StringUtils.h" 0013 #include "TemplateUtils.h" 0014 #include "TypeUtils.h" 0015 0016 #include <clang/AST/DeclCXX.h> 0017 #include <clang/AST/DeclTemplate.h> 0018 #include <clang/AST/Type.h> 0019 #include <clang/Basic/SourceManager.h> 0020 #include <llvm/ADT/StringRef.h> 0021 0022 class ClazyContext; 0023 namespace clang 0024 { 0025 class Decl; 0026 } // namespace clang 0027 0028 using namespace clang; 0029 0030 /** 0031 * Returns true if the call is on a java-style iterator class. 0032 * Returns if sizeof(T) > sizeof(void*), which would make QList<T> inefficient 0033 */ 0034 inline bool checkTooBigForQList(clang::QualType qt, const clang::ASTContext *context) 0035 { 0036 return (int)context->getTypeSize(qt) <= clazy::sizeOfPointer(context, qt); 0037 } 0038 0039 MissingTypeInfo::MissingTypeInfo(const std::string &name, ClazyContext *context) 0040 : CheckBase(name, context) 0041 { 0042 } 0043 0044 void MissingTypeInfo::VisitDecl(clang::Decl *decl) 0045 { 0046 ClassTemplateSpecializationDecl *tstdecl = clazy::templateDecl(decl); 0047 if (!tstdecl) { 0048 return; 0049 } 0050 0051 const bool isQList = clazy::name(tstdecl) == "QList"; 0052 const bool isQVector = isQList ? false : clazy::name(tstdecl) == "QVector"; 0053 0054 if (!isQList && !isQVector) { 0055 registerQTypeInfo(tstdecl); 0056 return; 0057 } 0058 0059 QualType qt2 = clazy::getTemplateArgumentType(tstdecl, 0); 0060 const Type *t = qt2.getTypePtrOrNull(); 0061 CXXRecordDecl *record = t ? t->getAsCXXRecordDecl() : nullptr; 0062 if (!record || !record->getDefinition() || typeHasClassification(qt2)) { 0063 return; // Don't crash if we only have a fwd decl 0064 } 0065 0066 const bool isCopyable = qt2.isTriviallyCopyableType(m_astContext); 0067 const bool isTooBigForQList = isQList && checkTooBigForQList(qt2, &m_astContext); 0068 0069 if ((isQVector || isTooBigForQList) && isCopyable) { 0070 if (sm().isInSystemHeader(record->getBeginLoc())) { 0071 return; 0072 } 0073 0074 std::string typeName = static_cast<std::string>(clazy::name(record)); 0075 if (typeName == "QPair") { // QPair doesn't use Q_DECLARE_TYPEINFO, but rather a explicit QTypeInfo. 0076 return; 0077 } 0078 0079 emitWarning(decl, "Missing Q_DECLARE_TYPEINFO: " + typeName); 0080 emitWarning(record, "Type declared here:", false); 0081 } 0082 } 0083 0084 void MissingTypeInfo::registerQTypeInfo(ClassTemplateSpecializationDecl *decl) 0085 { 0086 if (clazy::name(decl) == "QTypeInfo") { 0087 const std::string typeName = clazy::getTemplateArgumentTypeStr(decl, 0, lo(), /**recordOnly=*/true); 0088 if (!typeName.empty()) { 0089 m_typeInfos.insert(typeName); 0090 } 0091 } 0092 } 0093 0094 bool MissingTypeInfo::typeHasClassification(QualType qt) const 0095 { 0096 return m_typeInfos.find(clazy::simpleTypeName(qt, lo())) != m_typeInfos.end(); 0097 }