Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
QualTypeNames.h
Go to the documentation of this file.
1//===------- QualTypeNames.cpp - Generate Complete QualType Names ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11// Those directives indirectly includes "clang/AST/Attrs.h" which
12// includes "clang/AST/Attrs.inc".
13// "clang/AST/Attrs.inc", produces some "C4267" warnings specifically
14// on MSVC 2019.
15// This in turn blocks CI integrations for configuration with that
16// compiler that treats warnings as errors.
17// As that header is not under our control, we disable the warning
18// completely when going through those includes.
19#include <QtCore/qcompilerdetection.h>
20
21QT_WARNING_PUSH
22QT_WARNING_DISABLE_MSVC(4267)
23
24#include "clang/AST/DeclTemplate.h"
25#include "clang/AST/DeclarationName.h"
26#include "clang/AST/GlobalDecl.h"
27#include "clang/AST/Mangle.h"
28#include "clang/Basic/Version.h"
29
30QT_WARNING_POP
31
32#include <stdio.h>
33#include <memory>
34
35namespace clang {
36
37namespace TypeName {
38
39inline QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
40 bool WithGlobalNsPrefix);
41
42/// Create a NestedNameSpecifier for Namesp and its enclosing
43/// scopes.
44///
45/// \param[in] Ctx - the AST Context to be used.
46/// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
47/// is requested.
48/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
49/// specifier "::" should be prepended or not.
50static inline NestedNameSpecifier *createNestedNameSpecifier(
51 const ASTContext &Ctx,
52 const NamespaceDecl *Namesp,
53 bool WithGlobalNsPrefix);
54
55/// Create a NestedNameSpecifier for TagDecl and its enclosing
56/// scopes.
57///
58/// \param[in] Ctx - the AST Context to be used.
59/// \param[in] TD - the TagDecl for which a NestedNameSpecifier is
60/// requested.
61/// \param[in] FullyQualify - Convert all template arguments into fully
62/// qualified names.
63/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
64/// specifier "::" should be prepended or not.
65static inline NestedNameSpecifier *createNestedNameSpecifier(
66 const ASTContext &Ctx, const TypeDecl *TD,
67 bool FullyQualify, bool WithGlobalNsPrefix);
68
69static inline NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
70 const ASTContext &Ctx, const Decl *decl,
71 bool FullyQualified, bool WithGlobalNsPrefix);
72
73static inline NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
74 const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
75
76static inline bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
77 TemplateName &TName,
78 bool WithGlobalNsPrefix) {
79 bool Changed = false;
80 NestedNameSpecifier *NNS = nullptr;
81
82 TemplateDecl *ArgTDecl = TName.getAsTemplateDecl();
83 // ArgTDecl won't be NULL because we asserted that this isn't a
84 // dependent context very early in the call chain.
85 assert(ArgTDecl != nullptr);
86 QualifiedTemplateName *QTName = TName.getAsQualifiedTemplateName();
87
88 if (QTName &&
89 !QTName->hasTemplateKeyword() &&
90 (NNS = QTName->getQualifier())) {
91 NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier(
92 Ctx, NNS, WithGlobalNsPrefix);
93 if (QNNS != NNS) {
94 Changed = true;
95 NNS = QNNS;
96 } else {
97 NNS = nullptr;
98 }
99 } else {
100 NNS = createNestedNameSpecifierForScopeOf(
101 Ctx, ArgTDecl, true, WithGlobalNsPrefix);
102 }
103 if (NNS) {
104 TemplateName UnderlyingTN(ArgTDecl);
105 if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl())
106 UnderlyingTN = TemplateName(USD);
107 TName =
108 Ctx.getQualifiedTemplateName(NNS,
109 /*TemplateKeyword=*/false, UnderlyingTN);
110 Changed = true;
111 }
112 return Changed;
113}
114
115static inline bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx,
116 TemplateArgument &Arg,
117 bool WithGlobalNsPrefix) {
118 bool Changed = false;
119
120 // Note: we do not handle TemplateArgument::Expression, to replace it
121 // we need the information for the template instance decl.
122
123 if (Arg.getKind() == TemplateArgument::Template) {
124 TemplateName TName = Arg.getAsTemplate();
125 Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
126 if (Changed) {
127 Arg = TemplateArgument(TName);
128 }
129 } else if (Arg.getKind() == TemplateArgument::Type) {
130 QualType SubTy = Arg.getAsType();
131 // Check if the type needs more desugaring and recurse.
132 QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
133 if (QTFQ != SubTy) {
134 Arg = TemplateArgument(QTFQ);
135 Changed = true;
136 }
137 }
138 return Changed;
139}
140
141static inline const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
142 const Type *TypePtr,
143 bool WithGlobalNsPrefix) {
144 // DependentTemplateTypes exist within template declarations and
145 // definitions. Therefore we shouldn't encounter them at the end of
146 // a translation unit. If we do, the caller has made an error.
147 assert(!isa<DependentTemplateSpecializationType>(TypePtr));
148 // In case of template specializations, iterate over the arguments
149 // and fully qualify them as well.
150 if (const auto *TST = dyn_cast<const TemplateSpecializationType>(TypePtr)) {
151 bool MightHaveChanged = false;
152 SmallVector<TemplateArgument, 4> FQArgs;
153 // Cheap to copy and potentially modified by
154 // getFullyQualifedTemplateArgument.
155 for (TemplateArgument Arg : TST->template_arguments()) {
156 MightHaveChanged |= getFullyQualifiedTemplateArgument(
157 Ctx, Arg, WithGlobalNsPrefix);
158 FQArgs.push_back(Arg);
159 }
160
161 // If a fully qualified arg is different from the unqualified arg,
162 // allocate new type in the AST.
163 if (MightHaveChanged) {
164#if CLANG_VERSION_MAJOR >= 21
165 QualType QT = Ctx.getTemplateSpecializationType(
166 TST->getTemplateName(), FQArgs, /*CanonicalArgs=*/{},
167 TST->getCanonicalTypeInternal());
168#else
169 QualType QT = Ctx.getTemplateSpecializationType(
170 TST->getTemplateName(), FQArgs,
171 TST->getCanonicalTypeInternal());
172#endif
173 // getTemplateSpecializationType returns a fully qualified
174 // version of the specialization itself, so no need to qualify
175 // it.
176 return QT.getTypePtr();
177 }
178 } else if (const auto *TSTRecord = dyn_cast<const RecordType>(TypePtr)) {
179 // We are asked to fully qualify and we have a Record Type,
180 // which can point to a template instantiation with no sugar in any of
181 // its template argument, however we still need to fully qualify them.
182
183 if (const auto *TSTDecl =
184 dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
185 const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs();
186
187 bool MightHaveChanged = false;
188 SmallVector<TemplateArgument, 4> FQArgs;
189 for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
190 // cheap to copy and potentially modified by
191 // getFullyQualifedTemplateArgument
192 TemplateArgument Arg(TemplateArgs[I]);
193 MightHaveChanged |= getFullyQualifiedTemplateArgument(
194 Ctx, Arg, WithGlobalNsPrefix);
195 FQArgs.push_back(Arg);
196 }
197
198 // If a fully qualified arg is different from the unqualified arg,
199 // allocate new type in the AST.
200 if (MightHaveChanged) {
201 TemplateName TN(TSTDecl->getSpecializedTemplate());
202#if CLANG_VERSION_MAJOR >= 21
203 QualType QT = Ctx.getTemplateSpecializationType(
204 TN, FQArgs, /*CanonicalArgs=*/{},
205 TSTRecord->getCanonicalTypeInternal());
206#else
207 QualType QT = Ctx.getTemplateSpecializationType(
208 TN, FQArgs,
209 TSTRecord->getCanonicalTypeInternal());
210#endif
211 // getTemplateSpecializationType returns a fully qualified
212 // version of the specialization itself, so no need to qualify
213 // it.
214 return QT.getTypePtr();
215 }
216 }
217 }
218 return TypePtr;
219}
220
221static inline NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
222 bool FullyQualify,
223 bool WithGlobalNsPrefix) {
224 const DeclContext *DC = D->getDeclContext();
225 if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
226 while (NS && NS->isInline()) {
227 // Ignore inline namespace;
228 NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
229 }
230 if (NS && NS->getDeclName()) {
231 return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
232 }
233 return nullptr; // no starting '::', no anonymous
234 } else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
235 return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
236 } else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
237 return createNestedNameSpecifier(
238 Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
239 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
240 return NestedNameSpecifier::GlobalSpecifier(Ctx);
241 }
242 return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
243}
244
245/// Return a fully qualified version of this name specifier.
246static inline NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
247 const ASTContext &Ctx, NestedNameSpecifier *Scope,
248 bool WithGlobalNsPrefix) {
249 switch (Scope->getKind()) {
250 case NestedNameSpecifier::Global:
251 // Already fully qualified
252 return Scope;
253 case NestedNameSpecifier::Namespace:
255 Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix);
256 case NestedNameSpecifier::NamespaceAlias:
257 // Namespace aliases are only valid for the duration of the
258 // scope where they were introduced, and therefore are often
259 // invalid at the end of the TU. So use the namespace name more
260 // likely to be valid at the end of the TU.
262 Ctx,
263 Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(),
264 WithGlobalNsPrefix);
265 case NestedNameSpecifier::Identifier:
266 // A function or some other construct that makes it un-namable
267 // at the end of the TU. Skip the current component of the name,
268 // but use the name of it's prefix.
270 Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
271 case NestedNameSpecifier::Super:
272 case NestedNameSpecifier::TypeSpec:
273#if CLANG_VERSION_MAJOR < 21
274 case NestedNameSpecifier::TypeSpecWithTemplate:
275#endif
276 {
277 const Type *Type = Scope->getAsType();
278 // Find decl context.
279 const TagDecl *TD = nullptr;
280 if (const TagType *TagDeclType = Type->getAs<TagType>()) {
281 TD = TagDeclType->getDecl();
282 } else {
283 TD = Type->getAsCXXRecordDecl();
284 }
285 if (TD) {
286 return TypeName::createNestedNameSpecifier(Ctx, TD,
287 true /*FullyQualified*/,
288 WithGlobalNsPrefix);
289 } else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
290 return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
291 true /*FullyQualified*/,
292 WithGlobalNsPrefix);
293 }
294 return Scope;
295 }
296 }
297 llvm_unreachable("bad NNS kind");
298}
299
300/// Create a nested name specifier for the declaring context of
301/// the type.
302static inline NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
303 const ASTContext &Ctx, const Decl *Decl,
304 bool FullyQualified, bool WithGlobalNsPrefix) {
305 assert(Decl);
306
307 const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
308 const auto *Outer = dyn_cast<NamedDecl>(DC);
309 const auto *OuterNS = dyn_cast<NamespaceDecl>(DC);
310 if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) {
311 if (OuterNS) {
312 return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
313 } else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
314 return createNestedNameSpecifier(
315 Ctx, TD, FullyQualified, WithGlobalNsPrefix);
316 } else if (isa<TranslationUnitDecl>(Outer)) {
317 // Context is the TU. Nothing needs to be done.
318 return nullptr;
319 } else {
320 // Decl's context was neither the TU, a namespace, nor a
321 // TagDecl, which means it is a type local to a scope, and not
322 // accessible at the end of the TU.
323 return nullptr;
324 }
325 } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
326 return NestedNameSpecifier::GlobalSpecifier(Ctx);
327 }
328 return nullptr;
329}
330
331/// Create a nested name specifier for the declaring context of
332/// the type.
333static inline NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
334 const ASTContext &Ctx, const Type *TypePtr,
335 bool FullyQualified, bool WithGlobalNsPrefix) {
336 if (!TypePtr) return nullptr;
337
338 Decl *Decl = nullptr;
339 // There are probably other cases ...
340 if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
341 Decl = TDT->getDecl();
342 } else if (const auto *TagDeclType = dyn_cast<TagType>(TypePtr)) {
343 Decl = TagDeclType->getDecl();
344 } else if (const auto *TST = dyn_cast<TemplateSpecializationType>(TypePtr)) {
345 Decl = TST->getTemplateName().getAsTemplateDecl();
346 } else {
347 Decl = TypePtr->getAsCXXRecordDecl();
348 }
349
350 if (!Decl) return nullptr;
351
353 Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
354}
355
356inline NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
357 const NamespaceDecl *Namespace,
358 bool WithGlobalNsPrefix) {
359 while (Namespace && Namespace->isInline()) {
360 // Ignore inline namespace;
361 Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
362 }
363 if (!Namespace) return nullptr;
364
365 bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
366 return NestedNameSpecifier::Create(
367 Ctx,
368 createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
369 Namespace);
370}
371
372inline NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
373 const TypeDecl *TD,
374 bool FullyQualify,
375 bool WithGlobalNsPrefix) {
376 const Type *TypePtr = TD->getTypeForDecl();
377 if (isa<const TemplateSpecializationType>(TypePtr) ||
378 isa<const RecordType>(TypePtr)) {
379 // We are asked to fully qualify and we have a Record Type (which
380 // may point to a template specialization) or Template
381 // Specialization Type. We need to fully qualify their arguments.
382
383 TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix);
384 }
385
386 return NestedNameSpecifier::Create(
387 Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
388#if CLANG_VERSION_MAJOR < 21
389 false /*No TemplateKeyword*/,
390#endif
391 TypePtr);
392}
393
394/// Return the fully qualified type, including fully-qualified
395/// versions of any template parameters.
396inline QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
397 bool WithGlobalNsPrefix = false) {
398 // In case of myType* we need to strip the pointer first, fully
399 // qualify and attach the pointer once again.
400 if (isa<PointerType>(QT.getTypePtr())) {
401 // Get the qualifiers.
402 Qualifiers Quals = QT.getQualifiers();
403 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
404 QT = Ctx.getPointerType(QT);
405 // Add back the qualifiers.
406 QT = Ctx.getQualifiedType(QT, Quals);
407 return QT;
408 }
409
410 if (auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) {
411 // Get the qualifiers.
412 Qualifiers Quals = QT.getQualifiers();
413 // Fully qualify the pointee and class types.
414 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
415#if CLANG_VERSION_MAJOR >= 21
416 QT = Ctx.getMemberPointerType(QT, MPT->getQualifier(), MPT->getMostRecentCXXRecordDecl());
417#else
418 QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx,
419 WithGlobalNsPrefix);
420 QT = Ctx.getMemberPointerType(QT, Class.getTypePtr());
421#endif
422 // Add back the qualifiers.
423 QT = Ctx.getQualifiedType(QT, Quals);
424 return QT;
425 }
426
427 // In case of myType& we need to strip the reference first, fully
428 // qualify and attach the reference once again.
429 if (isa<ReferenceType>(QT.getTypePtr())) {
430 // Get the qualifiers.
431 bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
432 Qualifiers Quals = QT.getQualifiers();
433 QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
434 // Add the r- or l-value reference type back to the fully
435 // qualified one.
436 if (IsLValueRefTy)
437 QT = Ctx.getLValueReferenceType(QT);
438 else
439 QT = Ctx.getRValueReferenceType(QT);
440 // Add back the qualifiers.
441 QT = Ctx.getQualifiedType(QT, Quals);
442 return QT;
443 }
444
445 // Remove the part of the type related to the type being a template
446 // parameter (we won't report it as part of the 'type name' and it
447 // is actually make the code below to be more complex (to handle
448 // those)
449 while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
450 // Get the qualifiers.
451 Qualifiers Quals = QT.getQualifiers();
452
453 QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
454
455 // Add back the qualifiers.
456 QT = Ctx.getQualifiedType(QT, Quals);
457 }
458
459 NestedNameSpecifier *Prefix = nullptr;
460 // Local qualifiers are attached to the QualType outside of the
461 // elaborated type. Retrieve them before descending into the
462 // elaborated type.
463 Qualifiers PrefixQualifiers = QT.getLocalQualifiers();
464 QT = QualType(QT.getTypePtr(), 0);
465#if LIBCLANG_VERSION_MAJOR >= 18
466 constexpr ElaboratedTypeKeyword ETK_None = ElaboratedTypeKeyword::None;
467#endif
468 ElaboratedTypeKeyword Keyword = ETK_None;
469 if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
470 QT = ETypeInput->getNamedType();
471 assert(!QT.hasLocalQualifiers());
472 Keyword = ETypeInput->getKeyword();
473 }
474
475 // We don't consider the alias introduced by `using a::X` as a new type.
476 // The qualified name is still a::X.
477 if (const auto *UT = QT->getAs<UsingType>()) {
478 QT = Ctx.getQualifiedType(UT->getUnderlyingType(), PrefixQualifiers);
479 return getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
480 }
481
482 // Create a nested name specifier if needed.
483 Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(),
484 true /*FullyQualified*/,
485 WithGlobalNsPrefix);
486
487 // In case of template specializations iterate over the arguments and
488 // fully qualify them as well.
489 if (isa<const TemplateSpecializationType>(QT.getTypePtr()) ||
490 isa<const RecordType>(QT.getTypePtr())) {
491 // We are asked to fully qualify and we have a Record Type (which
492 // may point to a template specialization) or Template
493 // Specialization Type. We need to fully qualify their arguments.
494
495 const Type *TypePtr = getFullyQualifiedTemplateType(
496 Ctx, QT.getTypePtr(), WithGlobalNsPrefix);
497 QT = QualType(TypePtr, 0);
498 }
499 if (Prefix || Keyword != ETK_None) {
500 QT = Ctx.getElaboratedType(Keyword, Prefix, QT);
501 }
502 QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
503 return QT;
504}
505
506inline std::string getFullyQualifiedName(QualType QT,
507 const ASTContext &Ctx,
508 const PrintingPolicy &Policy,
509 bool WithGlobalNsPrefix = false) {
510 QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
511 return FQQT.getAsString(Policy);
512}
513
514} // end namespace TypeName
515} // end namespace clang
Access
Definition access.h:11
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)
static Location fromCXSourceLocation(CXSourceLocation location)
convert a CXSourceLocation to a qdoc Location
static QString cleanAnonymousTypeName(const QString &typeName)
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_[]
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, const InclusionPolicy &policy)
Building the PCH must be possible when there are no .cpp files, so it is moved here to its own member...
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)
QDocDatabase * qdocDB()
CXChildVisitResult visitFnArg(CXCursor cursor, Node **fnNode, bool &ignoreSignature)
The ClassNode represents a C++ class.
Definition classnode.h:21
void addResolvedBaseClass(Access access, ClassNode *node)
Adds the base class node to this class's list of base classes.
Definition classnode.cpp:27
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...
Definition config.h:85
Definition doc.h:31
const Location & location() const
Returns the starting location of a qdoc comment.
Definition doc.cpp:90
TopicList topicsUsed() const
Returns a reference to the list of topic commands used in the current qdoc comment.
Definition doc.cpp:246
void setFlagsType(TypedefNode *typedefNode)
Definition enumnode.cpp:76
void setAnonymous(bool anonymous)
Definition enumnode.h:41
This node is used to represent any kind of function being documented.
void setConst(bool b)
void setStatic(bool b)
void setVirtualness(Virtualness virtualness)
bool isNonvirtual() const
void setInvokable(bool b)
void setRef(bool b)
void setOverride(bool b)
void setRefRef(bool b)
void markConstexpr()
void markExplicit()
void setMetaness(Metaness metaness)
Parameters & parameters()
The Location class provides a way to mark a location in a file.
Definition location.h:20
void setColumnNo(int no)
Definition location.h:41
void setLineNo(int no)
Definition location.h:40
This class represents a C++ namespace.
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.
void setStatic(bool b)
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.
QString dataType() const
const QString & rightType() const
#define COMMAND_SINCE
Definition codeparser.h:75
#define COMMAND_FN
Definition codeparser.h:26
#define COMMAND_PAGE
Definition codeparser.h:44
#define CONFIG_VERSION
Definition config.h:427
#define CONFIG_DOCUMENTATIONINHEADERS
Definition config.h:361
bool hasTooManyTopics(const Doc &doc)
Checks if there are too many topic commands in doc.
NodeType
Definition genustypes.h:150
This namespace holds QDoc-internal utility methods.
Definition utilities.h:20
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
Definition node.h:46
#define assert
@ Public
Definition access.h:11
@ Private
Definition access.h:11
@ Protected
Definition access.h:11
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.
Definition parsererror.h:13
The Node class is the base class for all the nodes in QDoc's parse tree.
void setGenus(Genus t)
Definition node.h:93
void setAccess(Access t)
Sets the node's access type to t.
Definition node.h:177
bool isNamespace() const
Returns true if the node type is Namespace.
Definition node.h:115
bool isTypedef() const
Returns true if the node type is Typedef.
Definition node.h:133
bool isEnumType() const
Returns true if the node type is Enum.
Definition node.h:100
bool isVariable() const
Returns true if the node type is Variable.
Definition node.h:138
void setLocation(const Location &t)
Sets the node's declaration location, its definition location, or both, depending on the suffix of th...
Definition node.cpp:839
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
Definition node.h:143
virtual void setRelatedNonmember(bool b)
Sets a flag in the node indicating whether this node is a related nonmember of something.
Definition node.h:192
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
Definition node.h:107
bool isClass() const
Returns true if the node type is Class.
Definition node.h:97
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
Definition node.h:150
A class for parsing and managing a function parameter list.
Definition main.cpp:28
Parameter & operator[](int index)
Definition parameters.h:77
void pop_back()
Definition parameters.h:81
void reserve(int count)
Definition parameters.h:73
void clear()
Definition parameters.h:62
Parameter & last()
Definition parameters.h:75
int count() const
Definition parameters.h:72
void setPrivateSignal()
Definition parameters.h:82
CXTranslationUnit tu