diff options
author | Luca Di Sera <luca.disera@qt.io> | 2023-01-13 13:12:21 +0100 |
---|---|---|
committer | Luca Di Sera <luca.disera@qt.io> | 2023-01-26 14:40:28 +0100 |
commit | cd66158a60306850b39ba36486adefdea44a4b05 (patch) | |
tree | 6867bfd9d6120939bbfa9ceadd4be2a64cbb0a48 /src/qdoc/clangcodeparser.cpp | |
parent | e7a5008b856b36dc504745e1325c13e8e62ce0c1 (diff) | |
download | qttools-cd66158a60306850b39ba36486adefdea44a4b05.tar.gz |
QDoc: Use clang's C++ API to recognize copy/move constructors
QDoc uses clang's C API, LibClang, to parse the source code of C++
projects, so as to be able to extract the user-written documentation and
provide certain guarantees about its correctness.
When QDoc encounters a copy or move constructors, it marks its internal
representation of the element with this information, which is later used
to organize, order and render the documentation for the element.
As LibClang does not provide first party support for extracting
this information, a manual way to retrieve the information based on the
spelling of the argument of the processed constructors was performed.
This implementation was historically bugged.
As it did not follow the specification for copy/move constructors it was
able to recognize many false positives and unable to recognize certain
copy/move constructors.
Recent changes have solved some of the bugs that were acting as blocker
for other features but the implementation was left bugged as a
by-specification recognizer would have required a relative huge amount
of bug-prone work.
To solve the issue a series of patches were pushed upstream to LLVM,
exposing the required functionality of the C++ API to LibClang, which
was expected to be available with version 16, with the intention of
holding a fix until the upgrade to that new version was available.
Recent changes to QDoc allows us to turn to clang's C++ API, which is more
complete, on the spot from a LibClang's cursor thus not requiring any
more waiting time to solve the bugged implementation.
Hence, the detection method for copy/move constructors was revamped in
term of the C++ API, resolving the above mentioned issues.
`ClangCodeParser::processFunction` is the method that generally takes
care of extracting this form of information, enriching a `FunctionNode`,
the internal representation for documentable elements that are callable,
with the retrieved information.
`ClangCodeParser::processFunction` would perform ad-hoc checks based on
the spelling of the arguments of a processed cursor that was a
constructor.
The ad-hoc checks are thus removed, in favor of calling the
`CXXConstructorDecl::isCopyConstructor` and
`CXXConstructorDecl::isMoveConstructor` methods.
Certain constructors in the generated documentation may now be
re-ordered or marked differently in the output documentation if they
were incorrectly recognized or not recognized as copy/move constructors.
Change-Id: Id4e88cfa682b13899dd42af9c952f1316849dfee
Reviewed-by: Topi Reiniƶ <topi.reinio@qt.io>
Diffstat (limited to 'src/qdoc/clangcodeparser.cpp')
-rw-r--r-- | src/qdoc/clangcodeparser.cpp | 39 |
1 files changed, 5 insertions, 34 deletions
diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index eb11e7994..0681fe6a4 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -967,6 +967,10 @@ void ClangVisitor::processFunction(FunctionNode *fn, CXCursor cursor) assert(function_declaration); const clang::CXXConstructorDecl* constructor_declaration = llvm::dyn_cast<const clang::CXXConstructorDecl>(function_declaration); + + if (constructor_declaration && constructor_declaration->isCopyConstructor()) fn->setMetaness(FunctionNode::CCtor); + else if (constructor_declaration && constructor_declaration->isMoveConstructor()) fn->setMetaness(FunctionNode::MCtor); + const clang::CXXConversionDecl* conversion_declaration = llvm::dyn_cast<const clang::CXXConversionDecl>(function_declaration); if (function_declaration->isConstexpr()) fn->markConstexpr(); @@ -1035,40 +1039,7 @@ void ClangVisitor::processFunction(FunctionNode *fn, CXCursor cursor) // for QDoc should be updated. for (int i = 0; i < numArg; ++i) { CXType argType = clang_getArgType(funcType, i); - if (fn->isCtor()) { - // TODO:KLUDGE: [temporary-hack] - // The following is used to fix a very specific bug in the - // way QDoc assigns the metaness of constructors. - // It is nonetheless quite imperfect in its handling and - // is only used as a temporary fix while LLVM 16 is not - // available. - // - // This is expected to be removed as soon as LLVM 16 comes out. - static auto remove_qualifiers = [](QString type_spelling) { - // REMARK: While, generally, a type with - // both qualifiers would be written "const volatile - // T", clang accepts "volatile const T" too. - // - // Nonetheless, we do not handle that case as - // libclang, when providing the spelling, currently - // always writes the const-qualifier before the - // volatile-qualifier. - if (type_spelling.startsWith("const ")) - type_spelling.remove(0, QString("const ").size()); - - if (type_spelling.startsWith("volatile ")) - type_spelling.remove(0, QString("volatile ").size()); - - return type_spelling; - }; - - const QString type_spelling{remove_qualifiers(fromCXString(clang_getTypeSpelling(clang_getPointeeType(argType))))}; - if (type_spelling == fn->name()) { - if (argType.kind == CXType_RValueReference) fn->setMetaness(FunctionNode::MCtor); - else if (argType.kind == CXType_LValueReference) fn->setMetaness(FunctionNode::CCtor); - } - - } else if ((kind == CXCursor_CXXMethod) && (fn->name() == QLatin1String("operator="))) { + if ((kind == CXCursor_CXXMethod) && (fn->name() == QLatin1String("operator="))) { if (argType.kind == CXType_RValueReference) fn->setMetaness(FunctionNode::MAssign); else if (argType.kind == CXType_LValueReference) |