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)) {
265 getFragmentsForType(AT->getModifiedType(), Context, After));
269 if (
auto Nullability = AT->getImmediateNullability())
282 if (
const TypedefType *TypedefTy = dyn_cast<TypedefType>(
T)) {
283 const TypedefNameDecl *
Decl = TypedefTy->getDecl();
284 TypedefUnderlyingTypeResolver TypedefResolver(Context);
285 std::string USR = TypedefResolver.getUSRForType(QualType(
T, 0));
296 getFragmentsForNNS(TypedefTy->getQualifier(), Context, After));
298 if (TypedefTy->isObjCIdType()) {
305 USR, TypedefResolver.getUnderlyingTypeDecl(QualType(
T, 0)));
312 Fragments.
append(getFragmentsForType(PointeeT, Context, After));
323 !
T->
getAs<ObjCObjectPointerType>()->isObjCIdOrClassType()) {
329 if (!
T->
getAs<ObjCObjectPointerType>()->isObjCQualifiedIdType()) {
338 if (
const LValueReferenceType *LRT = dyn_cast<LValueReferenceType>(
T))
341 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
346 if (
const RValueReferenceType *RRT = dyn_cast<RValueReferenceType>(
T))
349 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
362 switch (AT->getSizeModifier()) {
373 if (
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
378 SmallString<128>
Size;
379 CAT->getSize().toStringUnsigned(Size);
386 getFragmentsForType(AT->getElementType(), Context, After));
389 if (
const TemplateSpecializationType *TemplSpecTy =
390 dyn_cast<TemplateSpecializationType>(
T)) {
398 auto TemplName = TemplSpecTy->getTemplateName();
400 raw_string_ostream Stream(Str);
403 SmallString<64> USR(
"");
404 if (
const auto *QTN = TemplName.getAsQualifiedTemplateName()) {
405 Fragments.
append(getFragmentsForNNS(QTN->getQualifier(), Context, After));
406 TemplName = QTN->getUnderlyingTemplate();
408 if (
const auto *TemplDecl = TemplName.getAsTemplateDecl())
416 TemplSpecTy->template_arguments(), Context, std::nullopt))
422 if (
const TagType *TagTy = dyn_cast<TagType>(
T)) {
430 Fragments.
append(getFragmentsForNNS(TagTy->getQualifier(), Context, After));
432 const TagDecl *
Decl = TagTy->getDecl();
434 if (
Decl->getName().empty())
435 return Fragments.
append(
"{ ... }",
437 SmallString<128> TagUSR;
450 if (
const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(Base)) {
451 const auto *
Decl = ObjCIT->getDecl();
452 SmallString<128> USR;
460 SmallString<128> USR;
469DeclarationFragmentsBuilder::getFragmentsForQualifiers(
const Qualifiers Quals) {
470 DeclarationFragments Fragments;
483 assert(!QT.
isNull() &&
"invalid type");
485 if (
const ParenType *PT = dyn_cast<ParenType>(QT)) {
487 return getFragmentsForType(PT->getInnerType(), Context, After)
491 const SplitQualType SQT = QT.
split();
492 DeclarationFragments QualsFragments = getFragmentsForQualifiers(SQT.
Quals),
494 getFragmentsForType(SQT.
Ty, Context, After);
496 TypeFragments.replace(
"bool", 0);
499 return TypeFragments;
519 return TypeFragments.appendSpace().append(std::move(QualsFragments));
528 if (!
Decl->isAnonymousNamespace())
567 Fragments.
append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
595 if (StringRef(ArgumentFragment.
begin()->Spelling)
596 .starts_with(
"type-parameter")) {
597 std::string ProperArgName =
T.getAsString();
598 ArgumentFragment.
begin()->Spelling.swap(ProperArgName);
600 Fragments.
append(std::move(ArgumentFragment))
608DeclarationFragmentsBuilder::getFragmentsForParam(
const ParmVarDecl *Param) {
611 auto *TSInfo = Param->getTypeSourceInfo();
614 : Param->getASTContext().getUnqualifiedObjCPointerType(
619 findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
624 getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
626 TypeFragments.
append(getFragmentsForType(
T, Param->getASTContext(), After));
628 if (StringRef(TypeFragments.
begin()->Spelling)
629 .starts_with(
"type-parameter")) {
630 std::string ProperArgName = Param->getOriginalType().getAsString();
631 TypeFragments.
begin()->Spelling.swap(ProperArgName);
634 if (Param->isObjCMethodParameter()) {
636 .
append(std::move(TypeFragments))
646 Fragments.
append(std::move(TypeFragments));
649 if (T->isTypedefNameType() ||
650 (!T->isAnyPointerType() && !T->isBlockPointerType()) || TrailingKeyword)
655 .
append(std::move(After));
661 const NamedDecl *BlockDecl, FunctionTypeLoc &
Block,
663 DeclarationFragments Fragments;
665 DeclarationFragments RetTyAfter;
666 auto ReturnValueFragment = getFragmentsForType(
669 Fragments.
append(std::move(ReturnValueFragment))
670 .
append(std::move(RetTyAfter))
675 unsigned NumParams =
Block.getNumParams();
677 if (!BlockProto || NumParams == 0) {
684 for (
unsigned I = 0; I != NumParams; ++I) {
687 After.append(getFragmentsForParam(
Block.getParam(I)));
700 switch (
Func->getStorageClass()) {
714 llvm_unreachable(
"invalid for functions");
716 if (
Func->isConsteval())
719 else if (
Func->isConstexpr())
726 auto ReturnValueFragment =
727 getFragmentsForType(ReturnType,
Func->getASTContext(), After);
728 if (StringRef(ReturnValueFragment.begin()->Spelling)
729 .starts_with(
"type-parameter")) {
730 std::string ProperArgName = ReturnType.
getAsString();
731 ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
737 bool ReturnTrailingKeyword = ReturnValueFragment.endsWithKeyword();
738 Fragments.
append(std::move(ReturnValueFragment));
744 if (
Func->getTemplateSpecializationInfo()) {
747 for (
unsigned i = 0, end =
Func->getNumParams(); i != end; ++i) {
751 getFragmentsForType(
Func->getParamDecl(i)->getType(),
752 Func->getParamDecl(i)->getASTContext(), After));
756 Fragments.
append(std::move(After));
759 unsigned NumParams =
Func->getNumParams();
760 for (
unsigned i = 0; i != NumParams; ++i) {
763 Fragments.
append(getFragmentsForParam(
Func->getParamDecl(i)));
766 if (
Func->isVariadic()) {
774 Func->getExceptionSpecType()));
799 if (!IntegerType.
isNull())
804 .
append(std::move(After));
817 if (Field->isMutable())
822 getFragmentsForType(Field->getType(), Field->getASTContext(), After))
841 if (!
Record->getName().empty())
858 if (!
Record->getName().empty())
871 Name =
Method->getNameAsString();
876 Name =
Method->getNameAsString();
880 .
append(std::move(After));
882 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
885 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
890 Method->getExceptionSpecType()));
898 StringRef Name =
Method->getName();
902 if (
Method->isConstexpr())
916 Method->getASTContext(), After))
919 .
append(std::move(After));
921 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
924 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
933 Method->getExceptionSpecType()));
943 if (ConversionFunction->isExplicit())
951 .
append(ConversionFunction->getConversionType().getAsString(),
954 for (
unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
958 Fragments.
append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
962 if (ConversionFunction->isConst())
978 Method->getASTContext(), After))
982 .
append(std::move(After));
984 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
987 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
996 Method->getExceptionSpecType()));
1006 for (
unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
1012 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
1020 Fragments.
append(
"typename",
1040 }
else if (
const auto *NTP =
1041 dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
1043 const auto TyFragments =
1044 getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
1045 Fragments.
append(std::move(TyFragments)).
append(std::move(After));
1047 if (NTP->isParameterPack())
1050 if (!NTP->getName().empty())
1055 if (NTP->hasDefaultArgument()) {
1057 raw_svector_ostream Output(ExprStr);
1058 NTP->getDefaultArgument().getArgument().print(
1059 NTP->getASTContext().getPrintingPolicy(), Output,
1064 }
else if (
const auto *TTP =
1065 dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1070 TTP->getTemplateParameters()->asArray()))
1073 .
append(TTP->wasDeclaredWithTypename() ?
"typename" :
"class",
1076 if (TTP->isParameterPack())
1079 if (!TTP->getName().empty())
1083 if (TTP->hasDefaultArgument()) {
1084 const auto Default = TTP->getDefaultArgument();
1105 for (
unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
1110 const auto &CTA = TemplateArguments[i];
1111 switch (CTA.getKind()) {
1115 getFragmentsForType(CTA.getAsType(), Context, After);
1117 if (StringRef(ArgumentFragment.
begin()->Spelling)
1118 .starts_with(
"type-parameter")) {
1119 if (TemplateArgumentLocs.has_value() &&
1120 TemplateArgumentLocs->size() > i) {
1121 std::string ProperArgName = TemplateArgumentLocs.value()[i]
1122 .getTypeSourceInfo()
1125 ArgumentFragment.
begin()->Spelling.swap(ProperArgName);
1127 auto &Spelling = ArgumentFragment.
begin()->Spelling;
1129 raw_string_ostream OutStream(Spelling);
1130 CTA.print(Context.getPrintingPolicy(), OutStream,
false);
1134 Fragments.
append(std::move(ArgumentFragment));
1138 const auto *VD = CTA.getAsDecl();
1141 Fragments.
append(VD->getNameAsString(),
1151 CTA.getAsIntegral().toString(Str);
1157 const auto SVTy = CTA.getStructuralValueType();
1158 Fragments.
append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1166 raw_string_ostream Stream(Str);
1167 CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1169 if (
const auto *TemplDecl =
1170 CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1188 raw_svector_ostream Output(ExprStr);
1189 CTA.getAsExpr()->printPretty(Output,
nullptr,
1190 Context.getPrintingPolicy());
1210 Concept->getTemplateParameters()->asArray()))
1246 std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs = {};
1247 if (
auto *TemplateArgs =
Decl->getTemplateArgsAsWritten()) {
1248 TemplateArgumentLocs = TemplateArgs->arguments();
1262 TemplateArgumentLocs))
1276 Decl->getTemplateParameters()->asArray()))
1285 Decl->getTemplateArgsAsWritten()->arguments()))
1305 Decl->getTemplateArgsAsWritten()->arguments()))
1320 Decl->getTemplateParameters()->asArray()))
1328 Decl->getTemplateArgsAsWritten()->arguments()))
1343 Decl->getTemplateParameters()->asArray()))
1375 for (
unsigned i = 0; i < numParameters; ++i) {
1395 auto *
Interface = Category->getClassInterface();
1405 .
append(Category->getName(),
1426 .
append(SuperClass->getName(),
1438 if (
Method->isClassMethod())
1440 else if (
Method->isInstanceMethod())
1446 Method->getASTContext(), After))
1447 .
append(std::move(After))
1460 for (
unsigned i = 0, end =
Method->param_size(); i != end; ++i) {
1466 ParamID.append(
":");
1472 Fragments.
append(getFragmentsForParam(Param));
1485 const auto Attributes =
Property->getPropertyAttributesAsWritten();
1492 auto RenderAttribute =
1498 if ((Attributes & Kind) && !Spelling.empty()) {
1503 Fragments.
append(Spelling,
1526 "unsafe_unretained");
1530 Property->getGetterName().getAsString());
1532 Property->getSetterName().getAsString());
1537 if (
const auto Nullability =
1538 AttributedType::stripOuterNullability(
Type)) {
1543 Fragments.
append(
"null_resettable",
1560 findTypeLocForBlockDecl(
Property->getTypeSourceInfo(), BlockLoc,
1563 auto PropType =
Property->getType();
1566 .
append(getFragmentsForType(PropType,
Property->getASTContext(), After))
1570 getFragmentsForBlock(
Property, BlockLoc, BlockProtoLoc, After));
1575 .
append(std::move(After))
1585 .
append(Protocol->getName(),
1589 if (!Protocol->protocols().empty()) {
1592 It != Protocol->protocol_end(); It++) {
1594 if (It != Protocol->protocol_begin())
1599 Fragments.
append((*It)->getName(),
1615 .
append(getFragmentsForType(
Decl->getUnderlyingType(),
1617 .
append(std::move(After))
1628 .
append(getFragmentsForType(
Decl->getUnderlyingType(),
1630 .
append(std::move(After));
1664 }
else if (
Decl->getIdentifier()) {
1668 Fragments.
append(
Decl->getDeclName().getAsString(),
1680 if (
Method->isClassMethod())
1682 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.
@ Default
Set to the current date and time.
@ 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.