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()) {
69 Fragment &
Last = Fragments.back();
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())
214 Fragments.
append(getFragmentsForNNS(NNS->
getPrefix(), Context, After));
237 Fragments.
append(Alias->getName(),
262 Fragments.
append(getFragmentsForType(
T, Context, After));
275 assert(
T &&
"invalid type");
292 Fragments.
append(getFragmentsForNNS(NNS, Context, After));
296 return Fragments.
append(getFragmentsForType(ET->desugar(), Context, After));
304 if (
const TypedefType *TypedefTy = dyn_cast<TypedefType>(
T)) {
307 std::string USR = TypedefResolver.getUSRForType(
QualType(
T, 0));
316 USR, TypedefResolver.getUnderlyingTypeDecl(
QualType(
T, 0)));
347 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
355 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
368 switch (AT->getSizeModifier()) {
385 CAT->getSize().toStringUnsigned(Size);
392 getFragmentsForType(AT->getElementType(), Context, After));
396 dyn_cast<TemplateSpecializationType>(
T)) {
397 const auto TemplName = TemplSpecTy->getTemplateName();
399 raw_string_ostream Stream(Str);
400 TemplName.print(Stream, Context.getPrintingPolicy(),
403 if (
const auto *TemplDecl = TemplName.getAsTemplateDecl())
410 TemplSpecTy->template_arguments(), Context, std::nullopt))
420 if (
const TagType *TagTy = dyn_cast<TagType>(
Base)) {
423 if (
Decl->getName().empty())
424 return Fragments.
append(
"{ ... }",
435 if (
const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(
Base)) {
436 const auto *
Decl = ObjCIT->getDecl();
454DeclarationFragmentsBuilder::getFragmentsForQualifiers(
const Qualifiers Quals) {
468 assert(!QT.
isNull() &&
"invalid type");
470 if (
const ParenType *PT = dyn_cast<ParenType>(QT)) {
472 return getFragmentsForType(PT->getInnerType(), Context, After)
479 getFragmentsForType(SQT.
Ty, Context, After);
481 TypeFragments.replace(
"bool", 0);
484 return TypeFragments;
504 return TypeFragments.appendSpace().append(std::move(QualsFragments));
513 if (!
Decl->isAnonymousNamespace())
552 Fragments.
append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
580 if (StringRef(ArgumentFragment.
begin()->Spelling)
581 .starts_with(
"type-parameter")) {
582 std::string ProperArgName =
T.getAsString();
583 ArgumentFragment.
begin()->Spelling.swap(ProperArgName);
585 Fragments.
append(std::move(ArgumentFragment))
593DeclarationFragmentsBuilder::getFragmentsForParam(
const ParmVarDecl *Param) {
604 findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
609 getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
613 if (StringRef(TypeFragments.
begin()->Spelling)
614 .starts_with(
"type-parameter")) {
616 TypeFragments.
begin()->Spelling.swap(ProperArgName);
621 .
append(std::move(TypeFragments))
627 Fragments.
append(std::move(TypeFragments));
633 .
append(std::move(After));
644 auto ReturnValueFragment = getFragmentsForType(
647 Fragments.
append(std::move(ReturnValueFragment))
648 .
append(std::move(RetTyAfter))
653 unsigned NumParams =
Block.getNumParams();
655 if (!BlockProto || NumParams == 0) {
662 for (
unsigned I = 0; I != NumParams; ++I) {
665 After.append(getFragmentsForParam(
Block.getParam(I)));
678 switch (
Func->getStorageClass()) {
692 llvm_unreachable(
"invalid for functions");
694 if (
Func->isConsteval())
697 else if (
Func->isConstexpr())
703 auto ReturnValueFragment =
704 getFragmentsForType(
Func->getReturnType(),
Func->getASTContext(), After);
705 if (StringRef(ReturnValueFragment.begin()->Spelling)
706 .starts_with(
"type-parameter")) {
707 std::string ProperArgName =
Func->getReturnType().getAsString();
708 ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
711 Fragments.
append(std::move(ReturnValueFragment))
716 if (
Func->getTemplateSpecializationInfo()) {
719 for (
unsigned i = 0, end =
Func->getNumParams(); i != end; ++i) {
723 getFragmentsForType(
Func->getParamDecl(i)->getType(),
724 Func->getParamDecl(i)->getASTContext(), After));
728 Fragments.
append(std::move(After));
731 unsigned NumParams =
Func->getNumParams();
732 for (
unsigned i = 0; i != NumParams; ++i) {
735 Fragments.
append(getFragmentsForParam(
Func->getParamDecl(i)));
738 if (
Func->isVariadic()) {
746 Func->getExceptionSpecType()));
771 if (!IntegerType.
isNull())
776 .
append(std::move(After));
789 if (Field->isMutable())
794 getFragmentsForType(Field->getType(), Field->getASTContext(), After))
813 if (!
Record->getName().empty())
830 if (!
Record->getName().empty())
842 if (
const auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) {
844 if (Constructor->isExplicit())
847 }
else if (isa<CXXDestructorDecl>(Method))
852 .
append(std::move(After));
854 for (
unsigned i = 0, end = Method->
getNumParams(); i != end; ++i) {
870 StringRef Name = Method->
getName();
888 .
append(std::move(After));
890 for (
unsigned i = 0, end = Method->
getNumParams(); i != end; ++i) {
912 if (ConversionFunction->isExplicit())
920 .
append(ConversionFunction->getConversionType().getAsString(),
923 for (
unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
927 Fragments.
append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
931 if (ConversionFunction->isConst())
951 .
append(std::move(After));
953 for (
unsigned i = 0, end = Method->
getNumParams(); i != end; ++i) {
975 for (
unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
981 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
989 Fragments.
append(
"typename",
1009 }
else if (
const auto *NTP =
1010 dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
1012 const auto TyFragments =
1013 getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
1014 Fragments.
append(std::move(TyFragments)).
append(std::move(After));
1016 if (NTP->isParameterPack())
1019 if (!NTP->getName().empty())
1024 if (NTP->hasDefaultArgument()) {
1026 raw_svector_ostream Output(ExprStr);
1027 NTP->getDefaultArgument().getArgument().print(
1028 NTP->getASTContext().getPrintingPolicy(), Output,
1033 }
else if (
const auto *TTP =
1034 dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1039 TTP->getTemplateParameters()->asArray()))
1042 .
append(TTP->wasDeclaredWithTypename() ?
"typename" :
"class",
1045 if (TTP->isParameterPack())
1048 if (!TTP->getName().empty())
1052 if (TTP->hasDefaultArgument()) {
1053 const auto Default = TTP->getDefaultArgument();
1074 for (
unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
1079 const auto &CTA = TemplateArguments[i];
1080 switch (CTA.getKind()) {
1084 getFragmentsForType(CTA.getAsType(), Context, After);
1086 if (StringRef(ArgumentFragment.
begin()->Spelling)
1087 .starts_with(
"type-parameter")) {
1088 if (TemplateArgumentLocs.has_value() &&
1089 TemplateArgumentLocs->size() > i) {
1090 std::string ProperArgName = TemplateArgumentLocs.value()[i]
1091 .getTypeSourceInfo()
1094 ArgumentFragment.
begin()->Spelling.swap(ProperArgName);
1096 auto &Spelling = ArgumentFragment.
begin()->Spelling;
1098 raw_string_ostream OutStream(Spelling);
1099 CTA.print(Context.getPrintingPolicy(), OutStream,
false);
1104 Fragments.
append(std::move(ArgumentFragment));
1108 const auto *VD = CTA.getAsDecl();
1111 Fragments.
append(VD->getNameAsString(),
1121 CTA.getAsIntegral().toString(Str);
1127 const auto SVTy = CTA.getStructuralValueType();
1128 Fragments.
append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1136 raw_string_ostream Stream(Str);
1137 CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1139 if (
const auto *TemplDecl =
1140 CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1158 raw_svector_ostream Output(ExprStr);
1159 CTA.getAsExpr()->printPretty(Output,
nullptr,
1160 Context.getPrintingPolicy());
1180 Concept->getTemplateParameters()->asArray()))
1185 .
append(Concept->getName().str(),
1202 if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
1223 cast<CXXRecordDecl>(
Decl)))
1228 Decl->getTemplateArgsAsWritten()->arguments()))
1242 Decl->getTemplateParameters()->asArray()))
1246 cast<CXXRecordDecl>(
Decl)))
1251 Decl->getTemplateArgsAsWritten()->arguments()))
1271 Decl->getTemplateArgsAsWritten()->arguments()))
1286 Decl->getTemplateParameters()->asArray()))
1294 Decl->getTemplateArgsAsWritten()->arguments()))
1309 Decl->getTemplateParameters()->asArray()))
1338 if (MI->isFunctionLike()) {
1340 unsigned numParameters = MI->getNumParams();
1341 if (MI->isC99Varargs())
1343 for (
unsigned i = 0; i < numParameters; ++i) {
1346 Fragments.
append(MI->params()[i]->getName(),
1349 if (MI->isVariadic()) {
1350 if (numParameters && MI->isC99Varargs())
1394 .
append(SuperClass->getName(),
1415 .
append(std::move(After))
1428 for (
unsigned i = 0, end = Method->
param_size(); i != end; ++i) {
1434 ParamID.append(
":");
1440 Fragments.
append(getFragmentsForParam(Param));
1453 const auto Attributes =
Property->getPropertyAttributesAsWritten();
1460 auto RenderAttribute =
1466 if ((Attributes & Kind) && !Spelling.empty()) {
1471 Fragments.
append(Spelling,
1494 "unsafe_unretained");
1498 Property->getGetterName().getAsString());
1500 Property->getSetterName().getAsString());
1505 if (
const auto Nullability =
1511 Fragments.
append(
"null_resettable",
1528 findTypeLocForBlockDecl(
Property->getTypeSourceInfo(), BlockLoc,
1531 auto PropType =
Property->getType();
1534 .
append(getFragmentsForType(PropType,
Property->getASTContext(), After))
1538 getFragmentsForBlock(
Property, BlockLoc, BlockProtoLoc, After));
1543 .
append(std::move(After))
1553 .
append(Protocol->getName(),
1557 if (!Protocol->protocols().empty()) {
1560 It != Protocol->protocol_end(); It++) {
1562 if (It != Protocol->protocol_begin())
1567 Fragments.
append((*It)->getName(),
1582 .
append(getFragmentsForType(
Decl->getUnderlyingType(),
1584 .
append(std::move(After))
1603 if (isa<CXXConstructorDecl>(
Decl) || isa<CXXDestructorDecl>(
Decl))
1606 else if (isa<CXXConversionDecl>(
Decl)) {
1610 }
else if (isa<CXXMethodDecl>(
Decl) &&
1611 cast<CXXMethodDecl>(
Decl)->isOverloadedOperator()) {
1614 }
else if (
Decl->getIdentifier()) {
1618 Fragments.
append(
Decl->getDeclName().getAsString(),
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...
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...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Type source information for an attributed type.
static std::optional< NullabilityKind > stripOuterNullability(QualType &T)
Strip off the top-level nullability annotation on the given type, if it's there.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
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.
Represents the canonical version of C arrays with a specified constant size.
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
Represents a type that was referred to using an elaborated type keyword, e.g., struct S,...
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.
const ParmVarDecl * getParamDecl(unsigned i) const
ExceptionSpecificationType getExceptionSpecType() const
Gets the ExceptionSpecificationType as declared.
QualType getReturnType() const
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
bool isVariadic() const
Whether this function prototype is variadic.
Declaration of a template function.
Wrapper for source info for functions.
StringRef getName() const
Return the actual identifier string.
const TypeClass * getTypePtr() const
An lvalue reference type, per C++11 [dcl.ref].
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
const MacroInfo * getMacroInfo() const
This represents a decl that may have a name.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Represents a C++ namespace alias.
Represent a C++ namespace.
bool isAnonymousNamespace() const
Returns true if this is an anonymous namespace declaration.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
IdentifierInfo * getAsIdentifier() const
Retrieve the identifier stored in this nested name specifier.
NestedNameSpecifier * getPrefix() const
Return the prefix of this nested name specifier.
@ NamespaceAlias
A namespace alias, stored as a NamespaceAliasDecl*.
@ TypeSpec
A type, stored as a Type*.
@ TypeSpecWithTemplate
A type that was preceded by the 'template' keyword, stored as a Type*.
@ Super
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Identifier
An identifier, stored as an IdentifierInfo*.
@ Global
The global specifier '::'. There is no stored value.
@ Namespace
A namespace, stored as a NamespaceDecl*.
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
ObjCCategoryDecl - Represents a category declaration.
Represents an ObjC class declaration.
ObjCMethodDecl - Represents an instance or class method declaration.
unsigned param_size() const
Selector getSelector() const
bool isInstanceMethod() const
ParmVarDecl * getParamDecl(unsigned Idx)
QualType getReturnType() const
bool isClassMethod() const
Represents a pointer to an Objective C object.
bool isObjCQualifiedIdType() const
True if this is equivalent to 'id.
bool isObjCIdOrClassType() const
True if this is equivalent to the 'id' or 'Class' type,.
Represents one property declaration in an Objective-C interface.
Represents an Objective-C protocol declaration.
ObjCProtocolList::iterator protocol_iterator
Sugar for parentheses used when specifying types.
Represents a parameter to a function.
bool isObjCMethodParameter() const
QualType getOriginalType() const
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.
The collection of all-type qualifiers we support.
An rvalue reference type, per C++11 [dcl.ref].
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
Represents the declaration of a struct/union/class/enum.
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()
Represents a type template specialization; the template must be a class template, a type alias templa...
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.
static StringRef getKeywordName(ElaboratedTypeKeyword Keyword)
The base class of the type hierarchy.
bool isBlockPointerType() const
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.
bool isObjCIdType() const
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.
@ 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
llvm::StringRef getAsString(SyncScope S)
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.
A std::pair-like structure for storing a qualified type split into its local qualifiers and its local...
const Type * Ty
The locally-unqualified type.
Qualifiers Quals
The local qualifiers.