aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSergio Martins <smartins@kde.org>2017-09-21 22:44:19 +0100
committerSergio Martins <smartins@kde.org>2017-09-21 22:44:19 +0100
commitebbb801b92170c4d5651805be3141e4cfd01e689 (patch)
tree3d63ec197d856474955dc6f1972844cb9b3960a4 /src
parent200b2ecb4acbd8701905d0b571c6bc3ba9687da7 (diff)
parentb843957a8dd3fc24ecdaae0289d976a08a0e6958 (diff)
Merge branch '1.2' into master
Diffstat (limited to 'src')
-rw-r--r--src/QtUtils.cpp25
-rw-r--r--src/QtUtils.h8
-rw-r--r--src/checks/level1/ctor-missing-parent-argument.cpp42
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 &paramType, 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 &paramType, 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"));
}
}