From c25a564e5adc195b3577f03a376d4777a0255602 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Thu, 21 Sep 2017 18:44:06 +0100 Subject: Refactor into QtUtils::recordHasCtorWithParam So code can be shared --- src/QtUtils.cpp | 25 ++++++++++++++++ src/QtUtils.h | 8 +++++ src/checks/level1/ctor-missing-parent-argument.cpp | 34 +++++++++------------- 3 files changed, 46 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/QtUtils.cpp b/src/QtUtils.cpp index 6bda1eb0..37e0f980 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 dfcc18ce..54651545 100644 --- a/src/QtUtils.h +++ b/src/QtUtils.h @@ -186,6 +186,14 @@ inline clang::ValueDecl *signalReceiverForConnect(clang::CallExpr *call) return FunctionUtils::valueDeclForCallArgument(call, 3); } +/** + * 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..20571f01 100644 --- a/src/checks/level1/ctor-missing-parent-argument.cpp +++ b/src/checks/level1/ctor-missing-parent-argument.cpp @@ -53,33 +53,25 @@ static string expectedParentTypeFor(CXXRecordDecl *decl) void CtorMissingParentArgument::VisitDecl(Decl *decl) { auto record = dyn_cast(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 && !foundParentArgument) { + if (numCtors > 0 && !hasQObjectParam) { emitWarning(decl, record->getQualifiedNameAsString() + - string(" should take ") + - parentType + string(" parent argument in CTOR")); + string(" should take ") + + parentType + string(" parent argument in CTOR")); } } -- cgit v1.2.3 From b843957a8dd3fc24ecdaae0289d976a08a0e6958 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Thu, 21 Sep 2017 22:42:51 +0100 Subject: ctor-missing-parent-argument: Don't warn when base class is in system header and doesn't accept any QObject in any ctor. BUG: 384926 --- src/checks/level1/ctor-missing-parent-argument.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/checks/level1/ctor-missing-parent-argument.cpp b/src/checks/level1/ctor-missing-parent-argument.cpp index 20571f01..1e80741b 100644 --- a/src/checks/level1/ctor-missing-parent-argument.cpp +++ b/src/checks/level1/ctor-missing-parent-argument.cpp @@ -69,6 +69,16 @@ void CtorMissingParentArgument::VisitDecl(Decl *decl) 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 (baseClass->getNameAsString() == "QCoreApplication") + return; + emitWarning(decl, record->getQualifiedNameAsString() + string(" should take ") + parentType + string(" parent argument in CTOR")); -- cgit v1.2.3