clang 22.0.0git
DeclarationFragments.cpp
Go to the documentation of this file.
1//===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
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/// \file
10/// This file implements Declaration Fragments related classes.
11///
12//===----------------------------------------------------------------------===//
13
15#include "clang/AST/ASTFwd.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclCXX.h"
20#include "clang/AST/Type.h"
21#include "clang/AST/TypeLoc.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/raw_ostream.h"
27#include <optional>
28
29using namespace clang::extractapi;
30using namespace llvm;
31
32namespace {
33
34void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
36 clang::FunctionProtoTypeLoc &BlockProto) {
37 if (!TSInfo)
38 return;
39
41 while (true) {
42 // Look through qualified types
43 if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
44 TL = QualifiedTL.getUnqualifiedLoc();
45 continue;
46 }
47
48 if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
49 TL = AttrTL.getModifiedLoc();
50 continue;
51 }
52
53 // Try to get the function prototype behind the block pointer type,
54 // then we're done.
55 if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
56 TL = BlockPtr.getPointeeLoc().IgnoreParens();
58 BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
59 }
60 break;
61 }
62}
63
64} // namespace
65
67DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
68 if (!Fragments.empty()) {
69 Fragment &Last = Fragments.back();
70 if (Last.Kind == FragmentKind::Text) {
71 // Merge the extra space into the last fragment if the last fragment is
72 // also text.
73 if (Last.Spelling.back() != Character) { // avoid duplicates at end
74 Last.Spelling.push_back(Character);
75 }
76 } else {
78 Fragments.back().Spelling.push_back(Character);
79 }
80 }
81
82 return *this;
83}
84
86 return appendUnduplicatedTextCharacter(' ');
87}
88
90 return appendUnduplicatedTextCharacter(';');
91}
92
94 if (Fragments.empty())
95 return *this;
96
97 Fragment &Last = Fragments.back();
98 if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
99 Last.Spelling.pop_back();
100
101 return *this;
102}
103
106 switch (Kind) {
108 return "none";
110 return "keyword";
112 return "attribute";
114 return "number";
116 return "string";
118 return "identifier";
120 return "typeIdentifier";
122 return "genericParameter";
124 return "externalParam";
126 return "internalParam";
128 return "text";
129 }
130
131 llvm_unreachable("Unhandled FragmentKind");
132}
133
136 return llvm::StringSwitch<FragmentKind>(S)
142 .Case("typeIdentifier",
144 .Case("genericParameter",
150}
151
153 ExceptionSpecificationType ExceptionSpec) {
154 DeclarationFragments Fragments;
155 switch (ExceptionSpec) {
157 return Fragments;
164 // FIXME: throw(int), get types of inner expression
165 return Fragments;
170 // FIXME: throw(conditional-expression), get expression
171 break;
184 default:
185 return Fragments;
186 }
187
188 llvm_unreachable("Unhandled exception specification");
189}
190
193 DeclarationFragments Fragments;
194 if (Record->isStruct())
196 else if (Record->isUnion())
198 else
200
201 return Fragments;
202}
203
204// NNS stores C++ nested name specifiers, which are prefixes to qualified names.
205// Build declaration fragments for NNS recursively so that we have the USR for
206// every part in a qualified name, and also leaves the actual underlying type
207// cleaner for its own fragment.
208DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNNS(
210 DeclarationFragments Fragments;
211 switch (NNS.getKind()) {
213 return Fragments;
214
216 auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix();
217 Fragments.append(getFragmentsForNNS(Prefix, Context, After));
218 if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace);
219 NS && NS->isAnonymousNamespace())
220 return Fragments;
222 index::generateUSRForDecl(Namespace, USR);
223 Fragments.append(Namespace->getName(),
225 Namespace);
226 break;
227 }
228
230 // The global specifier `::` at the beginning. No stored value.
231 break;
232
234 // Microsoft's `__super` specifier.
236 break;
237
239 // FIXME: Handle C++ template specialization type
240 Fragments.append(getFragmentsForType(NNS.getAsType(), Context, After));
241 break;
242 }
243 }
244
245 // Add the separator text `::` for this segment.
246 return Fragments.append("::", DeclarationFragments::FragmentKind::Text);
247}
248
249// Recursively build the declaration fragments for an underlying `Type` with
250// qualifiers removed.
251DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
252 const Type *T, ASTContext &Context, DeclarationFragments &After) {
253 assert(T && "invalid type");
254
255 DeclarationFragments Fragments;
256
257 if (const MacroQualifiedType *MQT = dyn_cast<MacroQualifiedType>(T)) {
258 Fragments.append(
259 getFragmentsForType(MQT->getUnderlyingType(), Context, After));
260 return Fragments;
261 }
262
263 if (const AttributedType *AT = dyn_cast<AttributedType>(T)) {
264 // FIXME: Serialize Attributes correctly
265 Fragments.append(
266 getFragmentsForType(AT->getModifiedType(), Context, After));
267 return Fragments;
268 }
269
270 // If the type is a typedefed type, get the underlying TypedefNameDecl for a
271 // direct reference to the typedef instead of the wrapped type.
272
273 // 'id' type is a typedef for an ObjCObjectPointerType
274 // we treat it as a typedef
275 if (const TypedefType *TypedefTy = dyn_cast<TypedefType>(T)) {
276 const TypedefNameDecl *Decl = TypedefTy->getDecl();
277 TypedefUnderlyingTypeResolver TypedefResolver(Context);
278 std::string USR = TypedefResolver.getUSRForType(QualType(T, 0));
279
280 if (ElaboratedTypeKeyword Keyword = TypedefTy->getKeyword();
282 Fragments
285 .appendSpace();
286 }
287
288 Fragments.append(
289 getFragmentsForNNS(TypedefTy->getQualifier(), Context, After));
290
291 if (TypedefTy->isObjCIdType()) {
292 return Fragments.append(Decl->getName(),
294 }
295
296 return Fragments.append(
298 USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0)));
299 }
300
301 // Declaration fragments of a pointer type is the declaration fragments of
302 // the pointee type followed by a `*`,
303 if (T->isPointerType() && !T->isFunctionPointerType()) {
304 QualType PointeeT = T->getPointeeType();
305 Fragments.append(getFragmentsForType(PointeeT, Context, After));
306 // If the pointee is itself a pointer, we do not want to insert a space
307 // before the `*` as the preceding character in the type name is a `*`.
308 if (!PointeeT->isAnyPointerType())
309 Fragments.appendSpace();
311 }
312
313 // For Objective-C `id` and `Class` pointers
314 // we do not spell out the `*`.
315 if (T->isObjCObjectPointerType() &&
317
318 Fragments.append(getFragmentsForType(T->getPointeeType(), Context, After));
319
320 // id<protocol> is an qualified id type
321 // id<protocol>* is not an qualified id type
324 }
325
326 return Fragments;
327 }
328
329 // Declaration fragments of a lvalue reference type is the declaration
330 // fragments of the underlying type followed by a `&`.
331 if (const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(T))
332 return Fragments
333 .append(
334 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
336
337 // Declaration fragments of a rvalue reference type is the declaration
338 // fragments of the underlying type followed by a `&&`.
339 if (const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(T))
340 return Fragments
341 .append(
342 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
344
345 // Declaration fragments of an array-typed variable have two parts:
346 // 1. the element type of the array that appears before the variable name;
347 // 2. array brackets `[(0-9)?]` that appear after the variable name.
348 if (const ArrayType *AT = T->getAsArrayTypeUnsafe()) {
349 // Build the "after" part first because the inner element type might also
350 // be an array-type. For example `int matrix[3][4]` which has a type of
351 // "(array 3 of (array 4 of ints))."
352 // Push the array size part first to make sure they are in the right order.
354
355 switch (AT->getSizeModifier()) {
357 break;
360 break;
363 break;
364 }
365
366 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
367 // FIXME: right now this would evaluate any expressions/macros written in
368 // the original source to concrete values. For example
369 // `int nums[MAX]` -> `int nums[100]`
370 // `char *str[5 + 1]` -> `char *str[6]`
372 CAT->getSize().toStringUnsigned(Size);
374 }
375
377
378 return Fragments.append(
379 getFragmentsForType(AT->getElementType(), Context, After));
380 }
381
382 if (const TemplateSpecializationType *TemplSpecTy =
383 dyn_cast<TemplateSpecializationType>(T)) {
384 if (ElaboratedTypeKeyword Keyword = TemplSpecTy->getKeyword();
386 Fragments
389 .appendSpace();
390
391 auto TemplName = TemplSpecTy->getTemplateName();
392 std::string Str;
393 raw_string_ostream Stream(Str);
394 TemplName.print(Stream, Context.getPrintingPolicy(),
396 SmallString<64> USR("");
397 if (const auto *QTN = TemplName.getAsQualifiedTemplateName()) {
398 Fragments.append(getFragmentsForNNS(QTN->getQualifier(), Context, After));
399 TemplName = QTN->getUnderlyingTemplate();
400 }
401 if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
402 index::generateUSRForDecl(TemplDecl, USR);
403 // FIXME: Handle other kinds of TemplateNames.
404
405 return Fragments
409 TemplSpecTy->template_arguments(), Context, std::nullopt))
411 }
412
413 // If the base type is a TagType (struct/interface/union/class/enum), let's
414 // get the underlying Decl for better names and USRs.
415 if (const TagType *TagTy = dyn_cast<TagType>(T)) {
416 if (ElaboratedTypeKeyword Keyword = TagTy->getKeyword();
418 Fragments
421 .appendSpace();
422
423 Fragments.append(getFragmentsForNNS(TagTy->getQualifier(), Context, After));
424
425 const TagDecl *Decl = TagTy->getOriginalDecl();
426 // Anonymous decl, skip this fragment.
427 if (Decl->getName().empty())
428 return Fragments.append("{ ... }",
430 SmallString<128> TagUSR;
432 return Fragments.append(Decl->getName(),
434 TagUSR, Decl);
435 }
436
437 // Everything we care about has been handled now, reduce to the canonical
438 // unqualified base type.
440
441 // If the base type is an ObjCInterfaceType, use the underlying
442 // ObjCInterfaceDecl for the true USR.
443 if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
444 const auto *Decl = ObjCIT->getDecl();
447 return Fragments.append(Decl->getName(),
449 USR, Decl);
450 }
451
452 // Default fragment builder for other kinds of types (BuiltinType etc.)
455 Fragments.append(Base.getAsString(),
457
458 return Fragments;
459}
460
462DeclarationFragmentsBuilder::getFragmentsForQualifiers(const Qualifiers Quals) {
463 DeclarationFragments Fragments;
464 if (Quals.hasConst())
466 if (Quals.hasVolatile())
468 if (Quals.hasRestrict())
470
471 return Fragments;
472}
473
474DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
475 const QualType QT, ASTContext &Context, DeclarationFragments &After) {
476 assert(!QT.isNull() && "invalid type");
477
478 if (const ParenType *PT = dyn_cast<ParenType>(QT)) {
480 return getFragmentsForType(PT->getInnerType(), Context, After)
482 }
483
484 const SplitQualType SQT = QT.split();
485 DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.Quals),
486 TypeFragments =
487 getFragmentsForType(SQT.Ty, Context, After);
488 if (QT.getAsString() == "_Bool")
489 TypeFragments.replace("bool", 0);
490
491 if (QualsFragments.getFragments().empty())
492 return TypeFragments;
493
494 // Use east qualifier for pointer types
495 // For example:
496 // ```
497 // int * const
498 // ^---- ^----
499 // type qualifier
500 // ^-----------------
501 // const pointer to int
502 // ```
503 // should not be reconstructed as
504 // ```
505 // const int *
506 // ^---- ^--
507 // qualifier type
508 // ^---------------- ^
509 // pointer to const int
510 // ```
511 if (SQT.Ty->isAnyPointerType())
512 return TypeFragments.appendSpace().append(std::move(QualsFragments));
513
514 return QualsFragments.appendSpace().append(std::move(TypeFragments));
515}
516
518 const NamespaceDecl *Decl) {
519 DeclarationFragments Fragments;
521 if (!Decl->isAnonymousNamespace())
522 Fragments.appendSpace().append(
524 return Fragments.appendSemicolon();
525}
526
529 DeclarationFragments Fragments;
530 if (Var->isConstexpr())
532 .appendSpace();
533
534 StorageClass SC = Var->getStorageClass();
535 if (SC != SC_None)
536 Fragments
539 .appendSpace();
540
541 // Capture potential fragments that needs to be placed after the variable name
542 // ```
543 // int nums[5];
544 // char (*ptr_to_array)[6];
545 // ```
547 FunctionTypeLoc BlockLoc;
548 FunctionProtoTypeLoc BlockProtoLoc;
549 findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
550
551 if (!BlockLoc) {
553 ? Var->getTypeSourceInfo()->getType()
555 Var->getType());
556
557 Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
558 .appendSpace();
559 } else {
560 Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
561 }
562
563 return Fragments
565 .append(std::move(After))
567}
568
571 DeclarationFragments Fragments;
572 if (Var->isConstexpr())
574 .appendSpace();
575 QualType T =
576 Var->getTypeSourceInfo()
577 ? Var->getTypeSourceInfo()->getType()
579
580 // Might be a member, so might be static.
581 if (Var->isStaticDataMember())
583 .appendSpace();
584
586 DeclarationFragments ArgumentFragment =
587 getFragmentsForType(T, Var->getASTContext(), After);
588 if (StringRef(ArgumentFragment.begin()->Spelling)
589 .starts_with("type-parameter")) {
590 std::string ProperArgName = T.getAsString();
591 ArgumentFragment.begin()->Spelling.swap(ProperArgName);
592 }
593 Fragments.append(std::move(ArgumentFragment))
594 .appendSpace()
597 return Fragments;
598}
599
601DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
602 DeclarationFragments Fragments, After;
603
604 auto *TSInfo = Param->getTypeSourceInfo();
605
606 QualType T = TSInfo ? TSInfo->getType()
608 Param->getType());
609
610 FunctionTypeLoc BlockLoc;
611 FunctionProtoTypeLoc BlockProtoLoc;
612 findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
613
614 DeclarationFragments TypeFragments;
615 if (BlockLoc)
616 TypeFragments.append(
617 getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
618 else
619 TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
620
621 if (StringRef(TypeFragments.begin()->Spelling)
622 .starts_with("type-parameter")) {
623 std::string ProperArgName = Param->getOriginalType().getAsString();
624 TypeFragments.begin()->Spelling.swap(ProperArgName);
625 }
626
627 if (Param->isObjCMethodParameter()) {
629 .append(std::move(TypeFragments))
630 .append(std::move(After))
632 .append(Param->getName(),
634 } else {
635 Fragments.append(std::move(TypeFragments));
636 if (!T->isAnyPointerType() && !T->isBlockPointerType())
637 Fragments.appendSpace();
638 Fragments
639 .append(Param->getName(),
641 .append(std::move(After));
642 }
643 return Fragments;
644}
645
646DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
648 FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
649 DeclarationFragments Fragments;
650
651 DeclarationFragments RetTyAfter;
652 auto ReturnValueFragment = getFragmentsForType(
653 Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
654
655 Fragments.append(std::move(ReturnValueFragment))
656 .append(std::move(RetTyAfter))
657 .appendSpace()
659
661 unsigned NumParams = Block.getNumParams();
662
663 if (!BlockProto || NumParams == 0) {
664 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
666 else
668 } else {
670 for (unsigned I = 0; I != NumParams; ++I) {
671 if (I)
673 After.append(getFragmentsForParam(Block.getParam(I)));
674 if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
676 }
678 }
679
680 return Fragments;
681}
682
685 DeclarationFragments Fragments;
686 switch (Func->getStorageClass()) {
687 case SC_None:
688 case SC_PrivateExtern:
689 break;
690 case SC_Extern:
692 .appendSpace();
693 break;
694 case SC_Static:
696 .appendSpace();
697 break;
698 case SC_Auto:
699 case SC_Register:
700 llvm_unreachable("invalid for functions");
701 }
702 if (Func->isConsteval()) // if consteval, it is also constexpr
704 .appendSpace();
705 else if (Func->isConstexpr())
707 .appendSpace();
708
709 // FIXME: Is `after` actually needed here?
711 QualType ReturnType = Func->getReturnType();
712 auto ReturnValueFragment =
713 getFragmentsForType(ReturnType, Func->getASTContext(), After);
714 if (StringRef(ReturnValueFragment.begin()->Spelling)
715 .starts_with("type-parameter")) {
716 std::string ProperArgName = ReturnType.getAsString();
717 ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
718 }
719
720 Fragments.append(std::move(ReturnValueFragment));
721 if (!ReturnType->isAnyPointerType())
722 Fragments.appendSpace();
723 Fragments.append(Func->getNameAsString(),
725
726 if (Func->getTemplateSpecializationInfo()) {
728
729 for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
730 if (i)
732 Fragments.append(
733 getFragmentsForType(Func->getParamDecl(i)->getType(),
734 Func->getParamDecl(i)->getASTContext(), After));
735 }
737 }
738 Fragments.append(std::move(After));
739
741 unsigned NumParams = Func->getNumParams();
742 for (unsigned i = 0; i != NumParams; ++i) {
743 if (i)
745 Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
746 }
747
748 if (Func->isVariadic()) {
749 if (NumParams > 0)
752 }
754
756 Func->getExceptionSpecType()));
757
758 return Fragments.appendSemicolon();
759}
760
762 const EnumConstantDecl *EnumConstDecl) {
763 DeclarationFragments Fragments;
764 return Fragments.append(EnumConstDecl->getName(),
766}
767
772
773 DeclarationFragments Fragments, After;
775
776 if (!EnumDecl->getName().empty())
777 Fragments.appendSpace().append(
779
780 QualType IntegerType = EnumDecl->getIntegerType();
781 if (!IntegerType.isNull())
782 Fragments.appendSpace()
784 .append(
785 getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
786 .append(std::move(After));
787
788 if (EnumDecl->getName().empty())
789 Fragments.appendSpace().append("{ ... }",
791
792 return Fragments.appendSemicolon();
793}
794
798 DeclarationFragments Fragments;
799 if (Field->isMutable())
801 .appendSpace();
802 return Fragments
803 .append(
804 getFragmentsForType(Field->getType(), Field->getASTContext(), After))
805 .appendSpace()
807 .append(std::move(After))
809}
810
812 const RecordDecl *Record) {
813 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
815
816 DeclarationFragments Fragments;
817 if (Record->isUnion())
819 else
821
822 Fragments.appendSpace();
823 if (!Record->getName().empty())
824 Fragments.append(Record->getName(),
826 else
828
829 return Fragments.appendSemicolon();
830}
831
833 const CXXRecordDecl *Record) {
834 if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
836
837 DeclarationFragments Fragments;
839
840 if (!Record->getName().empty())
841 Fragments.appendSpace().append(
843
844 return Fragments.appendSemicolon();
845}
846
849 const CXXMethodDecl *Method) {
850 DeclarationFragments Fragments;
851 std::string Name;
852 if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
853 Name = Method->getNameAsString();
854 if (Constructor->isExplicit())
856 .appendSpace();
857 } else if (isa<CXXDestructorDecl>(Method))
858 Name = Method->getNameAsString();
859
862 .append(std::move(After));
864 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
865 if (i)
867 Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
868 }
870
872 Method->getExceptionSpecType()));
873
874 return Fragments.appendSemicolon();
875}
876
878 const CXXMethodDecl *Method) {
879 DeclarationFragments Fragments;
880 StringRef Name = Method->getName();
881 if (Method->isStatic())
883 .appendSpace();
884 if (Method->isConstexpr())
886 .appendSpace();
887 if (Method->isVolatile())
889 .appendSpace();
890 if (Method->isVirtual())
892 .appendSpace();
893
894 // Build return type
896 Fragments
897 .append(getFragmentsForType(Method->getReturnType(),
898 Method->getASTContext(), After))
899 .appendSpace()
901 .append(std::move(After));
903 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
904 if (i)
906 Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
907 }
909
910 if (Method->isConst())
911 Fragments.appendSpace().append("const",
913
915 Method->getExceptionSpecType()));
916
917 return Fragments.appendSemicolon();
918}
919
922 const CXXConversionDecl *ConversionFunction) {
923 DeclarationFragments Fragments;
924
925 if (ConversionFunction->isExplicit())
927 .appendSpace();
928
930 .appendSpace();
931
932 Fragments
933 .append(ConversionFunction->getConversionType().getAsString(),
936 for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
937 ++i) {
938 if (i)
940 Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
941 }
943
944 if (ConversionFunction->isConst())
945 Fragments.appendSpace().append("const",
947
948 return Fragments.appendSemicolon();
949}
950
953 const CXXMethodDecl *Method) {
954 DeclarationFragments Fragments;
955
956 // Build return type
958 Fragments
959 .append(getFragmentsForType(Method->getReturnType(),
960 Method->getASTContext(), After))
961 .appendSpace()
962 .append(Method->getNameAsString(),
964 .append(std::move(After));
966 for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
967 if (i)
969 Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
970 }
972
973 if (Method->isConst())
974 Fragments.appendSpace().append("const",
976
978 Method->getExceptionSpecType()));
979
980 return Fragments.appendSemicolon();
981}
982
983// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
986 ArrayRef<NamedDecl *> ParameterArray) {
987 DeclarationFragments Fragments;
988 for (unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
989 if (i)
991 .appendSpace();
992
993 if (const auto *TemplateParam =
994 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
995 if (TemplateParam->hasTypeConstraint())
996 Fragments.append(TemplateParam->getTypeConstraint()
997 ->getNamedConcept()
998 ->getName()
999 .str(),
1001 else if (TemplateParam->wasDeclaredWithTypename())
1002 Fragments.append("typename",
1004 else
1006
1007 if (TemplateParam->isParameterPack())
1009
1010 if (!TemplateParam->getName().empty())
1011 Fragments.appendSpace().append(
1012 TemplateParam->getName(),
1014
1015 if (TemplateParam->hasDefaultArgument()) {
1016 const auto Default = TemplateParam->getDefaultArgument();
1019 {Default.getArgument()}, TemplateParam->getASTContext(),
1020 {Default}));
1021 }
1022 } else if (const auto *NTP =
1023 dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
1025 const auto TyFragments =
1026 getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
1027 Fragments.append(std::move(TyFragments)).append(std::move(After));
1028
1029 if (NTP->isParameterPack())
1031
1032 if (!NTP->getName().empty())
1033 Fragments.appendSpace().append(
1034 NTP->getName(),
1036
1037 if (NTP->hasDefaultArgument()) {
1038 SmallString<8> ExprStr;
1039 raw_svector_ostream Output(ExprStr);
1040 NTP->getDefaultArgument().getArgument().print(
1041 NTP->getASTContext().getPrintingPolicy(), Output,
1042 /*IncludeType=*/false);
1045 }
1046 } else if (const auto *TTP =
1047 dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1049 .appendSpace()
1052 TTP->getTemplateParameters()->asArray()))
1054 .appendSpace()
1055 .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",
1057
1058 if (TTP->isParameterPack())
1060
1061 if (!TTP->getName().empty())
1062 Fragments.appendSpace().append(
1063 TTP->getName(),
1065 if (TTP->hasDefaultArgument()) {
1066 const auto Default = TTP->getDefaultArgument();
1069 {Default.getArgument()}, TTP->getASTContext(), {Default}));
1070 }
1071 }
1072 }
1073 return Fragments;
1074}
1075
1076// Get fragments for template arguments, e.g. int in template<typename T>
1077// Foo<int>;
1078//
1079// Note: TemplateParameters is only necessary if the Decl is a
1080// PartialSpecialization, where we need the parameters to deduce the name of the
1081// generic arguments.
1084 const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
1085 const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {
1086 DeclarationFragments Fragments;
1087 for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
1088 if (i)
1090 .appendSpace();
1091
1092 const auto &CTA = TemplateArguments[i];
1093 switch (CTA.getKind()) {
1096 DeclarationFragments ArgumentFragment =
1097 getFragmentsForType(CTA.getAsType(), Context, After);
1098
1099 if (StringRef(ArgumentFragment.begin()->Spelling)
1100 .starts_with("type-parameter")) {
1101 if (TemplateArgumentLocs.has_value() &&
1102 TemplateArgumentLocs->size() > i) {
1103 std::string ProperArgName = TemplateArgumentLocs.value()[i]
1104 .getTypeSourceInfo()
1105 ->getType()
1106 .getAsString();
1107 ArgumentFragment.begin()->Spelling.swap(ProperArgName);
1108 } else {
1109 auto &Spelling = ArgumentFragment.begin()->Spelling;
1110 Spelling.clear();
1111 raw_string_ostream OutStream(Spelling);
1112 CTA.print(Context.getPrintingPolicy(), OutStream, false);
1113 }
1114 }
1115
1116 Fragments.append(std::move(ArgumentFragment));
1117 break;
1118 }
1120 const auto *VD = CTA.getAsDecl();
1121 SmallString<128> USR;
1123 Fragments.append(VD->getNameAsString(),
1125 break;
1126 }
1129 break;
1130
1132 SmallString<4> Str;
1133 CTA.getAsIntegral().toString(Str);
1135 break;
1136 }
1137
1139 const auto SVTy = CTA.getStructuralValueType();
1140 Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1142 break;
1143 }
1144
1147 std::string Str;
1148 raw_string_ostream Stream(Str);
1149 CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1150 SmallString<64> USR("");
1151 if (const auto *TemplDecl =
1152 CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1153 index::generateUSRForDecl(TemplDecl, USR);
1155 USR);
1156 if (CTA.getKind() == TemplateArgument::TemplateExpansion)
1158 break;
1159 }
1160
1163 .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,
1164 {}))
1166 break;
1167
1169 SmallString<8> ExprStr;
1170 raw_svector_ostream Output(ExprStr);
1171 CTA.getAsExpr()->printPretty(Output, nullptr,
1172 Context.getPrintingPolicy());
1174 break;
1175 }
1176
1178 break;
1179 }
1180 }
1181 return Fragments;
1182}
1183
1185 const ConceptDecl *Concept) {
1186 DeclarationFragments Fragments;
1187 return Fragments
1189 .appendSpace()
1192 Concept->getTemplateParameters()->asArray()))
1194 .appendSpace()
1196 .appendSpace()
1197 .append(Concept->getName().str(),
1199 .appendSemicolon();
1200}
1201
1204 const RedeclarableTemplateDecl *RedeclarableTemplate) {
1205 DeclarationFragments Fragments;
1207 .appendSpace()
1210 RedeclarableTemplate->getTemplateParameters()->asArray()))
1212 .appendSpace();
1213
1214 if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
1215 Fragments.appendSpace()
1217 .appendSpace()
1218 .append(RedeclarableTemplate->getName(),
1220 // the templated records will be resposbible for injecting their templates
1221 return Fragments.appendSpace();
1222}
1223
1227 DeclarationFragments Fragments;
1228 std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs = {};
1229 if (auto *TemplateArgs = Decl->getTemplateArgsAsWritten()) {
1230 TemplateArgumentLocs = TemplateArgs->arguments();
1231 }
1232 return Fragments
1234 .appendSpace()
1237 .appendSpace()
1239 cast<CXXRecordDecl>(Decl)))
1240 .pop_back() // there is an extra semicolon now
1243 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1244 TemplateArgumentLocs))
1246 .appendSemicolon();
1247}
1248
1252 DeclarationFragments Fragments;
1253 return Fragments
1255 .appendSpace()
1258 Decl->getTemplateParameters()->asArray()))
1260 .appendSpace()
1262 cast<CXXRecordDecl>(Decl)))
1263 .pop_back() // there is an extra semicolon now
1266 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1267 Decl->getTemplateArgsAsWritten()->arguments()))
1269 .appendSemicolon();
1270}
1271
1275 DeclarationFragments Fragments;
1276 return Fragments
1278 .appendSpace()
1281 .appendSpace()
1283 .pop_back() // there is an extra semicolon now
1286 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1287 Decl->getTemplateArgsAsWritten()->arguments()))
1289 .appendSemicolon();
1290}
1291
1295 DeclarationFragments Fragments;
1296 return Fragments
1298 .appendSpace()
1300 // Partial specs may have new params.
1302 Decl->getTemplateParameters()->asArray()))
1304 .appendSpace()
1306 .pop_back() // there is an extra semicolon now
1309 Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
1310 Decl->getTemplateArgsAsWritten()->arguments()))
1312 .appendSemicolon();
1313}
1314
1317 const FunctionTemplateDecl *Decl) {
1318 DeclarationFragments Fragments;
1319 return Fragments
1321 .appendSpace()
1323 // Partial specs may have new params.
1325 Decl->getTemplateParameters()->asArray()))
1327 .appendSpace()
1329 Decl->getAsFunction()));
1330}
1331
1334 const FunctionDecl *Decl) {
1335 DeclarationFragments Fragments;
1336 return Fragments
1338 .appendSpace()
1340 .appendSpace()
1342}
1343
1346 const MacroInfo *MI) {
1347 DeclarationFragments Fragments;
1349 .appendSpace();
1351
1352 if (MI->isFunctionLike()) {
1354 unsigned numParameters = MI->getNumParams();
1355 if (MI->isC99Varargs())
1356 --numParameters;
1357 for (unsigned i = 0; i < numParameters; ++i) {
1358 if (i)
1360 Fragments.append(MI->params()[i]->getName(),
1362 }
1363 if (MI->isVariadic()) {
1364 if (numParameters && MI->isC99Varargs())
1367 }
1369 }
1370 return Fragments;
1371}
1372
1374 const ObjCCategoryDecl *Category) {
1375 DeclarationFragments Fragments;
1376
1377 auto *Interface = Category->getClassInterface();
1378 SmallString<128> InterfaceUSR;
1379 index::generateUSRForDecl(Interface, InterfaceUSR);
1380
1382 .appendSpace()
1383 .append(Interface->getName(),
1385 Interface)
1387 .append(Category->getName(),
1390
1391 return Fragments;
1392}
1393
1396 DeclarationFragments Fragments;
1397 // Build the base of the Objective-C interface declaration.
1399 .appendSpace()
1400 .append(Interface->getName(),
1402
1403 // Build the inheritance part of the declaration.
1404 if (const ObjCInterfaceDecl *SuperClass = Interface->getSuperClass()) {
1405 SmallString<128> SuperUSR;
1406 index::generateUSRForDecl(SuperClass, SuperUSR);
1408 .append(SuperClass->getName(),
1410 SuperClass);
1411 }
1412
1413 return Fragments;
1414}
1415
1417 const ObjCMethodDecl *Method) {
1418 DeclarationFragments Fragments, After;
1419 // Build the instance/class method indicator.
1420 if (Method->isClassMethod())
1422 else if (Method->isInstanceMethod())
1424
1425 // Build the return type.
1427 .append(getFragmentsForType(Method->getReturnType(),
1428 Method->getASTContext(), After))
1429 .append(std::move(After))
1431
1432 // Build the selector part.
1433 Selector Selector = Method->getSelector();
1434 if (Selector.getNumArgs() == 0)
1435 // For Objective-C methods that don't take arguments, the first (and only)
1436 // slot of the selector is the method name.
1437 Fragments.appendSpace().append(
1440
1441 // For Objective-C methods that take arguments, build the selector slots.
1442 for (unsigned i = 0, end = Method->param_size(); i != end; ++i) {
1443 // Objective-C method selector parts are considered as identifiers instead
1444 // of "external parameters" as in Swift. This is because Objective-C method
1445 // symbols are referenced with the entire selector, instead of just the
1446 // method name in Swift.
1448 ParamID.append(":");
1449 Fragments.appendSpace().append(
1451
1452 // Build the internal parameter.
1453 const ParmVarDecl *Param = Method->getParamDecl(i);
1454 Fragments.append(getFragmentsForParam(Param));
1455 }
1456
1457 return Fragments.appendSemicolon();
1458}
1459
1461 const ObjCPropertyDecl *Property) {
1462 DeclarationFragments Fragments, After;
1463
1464 // Build the Objective-C property keyword.
1466
1467 const auto Attributes = Property->getPropertyAttributesAsWritten();
1468 // Build the attributes if there is any associated with the property.
1469 if (Attributes != ObjCPropertyAttribute::kind_noattr) {
1470 // No leading comma for the first attribute.
1471 bool First = true;
1473 // Helper function to render the attribute.
1474 auto RenderAttribute =
1475 [&](ObjCPropertyAttribute::Kind Kind, StringRef Spelling,
1476 StringRef Arg = "",
1479 // Check if the `Kind` attribute is set for this property.
1480 if ((Attributes & Kind) && !Spelling.empty()) {
1481 // Add a leading comma if this is not the first attribute rendered.
1482 if (!First)
1484 // Render the spelling of this attribute `Kind` as a keyword.
1485 Fragments.append(Spelling,
1487 // If this attribute takes in arguments (e.g. `getter=getterName`),
1488 // render the arguments.
1489 if (!Arg.empty())
1491 .append(Arg, ArgKind);
1492 First = false;
1493 }
1494 };
1495
1496 // Go through all possible Objective-C property attributes and render set
1497 // ones.
1498 RenderAttribute(ObjCPropertyAttribute::kind_class, "class");
1499 RenderAttribute(ObjCPropertyAttribute::kind_direct, "direct");
1500 RenderAttribute(ObjCPropertyAttribute::kind_nonatomic, "nonatomic");
1501 RenderAttribute(ObjCPropertyAttribute::kind_atomic, "atomic");
1502 RenderAttribute(ObjCPropertyAttribute::kind_assign, "assign");
1503 RenderAttribute(ObjCPropertyAttribute::kind_retain, "retain");
1504 RenderAttribute(ObjCPropertyAttribute::kind_strong, "strong");
1505 RenderAttribute(ObjCPropertyAttribute::kind_copy, "copy");
1506 RenderAttribute(ObjCPropertyAttribute::kind_weak, "weak");
1508 "unsafe_unretained");
1509 RenderAttribute(ObjCPropertyAttribute::kind_readwrite, "readwrite");
1510 RenderAttribute(ObjCPropertyAttribute::kind_readonly, "readonly");
1511 RenderAttribute(ObjCPropertyAttribute::kind_getter, "getter",
1512 Property->getGetterName().getAsString());
1513 RenderAttribute(ObjCPropertyAttribute::kind_setter, "setter",
1514 Property->getSetterName().getAsString());
1515
1516 // Render nullability attributes.
1517 if (Attributes & ObjCPropertyAttribute::kind_nullability) {
1518 QualType Type = Property->getType();
1519 if (const auto Nullability =
1521 if (!First)
1523 if (*Nullability == NullabilityKind::Unspecified &&
1525 Fragments.append("null_resettable",
1527 else
1528 Fragments.append(
1529 getNullabilitySpelling(*Nullability, /*isContextSensitive=*/true),
1531 First = false;
1532 }
1533 }
1534
1536 }
1537
1538 Fragments.appendSpace();
1539
1540 FunctionTypeLoc BlockLoc;
1541 FunctionProtoTypeLoc BlockProtoLoc;
1542 findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
1543 BlockProtoLoc);
1544
1545 auto PropType = Property->getType();
1546 if (!BlockLoc)
1547 Fragments
1548 .append(getFragmentsForType(PropType, Property->getASTContext(), After))
1549 .appendSpace();
1550 else
1551 Fragments.append(
1552 getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
1553
1554 return Fragments
1555 .append(Property->getName(),
1557 .append(std::move(After))
1558 .appendSemicolon();
1559}
1560
1562 const ObjCProtocolDecl *Protocol) {
1563 DeclarationFragments Fragments;
1564 // Build basic protocol declaration.
1566 .appendSpace()
1567 .append(Protocol->getName(),
1569
1570 // If this protocol conforms to other protocols, build the conformance list.
1571 if (!Protocol->protocols().empty()) {
1573 for (ObjCProtocolDecl::protocol_iterator It = Protocol->protocol_begin();
1574 It != Protocol->protocol_end(); It++) {
1575 // Add a leading comma if this is not the first protocol rendered.
1576 if (It != Protocol->protocol_begin())
1578
1579 SmallString<128> USR;
1580 index::generateUSRForDecl(*It, USR);
1581 Fragments.append((*It)->getName(),
1583 *It);
1584 }
1586 }
1587
1588 return Fragments;
1589}
1590
1592 const TypedefNameDecl *Decl) {
1593 DeclarationFragments Fragments, After;
1595 .appendSpace()
1596 .append(getFragmentsForType(Decl->getUnderlyingType(),
1597 Decl->getASTContext(), After))
1598 .append(std::move(After))
1599 .appendSpace()
1601
1602 return Fragments.appendSemicolon();
1603}
1604
1605// Instantiate template for FunctionDecl.
1606template FunctionSignature
1608
1609// Instantiate template for ObjCMethodDecl.
1610template FunctionSignature
1612
1613// Subheading of a symbol defaults to its name.
1616 DeclarationFragments Fragments;
1617 if (isa<CXXConstructorDecl>(Decl)) {
1618 Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
1620 } else if (isa<CXXDestructorDecl>(Decl)) {
1621 Fragments.append(cast<CXXDestructorDecl>(Decl)->getNameAsString(),
1623 } else if (isa<CXXConversionDecl>(Decl)) {
1624 Fragments.append(
1625 cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
1627 } else if (isa<CXXMethodDecl>(Decl) &&
1628 cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
1629 Fragments.append(Decl->getNameAsString(),
1631 } else if (isa<TagDecl>(Decl) &&
1632 cast<TagDecl>(Decl)->getTypedefNameForAnonDecl()) {
1633 return getSubHeading(cast<TagDecl>(Decl)->getTypedefNameForAnonDecl());
1634 } else if (Decl->getIdentifier()) {
1635 Fragments.append(Decl->getName(),
1637 } else {
1638 Fragments.append(Decl->getDeclName().getAsString(),
1640 }
1641
1642 return Fragments;
1643}
1644
1645// Subheading of an Objective-C method is a `+` or `-` sign indicating whether
1646// it's a class method or an instance method, followed by the selector name.
1649 DeclarationFragments Fragments;
1650 if (Method->isClassMethod())
1652 else if (Method->isInstanceMethod())
1654
1655 return Fragments.append(Method->getNameAsString(),
1657}
1658
1659// Subheading of a symbol defaults to its name.
1662 DeclarationFragments Fragments;
1664 return Fragments;
1665}
Forward declaration of all AST node types.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines the Declaration Fragments related classes.
int Category
Definition: Format.cpp:3180
const CFGBlock * Block
Definition: HTMLLogger.cpp:152
llvm::MachO::Record Record
Definition: MachO.h:31
Defines the clang::TypeLoc interface and its subclasses.
C Language Family Type Representation.
This file defines the UnderlyingTypeResolver which is a helper type for resolving the undelrying type...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
QualType getUnqualifiedObjCPointerType(QualType type) const
getUnqualifiedObjCPointerType - Returns version of Objective-C pointer type with lifetime qualifier r...
Definition: ASTContext.h:2477
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: TypeBase.h:3738
Type source information for an attributed type.
Definition: TypeLoc.h:1017
An attributed type is a type to which a type attribute has been applied.
Definition: TypeBase.h:6585
static std::optional< NullabilityKind > stripOuterNullability(QualType &T)
Strip off the top-level nullability annotation on the given type, if it's there.
Definition: Type.cpp:5245
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4634
Wrapper for source info for block pointers.
Definition: TypeLoc.h:1506
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2937
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2129
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
Represents a class template specialization, which refers to a class template with a given set of temp...
Declaration of a C++20 concept.
Represents the canonical version of C arrays with a specified constant size.
Definition: TypeBase.h:3776
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:524
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition: DeclBase.cpp:251
DeclContext * getDeclContext()
Definition: DeclBase.h:448
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:808
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3420
Represents an enum.
Definition: Decl.h:4004
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
Definition: Decl.h:4168
Represents a member of a struct/union/class.
Definition: Decl.h:3157
Represents a function declaration or definition.
Definition: Decl.h:1999
bool isVariadic() const
Whether this function prototype is variadic.
Definition: TypeBase.h:5686
Declaration of a template function.
Definition: DeclTemplate.h:952
Wrapper for source info for functions.
Definition: TypeLoc.h:1624
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:531
An lvalue reference type, per C++11 [dcl.ref].
Definition: TypeBase.h:3633
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:39
bool isC99Varargs() const
Definition: MacroInfo.h:207
bool isFunctionLike() const
Definition: MacroInfo.h:201
ArrayRef< const IdentifierInfo * > params() const
Definition: MacroInfo.h:185
unsigned getNumParams() const
Definition: MacroInfo.h:184
bool isVariadic() const
Definition: MacroInfo.h:209
Sugar type that represents a type that was qualified by a qualifier written as a macro invocation.
Definition: TypeBase.h:6161
This represents a decl that may have a name.
Definition: Decl.h:273
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:300
Represent a C++ namespace.
Definition: Decl.h:591
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
NamespaceAndPrefix getAsNamespaceAndPrefix() const
@ MicrosoftSuper
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Global
The global specifier '::'. There is no stored value.
@ Type
A type, stored as a Type*.
@ Namespace
A namespace-like entity, stored as a NamespaceBaseDecl*.
ObjCCategoryDecl - Represents a category declaration.
Definition: DeclObjC.h:2329
Represents an ObjC class declaration.
Definition: DeclObjC.h:1154
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:140
Represents a pointer to an Objective C object.
Definition: TypeBase.h:7961
bool isObjCQualifiedIdType() const
True if this is equivalent to 'id.
Definition: TypeBase.h:8036
bool isObjCIdOrClassType() const
True if this is equivalent to the 'id' or 'Class' type,.
Definition: TypeBase.h:8030
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:731
Represents an Objective-C protocol declaration.
Definition: DeclObjC.h:2084
ObjCProtocolList::iterator protocol_iterator
Definition: DeclObjC.h:2158
Sugar for parentheses used when specifying types.
Definition: TypeBase.h:3320
Represents a parameter to a function.
Definition: Decl.h:1789
bool isObjCMethodParameter() const
Definition: Decl.h:1832
QualType getOriginalType() const
Definition: Decl.cpp:2955
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: TypeBase.h:1004
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
Definition: TypeBase.h:8364
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: TypeBase.h:1332
Wrapper of type source information for a type with non-trivial direct qualifiers.
Definition: TypeLoc.h:305
The collection of all-type qualifiers we support.
Definition: TypeBase.h:331
bool hasConst() const
Definition: TypeBase.h:457
bool hasRestrict() const
Definition: TypeBase.h:477
bool hasVolatile() const
Definition: TypeBase.h:467
An rvalue reference type, per C++11 [dcl.ref].
Definition: TypeBase.h:3651
Represents a struct/union/class.
Definition: Decl.h:4309
Declaration of a redeclarable template.
Definition: DeclTemplate.h:715
Smart pointer class that efficiently represents Objective-C method names.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
unsigned getNumArgs() const
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3714
TypedefNameDecl * getTypedefNameForAnonDecl() const
Definition: Decl.h:3945
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
Definition: TemplateBase.h:74
@ Template
The template argument is a template name that was provided for a template template parameter.
Definition: TemplateBase.h:93
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
Definition: TemplateBase.h:89
@ Pack
The template argument is actually a parameter pack.
Definition: TemplateBase.h:107
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
Definition: TemplateBase.h:97
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
Definition: TemplateBase.h:78
@ Type
The template argument is a type.
Definition: TemplateBase.h:70
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
Definition: TemplateBase.h:67
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
Definition: TemplateBase.h:82
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
Definition: TemplateBase.h:103
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:415
ArrayRef< NamedDecl * > asArray()
Definition: DeclTemplate.h:143
Represents a type template specialization; the template must be a class template, a type alias templa...
Definition: TypeBase.h:7290
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
UnqualTypeLoc getUnqualifiedLoc() const
Skips past any qualifiers, if this is qualified.
Definition: TypeLoc.h:354
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
Definition: TypeLoc.h:89
TypeLoc IgnoreParens() const
Definition: TypeLoc.h:1417
A container of type source information.
Definition: TypeBase.h:8314
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:272
QualType getType() const
Return the type wrapped by this type source info.
Definition: TypeBase.h:8325
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isBlockPointerType() const
Definition: TypeBase.h:8600
bool isFunctionPointerType() const
Definition: TypeBase.h:8647
bool isPointerType() const
Definition: TypeBase.h:8580
CanQualType getCanonicalTypeUnqualified() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: TypeBase.h:9212
bool isObjCObjectPointerType() const
Definition: TypeBase.h:8749
bool isAnyPointerType() const
Definition: TypeBase.h:8588
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3559
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1568
static const char * getStorageClassSpecifierString(StorageClass SC)
Return the string used to specify the storage class SC.
Definition: Decl.cpp:2121
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1282
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1167
Represents a variable template specialization, which refers to a variable template with a given set o...
static DeclarationFragments getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *)
static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *)
static DeclarationFragments getFragmentsForEnumConstant(const EnumConstantDecl *)
Build DeclarationFragments for an enum constant declaration EnumConstantDecl.
static DeclarationFragments getFragmentsForObjCCategory(const ObjCCategoryDecl *)
Build DeclarationFragments for an Objective-C category declaration ObjCCategoryDecl.
static DeclarationFragments getFragmentsForMacro(StringRef Name, const MacroInfo *MI)
Build DeclarationFragments for a macro.
static DeclarationFragments getFragmentsForTypedef(const TypedefNameDecl *Decl)
Build DeclarationFragments for a typedef TypedefNameDecl.
static DeclarationFragments getFragmentsForEnum(const EnumDecl *)
Build DeclarationFragments for an enum declaration EnumDecl.
static DeclarationFragments getFragmentsForConversionFunction(const CXXConversionDecl *)
static DeclarationFragments getFragmentsForClassTemplateSpecialization(const ClassTemplateSpecializationDecl *)
static DeclarationFragments getFragmentsForTemplateParameters(ArrayRef< NamedDecl * >)
static DeclarationFragments getFragmentsForObjCProtocol(const ObjCProtocolDecl *)
Build DeclarationFragments for an Objective-C protocol declaration ObjCProtocolDecl.
static DeclarationFragments getFragmentsForConcept(const ConceptDecl *)
static DeclarationFragments getFragmentsForField(const FieldDecl *)
Build DeclarationFragments for a field declaration FieldDecl.
static DeclarationFragments getFragmentsForVar(const VarDecl *)
Build DeclarationFragments for a variable declaration VarDecl.
static DeclarationFragments getFragmentsForTemplateArguments(const ArrayRef< TemplateArgument >, ASTContext &, const std::optional< ArrayRef< TemplateArgumentLoc > >)
static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization(const ClassTemplatePartialSpecializationDecl *)
static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *)
Build DeclarationFragments for an Objective-C method declaration ObjCMethodDecl.
static DeclarationFragments getSubHeadingForMacro(StringRef Name)
Build a sub-heading for macro Name.
static DeclarationFragments getFragmentsForFunction(const FunctionDecl *)
Build DeclarationFragments for a function declaration FunctionDecl.
static DeclarationFragments getFragmentsForObjCProperty(const ObjCPropertyDecl *)
Build DeclarationFragments for an Objective-C property declaration ObjCPropertyDecl.
static DeclarationFragments getFragmentsForSpecialCXXMethod(const CXXMethodDecl *)
static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *)
static DeclarationFragments getFragmentsForNamespace(const NamespaceDecl *Decl)
static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(const VarTemplatePartialSpecializationDecl *)
static DeclarationFragments getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl)
static DeclarationFragments getFragmentsForVarTemplateSpecialization(const VarTemplateSpecializationDecl *)
static FunctionSignature getFunctionSignature(const FunctionT *Function)
Build FunctionSignature for a function-like declaration FunctionT like FunctionDecl,...
static DeclarationFragments getSubHeading(const NamedDecl *)
Build sub-heading fragments for a NamedDecl.
static DeclarationFragments getFragmentsForVarTemplate(const VarDecl *)
static DeclarationFragments getFragmentsForOverloadedOperator(const CXXMethodDecl *)
static DeclarationFragments getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl)
static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *)
Build DeclarationFragments for a struct/union record declaration RecordDecl.
static DeclarationFragments getFragmentsForObjCInterface(const ObjCInterfaceDecl *)
Build DeclarationFragments for an Objective-C interface declaration ObjCInterfaceDecl.
DeclarationFragments is a vector of tagged important parts of a symbol's declaration.
DeclarationFragments & append(DeclarationFragments Other)
Append another DeclarationFragments to the end.
const std::vector< Fragment > & getFragments() const
DeclarationFragments & appendSpace()
Append a text Fragment of a space character.
static DeclarationFragments getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec)
@ GenericParameter
Parameter that's used as generics in the context.
@ ExternalParam
External parameters in Objective-C methods.
@ TypeIdentifier
Identifier that refers to a type in the context.
@ InternalParam
Internal/local parameters in Objective-C methods.
DeclarationFragments & removeTrailingSemicolon()
Removes a trailing semicolon character if present.
static StringRef getFragmentKindString(FragmentKind Kind)
Get the string description of a FragmentKind Kind.
static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl)
DeclarationFragments & appendSemicolon()
Append a text Fragment of a semicolon character.
static FragmentKind parseFragmentKindFromString(StringRef S)
Get the corresponding FragmentKind from string S.
Store function signature information with DeclarationFragments of the return type and parameters.
@ kind_nullability
Indicates that the nullability of the type was spelled with a property attribute rather than a type q...
@ After
Like System, but searched after the system directories.
bool generateUSRForType(QualType T, ASTContext &Ctx, SmallVectorImpl< char > &Buf)
Generates a USR for a type.
bool generateUSRForDecl(const Decl *D, SmallVectorImpl< char > &Buf)
Generate a USR for a Decl, including the USR prefix.
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
StorageClass
Storage classes.
Definition: Specifiers.h:248
@ SC_Auto
Definition: Specifiers.h:256
@ SC_PrivateExtern
Definition: Specifiers.h:253
@ SC_Extern
Definition: Specifiers.h:251
@ SC_Register
Definition: Specifiers.h:257
@ SC_Static
Definition: Specifiers.h:252
@ SC_None
Definition: Specifiers.h:250
@ Property
The type of a property.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive=false)
Retrieve the spelling of the given nullability kind.
@ Keyword
The name has been typo-corrected to a keyword.
@ Concept
The name was classified as a concept name.
const FunctionProtoType * T
llvm::StringRef getAsString(SyncScope S)
Definition: SyncScope.h:60
ElaboratedTypeKeyword
The elaboration keyword that precedes a qualified type name or introduces an elaborated-type-specifie...
Definition: TypeBase.h:5881
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
@ None
No keyword precedes the qualified type name.
ExceptionSpecificationType
The various types of exception specifications that exist in C++11.
@ EST_DependentNoexcept
noexcept(expression), value-dependent
@ EST_DynamicNone
throw()
@ EST_None
no exception specification
@ EST_BasicNoexcept
noexcept
@ EST_NoexceptFalse
noexcept(expression), evals to 'false'
@ EST_NoexceptTrue
noexcept(expression), evals to 'true'
@ EST_Dynamic
throw(T1, T2)
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
static StringRef getKeywordName(ElaboratedTypeKeyword Keyword)
Definition: Type.cpp:3315
A std::pair-like structure for storing a qualified type split into its local qualifiers and its local...
Definition: TypeBase.h:870
const Type * Ty
The locally-unqualified type.
Definition: TypeBase.h:872
Qualifiers Quals
The local qualifiers.
Definition: TypeBase.h:875
Fragment holds information of a single fragment.