* \a obj is an expression to a type of an QObject (or pointer to) that is the sender or the receiver * \a method is an expression like SIGNAL(....) or SLOT(....) * * This function try to find the matching signal or slot declaration, and register its use. */
| 70 | * This function try to find the matching signal or slot declaration, and register its use. |
| 71 | */ |
| 72 | void QtSupport::handleSignalOrSlot(clang::Expr* obj, clang::Expr* method) |
| 73 | { |
| 74 | if (!obj || !method) return; |
| 75 | obj = obj->IgnoreImpCasts(); |
| 76 | method = method->IgnoreImpCasts(); |
| 77 | auto objType = obj->getType().getTypePtrOrNull(); |
| 78 | if (!objType) return; |
| 79 | |
| 80 | const clang::CXXRecordDecl* objClass = objType->getPointeeCXXRecordDecl(); |
| 81 | if (!objClass) { |
| 82 | // It can be a non-pointer if called like: foo.connect(....); |
| 83 | objClass = objType->getAsCXXRecordDecl(); |
| 84 | if (!objClass) return; |
| 85 | } |
| 86 | |
| 87 | const clang::StringLiteral *methodLiteral = clang::dyn_cast<clang::StringLiteral>(method); |
| 88 | if (!methodLiteral) { |
| 89 | // try qFlagLocation |
| 90 | clang::CallExpr *flagLoc = clang::dyn_cast<clang::CallExpr>(method); |
| 91 | |
| 92 | if (!flagLoc || flagLoc->getNumArgs() != 1 || !flagLoc->getDirectCallee() |
| 93 | || flagLoc->getDirectCallee()->getName() != "qFlagLocation") return; |
| 94 | |
| 95 | |
| 96 | methodLiteral = clang::dyn_cast<clang::StringLiteral>(flagLoc->getArg(0)->IgnoreImpCasts()); |
| 97 | if (!methodLiteral) return; |
| 98 | } |
| 99 | if (methodLiteral->getCharByteWidth() != 1) return; |
| 100 | |
| 101 | |
| 102 | auto signature = methodLiteral->getString().trim(); |
| 103 | if (signature.size() < 4) |
| 104 | return; |
| 105 | |
| 106 | if (signature.find('\0') != signature.npos) { |
| 107 | signature = signature.substr(0, signature.find('\0')).trim(); |
| 108 | } |
| 109 | |
| 110 | auto lParenPos = signature.find('('); |
| 111 | auto rParenPos = signature.find(')'); |
| 112 | if (rParenPos == std::string::npos || rParenPos < lParenPos || lParenPos < 2) |
| 113 | return; |
| 114 | |
| 115 | llvm::StringRef methodName = signature.slice(1 , lParenPos).trim(); |
| 116 | |
| 117 | // Try to find the method which match this name in the given class or bases. |
| 118 | auto candidates = lookUpCandidates(objClass, methodName); |
| 119 | |
| 120 | clang::LangOptions lo; |
| 121 | lo.CPlusPlus = true; |
| 122 | lo.Bool = true; |
| 123 | clang::PrintingPolicy policy(lo); |
| 124 | policy.SuppressScope = true; |
| 125 | |
| 126 | auto argPos = lParenPos + 1; |
| 127 | unsigned int arg = 0; |
| 128 | while (argPos < signature.size() && !candidates.empty()) { |
| 129 |
nothing calls this directly
no test coverage detected