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())
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");
259 getFragmentsForType(MQT->getUnderlyingType(), Context, After));
266 getFragmentsForType(AT->getModifiedType(), Context, After));
275 if (
const TypedefType *TypedefTy = dyn_cast<TypedefType>(
T)) {
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));
334 getFragmentsForType(LRT->getPointeeTypeAsWritten(), Context, After))
342 getFragmentsForType(RRT->getPointeeTypeAsWritten(), Context, After))
355 switch (AT->getSizeModifier()) {
372 CAT->getSize().toStringUnsigned(Size);
379 getFragmentsForType(AT->getElementType(), Context, After));
383 dyn_cast<TemplateSpecializationType>(
T)) {
391 auto TemplName = TemplSpecTy->getTemplateName();
393 raw_string_ostream Stream(Str);
394 TemplName.print(Stream, Context.getPrintingPolicy(),
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));
427 if (
Decl->getName().empty())
428 return Fragments.
append(
"{ ... }",
443 if (
const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(
Base)) {
444 const auto *
Decl = ObjCIT->getDecl();
462DeclarationFragmentsBuilder::getFragmentsForQualifiers(
const Qualifiers Quals) {
476 assert(!QT.
isNull() &&
"invalid type");
478 if (
const ParenType *PT = dyn_cast<ParenType>(QT)) {
480 return getFragmentsForType(PT->getInnerType(), Context, After)
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) {
612 findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
617 getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
621 if (StringRef(TypeFragments.
begin()->Spelling)
622 .starts_with(
"type-parameter")) {
624 TypeFragments.
begin()->Spelling.swap(ProperArgName);
629 .
append(std::move(TypeFragments))
635 Fragments.
append(std::move(TypeFragments));
641 .
append(std::move(After));
652 auto ReturnValueFragment = getFragmentsForType(
655 Fragments.
append(std::move(ReturnValueFragment))
656 .
append(std::move(RetTyAfter))
661 unsigned NumParams =
Block.getNumParams();
663 if (!BlockProto || NumParams == 0) {
670 for (
unsigned I = 0; I != NumParams; ++I) {
673 After.append(getFragmentsForParam(
Block.getParam(I)));
686 switch (
Func->getStorageClass()) {
700 llvm_unreachable(
"invalid for functions");
702 if (
Func->isConsteval())
705 else if (
Func->isConstexpr())
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);
720 Fragments.
append(std::move(ReturnValueFragment));
726 if (
Func->getTemplateSpecializationInfo()) {
729 for (
unsigned i = 0, end =
Func->getNumParams(); i != end; ++i) {
733 getFragmentsForType(
Func->getParamDecl(i)->getType(),
734 Func->getParamDecl(i)->getASTContext(), After));
738 Fragments.
append(std::move(After));
741 unsigned NumParams =
Func->getNumParams();
742 for (
unsigned i = 0; i != NumParams; ++i) {
745 Fragments.
append(getFragmentsForParam(
Func->getParamDecl(i)));
748 if (
Func->isVariadic()) {
756 Func->getExceptionSpecType()));
781 if (!IntegerType.
isNull())
786 .
append(std::move(After));
799 if (Field->isMutable())
804 getFragmentsForType(Field->getType(), Field->getASTContext(), After))
823 if (!
Record->getName().empty())
840 if (!
Record->getName().empty())
853 Name =
Method->getNameAsString();
857 }
else if (isa<CXXDestructorDecl>(
Method))
858 Name =
Method->getNameAsString();
862 .
append(std::move(After));
864 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
867 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
872 Method->getExceptionSpecType()));
880 StringRef Name =
Method->getName();
884 if (
Method->isConstexpr())
898 Method->getASTContext(), After))
901 .
append(std::move(After));
903 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
906 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
915 Method->getExceptionSpecType()));
925 if (ConversionFunction->isExplicit())
933 .
append(ConversionFunction->getConversionType().getAsString(),
936 for (
unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
940 Fragments.
append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
944 if (ConversionFunction->isConst())
960 Method->getASTContext(), After))
964 .
append(std::move(After));
966 for (
unsigned i = 0, end =
Method->getNumParams(); i != end; ++i) {
969 Fragments.
append(getFragmentsForParam(
Method->getParamDecl(i)));
978 Method->getExceptionSpecType()));
988 for (
unsigned i = 0, end = ParameterArray.size(); i != end; ++i) {
994 dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
1002 Fragments.
append(
"typename",
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));
1029 if (NTP->isParameterPack())
1032 if (!NTP->getName().empty())
1037 if (NTP->hasDefaultArgument()) {
1039 raw_svector_ostream Output(ExprStr);
1040 NTP->getDefaultArgument().getArgument().print(
1041 NTP->getASTContext().getPrintingPolicy(), Output,
1046 }
else if (
const auto *TTP =
1047 dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
1052 TTP->getTemplateParameters()->asArray()))
1055 .
append(TTP->wasDeclaredWithTypename() ?
"typename" :
"class",
1058 if (TTP->isParameterPack())
1061 if (!TTP->getName().empty())
1065 if (TTP->hasDefaultArgument()) {
1066 const auto Default = TTP->getDefaultArgument();
1087 for (
unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
1092 const auto &CTA = TemplateArguments[i];
1093 switch (CTA.getKind()) {
1097 getFragmentsForType(CTA.getAsType(), Context, After);
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()
1107 ArgumentFragment.
begin()->Spelling.swap(ProperArgName);
1109 auto &Spelling = ArgumentFragment.
begin()->Spelling;
1111 raw_string_ostream OutStream(Spelling);
1112 CTA.print(Context.getPrintingPolicy(), OutStream,
false);
1116 Fragments.
append(std::move(ArgumentFragment));
1120 const auto *VD = CTA.getAsDecl();
1123 Fragments.
append(VD->getNameAsString(),
1133 CTA.getAsIntegral().toString(Str);
1139 const auto SVTy = CTA.getStructuralValueType();
1140 Fragments.
append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
1148 raw_string_ostream Stream(Str);
1149 CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
1151 if (
const auto *TemplDecl =
1152 CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
1170 raw_svector_ostream Output(ExprStr);
1171 CTA.getAsExpr()->printPretty(Output,
nullptr,
1172 Context.getPrintingPolicy());
1192 Concept->getTemplateParameters()->asArray()))
1214 if (isa<TypeAliasTemplateDecl>(RedeclarableTemplate))
1228 std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs = {};
1229 if (
auto *TemplateArgs =
Decl->getTemplateArgsAsWritten()) {
1230 TemplateArgumentLocs = TemplateArgs->arguments();
1239 cast<CXXRecordDecl>(
Decl)))
1244 TemplateArgumentLocs))
1258 Decl->getTemplateParameters()->asArray()))
1262 cast<CXXRecordDecl>(
Decl)))
1267 Decl->getTemplateArgsAsWritten()->arguments()))
1287 Decl->getTemplateArgsAsWritten()->arguments()))
1302 Decl->getTemplateParameters()->asArray()))
1310 Decl->getTemplateArgsAsWritten()->arguments()))
1325 Decl->getTemplateParameters()->asArray()))
1357 for (
unsigned i = 0; i < numParameters; ++i) {
1408 .
append(SuperClass->getName(),
1420 if (
Method->isClassMethod())
1422 else if (
Method->isInstanceMethod())
1428 Method->getASTContext(), After))
1429 .
append(std::move(After))
1442 for (
unsigned i = 0, end =
Method->param_size(); i != end; ++i) {
1448 ParamID.append(
":");
1454 Fragments.
append(getFragmentsForParam(Param));
1467 const auto Attributes =
Property->getPropertyAttributesAsWritten();
1474 auto RenderAttribute =
1480 if ((Attributes & Kind) && !Spelling.empty()) {
1485 Fragments.
append(Spelling,
1508 "unsafe_unretained");
1512 Property->getGetterName().getAsString());
1514 Property->getSetterName().getAsString());
1519 if (
const auto Nullability =
1525 Fragments.
append(
"null_resettable",
1542 findTypeLocForBlockDecl(
Property->getTypeSourceInfo(), BlockLoc,
1545 auto PropType =
Property->getType();
1548 .
append(getFragmentsForType(PropType,
Property->getASTContext(), After))
1552 getFragmentsForBlock(
Property, BlockLoc, BlockProtoLoc, After));
1557 .
append(std::move(After))
1567 .
append(Protocol->getName(),
1571 if (!Protocol->protocols().empty()) {
1574 It != Protocol->protocol_end(); It++) {
1576 if (It != Protocol->protocol_begin())
1581 Fragments.
append((*It)->getName(),
1596 .
append(getFragmentsForType(
Decl->getUnderlyingType(),
1598 .
append(std::move(After))
1617 if (isa<CXXConstructorDecl>(
Decl)) {
1620 }
else if (isa<CXXDestructorDecl>(
Decl)) {
1621 Fragments.
append(cast<CXXDestructorDecl>(
Decl)->getNameAsString(),
1623 }
else if (isa<CXXConversionDecl>(
Decl)) {
1627 }
else if (isa<CXXMethodDecl>(
Decl) &&
1628 cast<CXXMethodDecl>(
Decl)->isOverloadedOperator()) {
1631 }
else if (isa<TagDecl>(
Decl) &&
1632 cast<TagDecl>(
Decl)->getTypedefNameForAnonDecl()) {
1634 }
else if (
Decl->getIdentifier()) {
1638 Fragments.
append(
Decl->getDeclName().getAsString(),
1650 if (
Method->isClassMethod())
1652 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...
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.
An attributed type is a type to which a type attribute has been applied.
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
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
An lvalue reference type, per C++11 [dcl.ref].
Encapsulates the data about a macro definition (e.g.
bool isC99Varargs() const
bool isFunctionLike() const
ArrayRef< const IdentifierInfo * > params() const
unsigned getNumParams() const
Sugar type that represents a type that was qualified by a qualifier written as a macro invocation.
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 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.
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.
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.
@ 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)
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)
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.