19#include <QtCore/qcompilerdetection.h>
22QT_WARNING_DISABLE_MSVC(4267)
24#include "clang/AST/DeclTemplate.h"
25#include "clang/AST/DeclarationName.h"
26#include "clang/AST/GlobalDecl.h"
27#include "clang/AST/Mangle.h"
39 bool WithGlobalNsPrefix);
50 const ASTContext &Ctx,
51 const NamespaceDecl *Namesp,
52 bool WithGlobalNsPrefix);
65 const ASTContext &Ctx,
const TypeDecl *TD,
66 bool FullyQualify,
bool WithGlobalNsPrefix);
69 const ASTContext &Ctx,
const Decl *decl,
70 bool FullyQualified,
bool WithGlobalNsPrefix);
73 const ASTContext &Ctx, NestedNameSpecifier *scope,
bool WithGlobalNsPrefix);
77 bool WithGlobalNsPrefix) {
79 NestedNameSpecifier *NNS =
nullptr;
81 TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
84 assert(ArgTDecl !=
nullptr);
85 QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName();
88 !QTName->hasTemplateKeyword() &&
89 (NNS = QTName->getQualifier())) {
91 Ctx
, NNS
, WithGlobalNsPrefix
);
99 NNS = createNestedNameSpecifierForScopeOf(
100 Ctx, ArgTDecl,
true, WithGlobalNsPrefix);
103 TemplateName UnderlyingTN(ArgTDecl);
104 if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl())
105 UnderlyingTN = TemplateName(USD);
107 Ctx.getQualifiedTemplateName(NNS,
108 false, UnderlyingTN);
115 TemplateArgument &Arg,
116 bool WithGlobalNsPrefix) {
117 bool Changed =
false;
122 if (Arg.getKind() == TemplateArgument::Template) {
123 TemplateName TName = Arg.getAsTemplate();
126 Arg = TemplateArgument(TName);
128 }
else if (Arg.getKind() == TemplateArgument::Type) {
129 QualType SubTy = Arg.getAsType();
133 Arg = TemplateArgument(QTFQ);
142 bool WithGlobalNsPrefix) {
146 assert(!isa<DependentTemplateSpecializationType>(TypePtr));
149 if (
const auto *TST = dyn_cast<
const TemplateSpecializationType>(TypePtr)) {
150 bool MightHaveChanged =
false;
151 SmallVector<TemplateArgument, 4> FQArgs;
154 for (TemplateArgument Arg : TST->template_arguments()) {
155 MightHaveChanged |= getFullyQualifiedTemplateArgument(
156 Ctx, Arg, WithGlobalNsPrefix);
157 FQArgs.push_back(Arg);
162 if (MightHaveChanged) {
163 QualType QT = Ctx.getTemplateSpecializationType(
164 TST->getTemplateName(), FQArgs,
165 TST->getCanonicalTypeInternal());
169 return QT.getTypePtr();
171 }
else if (
const auto *TSTRecord = dyn_cast<
const RecordType>(TypePtr)) {
176 if (
const auto *TSTDecl =
177 dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
178 const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
180 bool MightHaveChanged =
false;
181 SmallVector<TemplateArgument, 4> FQArgs;
182 for (
unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
185 TemplateArgument Arg(TemplateArgs[I]);
187 Ctx
, Arg
, WithGlobalNsPrefix
);
188 FQArgs.push_back(Arg);
193 if (MightHaveChanged) {
194 TemplateName TN(TSTDecl->getSpecializedTemplate());
195 QualType QT = Ctx.getTemplateSpecializationType(
197 TSTRecord->getCanonicalTypeInternal());
201 return QT.getTypePtr();
208static inline NestedNameSpecifier *
createOuterNNS(
const ASTContext &Ctx,
const Decl *D,
210 bool WithGlobalNsPrefix) {
211 const DeclContext *DC = D->getDeclContext();
212 if (
const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
213 while (NS && NS->isInline()) {
215 NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
217 if (NS && NS->getDeclName()) {
218 return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
221 }
else if (
const auto *TD = dyn_cast<TagDecl>(DC)) {
222 return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
223 }
else if (
const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
224 return createNestedNameSpecifier(
225 Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
226 }
else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
227 return NestedNameSpecifier::GlobalSpecifier(Ctx);
234 const ASTContext &Ctx, NestedNameSpecifier *Scope,
235 bool WithGlobalNsPrefix) {
236 switch (Scope->getKind()) {
237 case NestedNameSpecifier::Global:
240 case NestedNameSpecifier::Namespace:
242 Ctx
, Scope->getAsNamespace()
, WithGlobalNsPrefix
);
243 case NestedNameSpecifier::NamespaceAlias:
250 Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl()
,
252 case NestedNameSpecifier::Identifier:
257 Ctx
, Scope->getPrefix()
, WithGlobalNsPrefix
);
258 case NestedNameSpecifier::Super:
259 case NestedNameSpecifier::TypeSpec:
260 case NestedNameSpecifier::TypeSpecWithTemplate: {
261 const Type *Type = Scope->getAsType();
263 const TagDecl *TD =
nullptr;
264 if (
const TagType *TagDeclType = Type->getAs<TagType>()) {
265 TD = TagDeclType->getDecl();
267 TD = Type->getAsCXXRecordDecl();
270 return TypeName::createNestedNameSpecifier(Ctx, TD,
273 }
else if (
const auto *TDD = dyn_cast<TypedefType>(Type)) {
274 return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
281 llvm_unreachable(
"bad NNS kind");
287 const ASTContext &Ctx,
const Decl *Decl,
288 bool FullyQualified,
bool WithGlobalNsPrefix) {
291 const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
292 const auto *Outer = dyn_cast<NamedDecl>(DC);
293 const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
294 if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
296 return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
297 }
else if (
const auto *TD = dyn_cast<TagDecl>(Outer)) {
298 return createNestedNameSpecifier(
299 Ctx, TD, FullyQualified, WithGlobalNsPrefix);
300 }
else if (isa<TranslationUnitDecl>(Outer)) {
309 }
else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
310 return NestedNameSpecifier::GlobalSpecifier(Ctx);
318 const ASTContext &Ctx,
const Type *TypePtr,
319 bool FullyQualified,
bool WithGlobalNsPrefix) {
320 if (!TypePtr)
return nullptr;
322 Decl *Decl =
nullptr;
324 if (
const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
325 Decl = TDT->getDecl();
326 }
else if (
const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
327 Decl = TagDeclType->getDecl();
328 }
else if (
const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
329 Decl = TST->getTemplateName().getAsTemplateDecl();
331 Decl = TypePtr->getAsCXXRecordDecl();
334 if (!Decl)
return nullptr;
337 Ctx
, Decl
, FullyQualified
, WithGlobalNsPrefix
);
341 const NamespaceDecl *Namespace,
342 bool WithGlobalNsPrefix) {
343 while (Namespace && Namespace->isInline()) {
345 Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
347 if (!Namespace)
return nullptr;
349 bool FullyQualified =
true;
350 return NestedNameSpecifier::Create(
352 createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
359 bool WithGlobalNsPrefix) {
360 const Type *TypePtr = TD->getTypeForDecl();
361 if (isa<
const TemplateSpecializationType>(TypePtr) ||
362 isa<
const RecordType>(TypePtr)) {
370 return NestedNameSpecifier::Create(
371 Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
378 bool WithGlobalNsPrefix =
false) {
381 if (isa<PointerType>(QT.getTypePtr())) {
383 Qualifiers Quals = QT.getQualifiers();
385 QT = Ctx.getPointerType(QT);
387 QT = Ctx.getQualifiedType(QT, Quals);
391 if (
auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) {
393 Qualifiers Quals = QT.getQualifiers();
398 QT = Ctx.getMemberPointerType(QT, Class.getTypePtr());
400 QT = Ctx.getQualifiedType(QT, Quals);
406 if (isa<ReferenceType>(QT.getTypePtr())) {
408 bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
409 Qualifiers Quals = QT.getQualifiers();
414 QT = Ctx.getLValueReferenceType(QT);
416 QT = Ctx.getRValueReferenceType(QT);
418 QT = Ctx.getQualifiedType(QT, Quals);
426 while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
428 Qualifiers Quals = QT.getQualifiers();
430 QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
433 QT = Ctx.getQualifiedType(QT, Quals);
436 NestedNameSpecifier *Prefix =
nullptr;
440 Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
441 QT = QualType(QT.getTypePtr(), 0);
442#if LIBCLANG_VERSION_MAJOR >= 18
443 constexpr ElaboratedTypeKeyword ETK_None = ElaboratedTypeKeyword::None;
445 ElaboratedTypeKeyword Keyword = ETK_None;
446 if (
const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
447 QT = ETypeInput->getNamedType();
448 assert(!QT.hasLocalQualifiers());
449 Keyword = ETypeInput->getKeyword();
454 if (
const auto *UT = QT->getAs<UsingType>()) {
455 QT = Ctx.getQualifiedType(UT->getUnderlyingType(), PrefixQualifiers);
466 if (isa<
const TemplateSpecializationType>(QT.getTypePtr()) ||
467 isa<
const RecordType>(QT.getTypePtr())) {
473 Ctx
, QT.getTypePtr()
, WithGlobalNsPrefix
);
474 QT = QualType(TypePtr, 0);
476 if (Prefix || Keyword != ETK_None) {
477 QT = Ctx.getElaboratedType(Keyword, Prefix, QT);
479 QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
484 const ASTContext &Ctx,
485 const PrintingPolicy &Policy,
486 bool WithGlobalNsPrefix =
false) {
488 return FQQT.getAsString(Policy);
static const clang::Decl * get_cursor_declaration(CXCursor cursor)
Returns the underlying Decl that cursor represents.
static QString reconstructQualifiedPathForCursor(CXCursor cur)
Reconstruct the qualified path name of a function that is being overridden.
QString functionName(CXCursor cursor)
Returns the function name from a given cursor representing a function declaration.
static std::string get_default_value_initializer_as_string(const clang::TemplateTemplateParmDecl *parameter)
static QString fromCXString(CXString &&string)
convert a CXString to a QString, and dispose the CXString
static QDebug operator<<(QDebug debug, const std::vector< T > &v)
static QString getSpelling(CXSourceRange range)
static void setOverridesForFunction(FunctionNode *fn, CXCursor cursor)
static QList< QByteArray > includePathsFromHeaders(const std::set< Config::HeaderFilePath > &allHeaders)
static const auto kClangDontDisplayDiagnostics
void getMoreArgs(const std::vector< QByteArray > &include_paths, const std::set< Config::HeaderFilePath > &all_headers, std::vector< const char * > &args)
Load the include paths into moreArgs.
static std::string get_default_value_initializer_as_string(const clang::ParmVarDecl *parameter)
void getDefaultArgs(const QList< QByteArray > &defines, std::vector< const char * > &args)
Load the default arguments and the defines into args.
static std::string get_expression_as_string(const clang::Expr *expression, const clang::ASTContext &declaration_context)
bool visitChildrenLambda(CXCursor cursor, T &&lambda)
Call clang_visitChildren on the given cursor with the lambda as a callback T can be any functor that ...
static std::string get_default_value_initializer_as_string(const clang::NamedDecl *declaration)
static RelaxedTemplateDeclaration get_template_declaration(const clang::TemplateDecl *template_declaration)
static std::string get_default_value_initializer_as_string(const clang::NonTypeTemplateParmDecl *parameter)
static QString fromCache(const QByteArray &cache, unsigned int offset1, unsigned int offset2)
static float getUnpatchedVersion(QString t)
std::optional< PCHFile > buildPCH(QDocDatabase *qdb, QString module_header, const std::set< Config::HeaderFilePath > &all_headers, const std::vector< QByteArray > &include_paths, const QList< QByteArray > &defines)
Building the PCH must be possible when there are no .cpp files, so it is moved here to its own member...
static Location fromCXSourceLocation(CXSourceLocation location)
convert a CXSourceLocation to a qdoc Location
static Access fromCX_CXXAccessSpecifier(CX_CXXAccessSpecifier spec)
convert a CX_CXXAccessSpecifier to Node::Access
static std::string get_default_value_initializer_as_string(const clang::TemplateTypeParmDecl *parameter)
constexpr const char fnDummyFileName[]
static CXTranslationUnit_Flags flags_
static Node * findNodeForCursor(QDocDatabase *qdb, CXCursor cur)
Find the node from the QDocDatabase qdb that corresponds to the declaration represented by the cursor...
static std::string get_fully_qualified_type_name(clang::QualType type, const clang::ASTContext &declaration_context)
Returns a string representing the name of type as if it was referred to at the end of the translation...
static void printDiagnostics(const CXTranslationUnit &translationUnit)
static const char * defaultArgs_[]
static QString readFile(CXFile cxFile, unsigned int offset1, unsigned int offset2)
void addChild(Node *child)
Adds the child to this node's child list and sets the child's parent pointer to this Aggregate.
ParsedCppFileIR parse_cpp_file(const QString &filePath)
Get ready to parse the C++ cpp file identified by filePath and add its parsed contents to the databas...
ClangCodeParser(QDocDatabase *qdb, Config &, const std::vector< QByteArray > &include_paths, const QList< QByteArray > &defines, std::optional< std::reference_wrapper< const PCHFile > > pch)
ClangVisitor(QDocDatabase *qdb, const std::set< Config::HeaderFilePath > &allHeaders)
Node * nodeForCommentAtLocation(CXSourceLocation loc, CXSourceLocation nextCommentLoc)
Given a comment at location loc, return a Node for this comment nextCommentLoc is the location of the...
CXChildVisitResult visitChildren(CXCursor cursor)
CXChildVisitResult visitFnArg(CXCursor cursor, Node **fnNode, bool &ignoreSignature)
The ClassNode represents a C++ class.
void addResolvedBaseClass(Access access, ClassNode *node)
Adds the base class node to this class's list of base classes.
static bool isWorthWarningAbout(const Doc &doc)
Test for whether a doc comment warrants warnings.
The Config class contains the configuration variables for controlling how qdoc produces documentation...
const Location & location() const
Returns the starting location of a qdoc comment.
TopicList topicsUsed() const
Returns a reference to the list of topic commands used in the current qdoc comment.
void setFlagsType(TypedefNode *typedefNode)
This node is used to represent any kind of function being documented.
void setVirtualness(Virtualness virtualness)
bool isNonvirtual() const
void setInvokable(bool b)
void setMetaness(Metaness metaness)
Parameters & parameters()
The Location class provides a way to mark a location in a file.
This class represents a C++ namespace.
void setAccess(Access t)
Sets the node's access type to t.
NodeType
An unsigned char value that identifies an object as a particular subclass of Node.
bool isNamespace() const
Returns true if the node type is Namespace.
bool isTypedef() const
Returns true if the node type is Typedef.
bool isFunction(Genus g=DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isEnumType() const
Returns true if the node type is Enum.
bool isVariable() const
Returns true if the node type is Variable.
void setLocation(const Location &t)
Sets the node's declaration location, its definition location, or both, depending on the suffix of th...
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
virtual void setRelatedNonmember(bool b)
Sets a flag in the node indicating whether this node is a related nonmember of something.
bool isClass() const
Returns true if the node type is Class.
LinkType
An unsigned char value that probably should be moved out of the Node base class.
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
A class for parsing and managing a function parameter list.
Parameter & operator[](int index)
This class describes one instance of using the Q_PROPERTY macro.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
NamespaceNode * primaryTreeRoot()
Returns a pointer to the root node of the primary tree.
const QString & leftType() const
Node * clone(Aggregate *parent) override
Clone this node on the heap and make the clone a child of parent.
bool isStatic() const override
Returns true if the FunctionNode represents a static function.
const QString & rightType() const
bool hasTooManyTopics(const Doc &doc)
Checks if there are too many topic commands in doc.
Combined button and popup list for selecting options.
static NestedNameSpecifier * createOuterNNS(const ASTContext &Ctx, const Decl *D, bool FullyQualify, bool WithGlobalNsPrefix)
QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix)
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, TemplateName &TName, bool WithGlobalNsPrefix)
static const Type * getFullyQualifiedTemplateType(const ASTContext &Ctx, const Type *TypePtr, bool WithGlobalNsPrefix)
static NestedNameSpecifier * createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Type *TypePtr, bool FullyQualified, bool WithGlobalNsPrefix)
static NestedNameSpecifier * createNestedNameSpecifier(const ASTContext &Ctx, const TypeDecl *TD, bool FullyQualify, bool WithGlobalNsPrefix)
static NestedNameSpecifier * createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *decl, bool FullyQualified, bool WithGlobalNsPrefix)
static NestedNameSpecifier * getFullyQualifiedNestedNameSpecifier(const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix)
Return a fully qualified version of this name specifier.
static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, TemplateArgument &Arg, bool WithGlobalNsPrefix)
std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, const PrintingPolicy &Policy, bool WithGlobalNsPrefix=false)
static NestedNameSpecifier * createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp, bool WithGlobalNsPrefix)
QList< Node * > NodeVector
Returns the spelling in the file for a source range.
std::variant< Node *, FnMatchError > operator()(const Location &location, const QString &fnSignature, const QString &idTag, QStringList context)
Use clang to parse the function signature from a function command.
Encapsulates information about.
operator CXTranslationUnit()