diff options
author | Sergio Martins <smartins@kde.org> | 2017-09-21 22:44:19 +0100 |
---|---|---|
committer | Sergio Martins <smartins@kde.org> | 2017-09-21 22:44:19 +0100 |
commit | ebbb801b92170c4d5651805be3141e4cfd01e689 (patch) | |
tree | 3d63ec197d856474955dc6f1972844cb9b3960a4 /src | |
parent | 200b2ecb4acbd8701905d0b571c6bc3ba9687da7 (diff) | |
parent | b843957a8dd3fc24ecdaae0289d976a08a0e6958 (diff) |
Merge branch '1.2' into master
Diffstat (limited to 'src')
-rw-r--r-- | src/QtUtils.cpp | 25 | ||||
-rw-r--r-- | src/QtUtils.h | 8 | ||||
-rw-r--r-- | src/checks/level1/ctor-missing-parent-argument.cpp | 42 |
3 files changed, 55 insertions, 20 deletions
diff --git a/src/QtUtils.cpp b/src/QtUtils.cpp index eb267bf4..cc889c86 100644 --- a/src/QtUtils.cpp +++ b/src/QtUtils.cpp @@ -323,3 +323,28 @@ CXXMethodDecl *QtUtils::pmfFromUnary(UnaryOperator *uo) return nullptr; } + +bool QtUtils::recordHasCtorWithParam(clang::CXXRecordDecl *record, const std::string ¶mType, bool &ok, int &numCtors) +{ + ok = true; + numCtors = 0; + if (!record || !record->hasDefinition() || + record->getDefinition() != record) { // Means fwd decl + ok = false; + return false; + } + + for (auto ctor : record->ctors()) { + if (ctor->isCopyOrMoveConstructor()) + continue; + numCtors++; + for (auto param : ctor->parameters()) { + QualType qt = TypeUtils::pointeeQualType(param->getType()); + if (!qt.isConstQualified() && TypeUtils::derivesFrom(qt, paramType)) { + return true; + } + } + } + + return false; +} diff --git a/src/QtUtils.h b/src/QtUtils.h index 197a135f..af0fa9bf 100644 --- a/src/QtUtils.h +++ b/src/QtUtils.h @@ -188,6 +188,14 @@ inline clang::ValueDecl *signalReceiverForConnect(clang::CallExpr *call) } /** + * Returns true if a class has a ctor that has a parameter of type paramType. + * ok will be false if an error occurred, or if the record is a fwd declaration, which isn't enough + * for we to find out the signature. + * numCtors will have the number of constructors analyized. + */ +bool recordHasCtorWithParam(clang::CXXRecordDecl *record, const std::string ¶mType, bool &ok, int &numCtors); + +/** * Returns true if we can prove the container doesn't detach. * Returns false otherwise, meaning that you can't conclude anything if false is returned. * diff --git a/src/checks/level1/ctor-missing-parent-argument.cpp b/src/checks/level1/ctor-missing-parent-argument.cpp index f6ffca76..1e80741b 100644 --- a/src/checks/level1/ctor-missing-parent-argument.cpp +++ b/src/checks/level1/ctor-missing-parent-argument.cpp @@ -53,33 +53,35 @@ static string expectedParentTypeFor(CXXRecordDecl *decl) void CtorMissingParentArgument::VisitDecl(Decl *decl) { auto record = dyn_cast<CXXRecordDecl>(decl); - if (!record || !record->hasDefinition() || - record->getDefinition() != record || // Means fwd decl - !QtUtils::isQObject(record)) { + bool ok = false; + + if (!QtUtils::isQObject(record)) + return; + + const bool hasCtors = record->ctor_begin() != record->ctor_end(); + if (!hasCtors) return; - } - bool foundParentArgument = false; const string parentType = expectedParentTypeFor(record); int numCtors = 0; - for (auto ctor : record->ctors()) { - if (ctor->isCopyOrMoveConstructor()) - continue; - - ++numCtors; - for (auto param : ctor->parameters()) { - QualType qt = TypeUtils::pointeeQualType(param->getType()); - if (!qt.isConstQualified() && TypeUtils::derivesFrom(qt, parentType)) { - foundParentArgument = true; - break; - } + const bool hasQObjectParam = QtUtils::recordHasCtorWithParam(record, parentType, /*by-ref*/ok, /*by-ref*/numCtors); + if (!ok) + return; + + if (numCtors > 0 && !hasQObjectParam) { + clang::CXXRecordDecl *baseClass = QtUtils::getQObjectBaseClass(record); + const bool baseHasQObjectParam = QtUtils::recordHasCtorWithParam(baseClass, parentType, /*by-ref*/ok, /*by-ref*/numCtors); + if (ok && !baseHasQObjectParam && sm().isInSystemHeader(baseClass->getLocStart())) { + // If the base class ctors don't accept QObject, and it's declared in a system header don't warn + return; } - } - if (numCtors > 0 && !foundParentArgument) { + if (baseClass->getNameAsString() == "QCoreApplication") + return; + emitWarning(decl, record->getQualifiedNameAsString() + - string(" should take ") + - parentType + string(" parent argument in CTOR")); + string(" should take ") + + parentType + string(" parent argument in CTOR")); } } |