24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/raw_ostream.h"
49 TL = AttrTL.getModifiedLoc();
67DeclarationFragments::appendUnduplicatedTextCharacter(
char Character) {
68 if (!Fragments.empty()) {
73 if (
Last.Spelling.back() != Character) {
74 Last.Spelling.push_back(Character);
78 Fragments.back().Spelling.push_back(Character);
86 return appendUnduplicatedTextCharacter(
' ');
90 return appendUnduplicatedTextCharacter(
';');
94 if (Fragments.empty())
99 Last.Spelling.pop_back();
120 return "typeIdentifier";
122 return "genericParameter";
124 return "externalParam";
126 return "internalParam";
131 llvm_unreachable(
"Unhandled FragmentKind");
136 return llvm::StringSwitch<FragmentKind>(S)
142 .Case(
"typeIdentifier",
144 .Case(
"genericParameter",
155 switch (ExceptionSpec) {
188 llvm_unreachable(
"Unhandled exception specification");
196 else if (
Record->isUnion())
217 Fragments.
append(getFragmentsForNNS(Prefix, Context, After));
218 if (
const auto *NS = dyn_cast<NamespaceDecl>(Namespace);
219 NS && NS->isAnonymousNamespace())
223 Fragments.
append(Namespace->getName(),
240 Fragments.
append(getFragmentsForType(NNS.
getAsType(), Context, After));
253 assert(
T &&
"invalid type");
255 DeclarationFragments Fragments;
257 if (
const MacroQualifiedType *MQT = dyn_cast<MacroQualifiedType>(
T)) {
259 getFragmentsForType(MQT->getUnderlyingType(), Context, After));
263 if (
const AttributedType *AT = dyn_cast<AttributedType>(
T)) {
266 getFragmentsForType(AT->getModifiedType(), Context, After));
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));
289 getFragmentsForNNS(TypedefTy->getQualifier(), Context, After));
291 if (TypedefTy->isObjCIdType()) {
298 USR, TypedefResolver.getUnderlyingTypeDecl(QualType(
T, 0)));
305 Fragments.
append(getFragmentsForType(PointeeT, Context, After));
316 !
T->
getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
322 if (!
T->
getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
331 if (
const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(
T))
334 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
339 if (
const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(
T))
342 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
355 switch (AT->getSizeModifier()) {
366 if (
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
371 SmallString<128>
Size;
372 CAT->getSize().toStringUnsigned(Size);
379 getFragmentsForType(AT->getElementType(), Context, After));
382 if (
const TemplateSpecializationType *TemplSpecTy =
383 dyn_cast<TemplateSpecializationType>(
T)) {
391 auto TemplName = TemplSpecTy->getTemplateName();
393 raw_string_ostream Stream(Str);
396 SmallString<64> USR(
"");
397 if (
const auto *QTN = TemplName.getAsQualifiedTemplateName()) {
398 Fragments.
append(getFragmentsForNNS(QTN->getQualifier(), Context, After));
399 TemplName = QTN->getUnderlyingTemplate();
401 if (
const auto *TemplDecl = TemplName.getAsTemplateDecl())
409 TemplSpecTy->template_arguments(), Context, std::nullopt))
415 if (
const TagType *TagTy = dyn_cast<TagType>(
T)) {
423 Fragments.
append(getFragmentsForNNS(TagTy->getQualifier(), Context, After));
425 const TagDecl *
Decl = TagTy->getDecl();
427 if (
Decl->getName().empty())
428 return Fragments.
append(
"{ ... }",
430 SmallString<128> TagUSR;
443 if (
const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
444 const auto *
Decl = ObjCIT->getDecl();
445 SmallString<128> USR;
453 SmallString<128> USR;
462DeclarationFragmentsBuilder::getFragmentsForQualifiers(
const Qualifiers Quals) {
463 DeclarationFragments Fragments;
476 assert(!QT.
isNull() &&
"invalid type");
478 if (
const ParenType *PT = dyn_cast<ParenType>(QT)) {
480 return getFragmentsForType(PT->getInnerType(), Context, After)
484 const SplitQualType SQT = QT.
split();
485 DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.
Quals),
487 getFragmentsForType(SQT.
Ty, Context, After);
489 TypeFragments.replace(
"bool", 0);
492 return TypeFragments;
512 return TypeFragments.appendSpace().append(std::move(QualsFragments));
521 if (!
Decl->isAnonymousNamespace())
560 Fragments.
append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
588 if (StringRef(ArgumentFragment.
begin()->Spelling)
589 .starts_with(
"type-parameter")) {
590 std::string ProperArgName =
T.getAsString();
591 ArgumentFragment.
begin()->Spelling.swap(ProperArgName);
593 Fragments.
append(std::move(ArgumentFragment))
601DeclarationFragmentsBuilder::getFragmentsForParam(
const ParmVarDecl *Param) {
604 auto *TSInfo = Param->getTypeSourceInfo();
607 : Param->getASTContext().getUnqualifiedObjCPointerType(
612 findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
617 getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
619 TypeFragments.
append(getFragmentsForType(
T, Param->getASTContext(), After));
621 if (StringRef(TypeFragments.
begin()->Spelling)
622 .starts_with(
"type-parameter")) {
623 std::string ProperArgName = Param->getOriginalType().getAsString();
624 TypeFragments.
begin()->Spelling.swap(ProperArgName);
627 if (Param->isObjCMethodParameter()) {
629 .
append(std::move(TypeFragments))
635 Fragments.
append(std::move(TypeFragments));
638 if (T->isTypedefNameType() ||
639 (!T->isAnyPointerType() && !T->isBlockPointerType()))
644 .
append(std::move(After));
650 const NamedDecl *BlockDecl, FunctionTypeLoc &
Block,
652 DeclarationFragments Fragments;
654 DeclarationFragments RetTyAfter;
655 auto ReturnValueFragment = getFragmentsForType(
658 Fragments.
append(std::move(ReturnValueFragment))
659 .
append(std::move(RetTyAfter))
664 unsigned NumParams =
Block.getNumParams();
666 if (!BlockProto || NumParams == 0) {
673 for (
unsigned I = 0; I != NumParams; ++I) {
676 After.append(getFragmentsForParam(
Block.getParam(I)));
689 switch (
Func->getStorageClass()) {
703 llvm_unreachable(
"invalid for functions");
705 if (
Func->isConsteval())
708 else if (
Func->isConstexpr())
715 auto ReturnValueFragment =
716 getFragmentsForType(ReturnType,
Func->getASTContext(), After);
717 if (StringRef(ReturnValueFragment.begin()->Spelling)
718 .starts_with(
"type-parameter")) {
719 std::string ProperArgName = ReturnType.
getAsString();
720 ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
723 Fragments.
append(std::move(ReturnValueFragment));
729 if (
Func->getTemplateSpecializationInfo()) {
732 for (
unsigned i = 0, end =
Func->getNumParams(); i != end; ++i) {
736 getFragmentsForType(
Func->getParamDecl(i)->getType(),
737 Func->getParamDecl(i)->getASTContext(), After));
741 Fragments.
append(std::move(After));
744 unsigned NumParams =
Func->getNumParams();
745 for (
unsigned i = 0; i != NumParams; ++i) {
748 Fragments.
append(getFragmentsForParam(
Func->getParamDecl(i)));
751 if (
Func->isVariadic()) {
759 Func->getExceptionSpecType()));
784 if (!IntegerType.
isNull())
789 .
append(std::move(After));
802 if (Field->isMutable())
807 getFragmentsForType(Field->getType(), Field->getASTContext(), After))
826 if (!
Record->getName().empty())
843 if (!
Record->getName().empty())
856 Name =
Method->getNameAsString();
861 Name =
Method->getNameAsString();
865 .
append(std::move(After));
867 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
870 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
875 Method->getExceptionSpecType()));
883 StringRef Name =
Method->getName();
887 if (
Method->isConstexpr())
901 Method->getASTContext(), After))
904 .
append(std::move(After));
906 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
909 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
918 Method->getExceptionSpecType()));
928 if (ConversionFunction->isExplicit())
936 .
append(ConversionFunction->getConversionType().getAsString(),
939 for (
unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
943 Fragments.
append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
947 if (ConversionFunction->isConst())
963 Method->getASTContext(), After))
967 .
append(std::move(After));
969 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
972 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
981 Method->getExceptionSpecType()));
991 for (
unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
997 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
1005 Fragments.
append(
"typename",
1025 }
else if (
const auto *NTP =
1026 dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
1028 const auto TyFragments =
1029 getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
1030 Fragments.
append(std::move(TyFragments)).
append(std::move(After));
1032 if (NTP->isParameterPack())
1035 if (!NTP->getName().empty())
1040 if (NTP->hasDefaultArgument()) {
1042 raw_svector_ostream Output(ExprStr);
1043 NTP->getDefaultArgument().getArgument().print(
1044 NTP->getASTContext().getPrintingPolicy(), Output,
1049 }
else if (
const auto *TTP =
1050 dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1055 TTP->getTemplateParameters()->asArray()))
1058 .
append(TTP->wasDeclaredWithTypename() ?
"typename" :
"class",
1061 if (TTP->isParameterPack())
1064 if (!TTP->getName().empty())
1068 if (TTP->hasDefaultArgument()) {
1069 const auto Default = TTP->getDefaultArgument();
1090 for (
unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
1095 const auto &CTA = TemplateArguments[i];
1096 switch (CTA.getKind()) {
1100 getFragmentsForType(CTA.getAsType(), Context, After);
1102 if (StringRef(ArgumentFragment.
begin()->Spelling)
1103 .starts_with(
"type-parameter")) {
1104 if (TemplateArgumentLocs.has_value() &&
1105 TemplateArgumentLocs->size() > i) {
1106 std::string ProperArgName = TemplateArgumentLocs.value()[i]
1107 .getTypeSourceInfo()
1110 ArgumentFragment.
begin()->Spelling.swap(ProperArgName);
1112 auto &Spelling = ArgumentFragment.
begin()->Spelling;
1114 raw_string_ostream OutStream(Spelling);
1115 CTA.print(Context.getPrintingPolicy(), OutStream,
false);
1119 Fragments.
append(std::move(ArgumentFragment));
1123 const auto *VD = CTA.getAsDecl();
1126 Fragments.
append(VD->getNameAsString(),
1136 CTA.getAsIntegral().toString(Str);
1142 const auto SVTy = CTA.getStructuralValueType();
1143 Fragments.
append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1151 raw_string_ostream Stream(Str);
1152 CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1154 if (
const auto *TemplDecl =
1155 CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1173 raw_svector_ostream Output(ExprStr);
1174 CTA.getAsExpr()->printPretty(Output,
nullptr,
1175 Context.getPrintingPolicy());
1195 Concept->getTemplateParameters()->asArray()))
1231 std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs = {};
1232 if (
auto *TemplateArgs =
Decl->getTemplateArgsAsWritten()) {
1233 TemplateArgumentLocs = TemplateArgs->arguments();
1247 TemplateArgumentLocs))
1261 Decl->getTemplateParameters()->asArray()))
1270 Decl->getTemplateArgsAsWritten()->arguments()))
1290 Decl->getTemplateArgsAsWritten()->arguments()))
1305 Decl->getTemplateParameters()->asArray()))
1313 Decl->getTemplateArgsAsWritten()->arguments()))
1328 Decl->getTemplateParameters()->asArray()))
1360 for (
unsigned i = 0; i < numParameters; ++i) {
1380 auto *
Interface = Category->getClassInterface();
1390 .
append(Category->getName(),
1411 .
append(SuperClass->getName(),
1423 if (
Method->isClassMethod())
1425 else if (
Method->isInstanceMethod())
1431 Method->getASTContext(), After))
1432 .
append(std::move(After))
1445 for (
unsigned i = 0, end =
Method->param_size(); i != end; ++i) {
1451 ParamID.append(
":");
1457 Fragments.
append(getFragmentsForParam(Param));
1470 const auto Attributes =
Property->getPropertyAttributesAsWritten();
1477 auto RenderAttribute =
1483 if ((Attributes & Kind) && !Spelling.empty()) {
1488 Fragments.
append(Spelling,
1511 "unsafe_unretained");
1515 Property->getGetterName().getAsString());
1517 Property->getSetterName().getAsString());
1522 if (
const auto Nullability =
1523 AttributedType::stripOuterNullability(
Type)) {
1528 Fragments.
append(
"null_resettable",
1545 findTypeLocForBlockDecl(
Property->getTypeSourceInfo(), BlockLoc,
1548 auto PropType =
Property->getType();
1551 .
append(getFragmentsForType(PropType,
Property->getASTContext(), After))
1555 getFragmentsForBlock(
Property, BlockLoc, BlockProtoLoc, After));
1560 .
append(std::move(After))
1570 .
append(Protocol->getName(),
1574 if (!Protocol->protocols().empty()) {
1577 It != Protocol->protocol_end(); It++) {
1579 if (It != Protocol->protocol_begin())
1584 Fragments.
append((*It)->getName(),
1599 .
append(getFragmentsForType(
Decl->getUnderlyingType(),
1601 .
append(std::move(After))
1637 }
else if (
Decl->getIdentifier()) {
1641 Fragments.
append(
Decl->getDeclName().getAsString(),
1653 if (
Method->isClassMethod())
1655 else if (
Method->isInstanceMethod())
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.
llvm::MachO::Record Record
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...
const clang::PrintingPolicy & getPrintingPolicy() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getUnqualifiedObjCPointerType(QualType type) const
getUnqualifiedObjCPointerType - Returns version of Objective-C pointer type with lifetime qualifier r...
Type source information for an attributed type.
Wrapper for source info for block pointers.
Represents a C++ conversion function within a class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
Represents a class template specialization, which refers to a class template with a given set of temp...
Declaration of a C++20 concept.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
DeclContext * getDeclContext()
TypeSourceInfo * getTypeSourceInfo() const
An instance of this object exists for each enum constant that is defined.
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
bool isVariadic() const
Whether this function prototype is variadic.
Declaration of a template function.
Wrapper for source info for functions.
const TypeClass * getTypePtr() const
Encapsulates the data about a macro definition (e.g.
bool isC99Varargs() const
bool isFunctionLike() const
ArrayRef< const IdentifierInfo * > params() const
unsigned getNumParams() const
This represents a decl that may have a name.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represent a C++ namespace.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
NamespaceAndPrefix getAsNamespaceAndPrefix() const
const Type * getAsType() 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.
Represents an ObjC class declaration.
ObjCMethodDecl - Represents an instance or class method declaration.
Represents one property declaration in an Objective-C interface.
Represents an Objective-C protocol declaration.
ObjCProtocolList::iterator protocol_iterator
Represents a parameter to a function.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Wrapper of type source information for a type with non-trivial direct qualifiers.
Represents a struct/union/class.
Declaration of a redeclarable template.
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
TypedefNameDecl * getTypedefNameForAnonDecl() const
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
@ Template
The template argument is a template name that was provided for a template template parameter.
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
@ Pack
The template argument is actually a parameter pack.
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
@ Type
The template argument is a type.
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
ArrayRef< NamedDecl * > asArray()
Base wrapper for a particular "section" of type source info.
UnqualTypeLoc getUnqualifiedLoc() const
Skips past any qualifiers, if this is qualified.
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
TypeLoc IgnoreParens() const
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
bool isFunctionPointerType() const
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isObjCObjectPointerType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
Base class for declarations which introduce a typedef-name.
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
static const char * getStorageClassSpecifierString(StorageClass SC)
Return the string used to specify the storage class SC.
bool isStaticDataMember() const
Determines whether this is a static data member.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a variable template specialization, which refers to a variable template with a given set o...
@ 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.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
bool isa(CodeGen::Address addr)
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
StorageClass
Storage classes.
@ Property
The type of a property.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive=false)
Retrieve the spelling of the given nullability kind.
const FunctionProtoType * T
@ Keyword
The name has been typo-corrected to a keyword.
@ Type
The name was classified as a type.
@ Concept
The name was classified as a concept name.
llvm::StringRef getAsString(SyncScope S)
U cast(CodeGen::Address addr)
ElaboratedTypeKeyword
The elaboration keyword that precedes a qualified type name or introduces an elaborated-type-specifie...
@ 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_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.
static StringRef getKeywordName(ElaboratedTypeKeyword Keyword)
const Type * Ty
The locally-unqualified type.
Qualifiers Quals
The local qualifiers.