llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
+ llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;
llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
llvm::FoldingSet<TypenameType> TypenameTypes;
/// specified typename decl.
QualType getTypedefType(TypedefDecl *Decl);
+ QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
+ QualType Replacement);
+
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
bool ParameterPack,
IdentifierInfo *Name = 0);
static bool classof(const TemplateTypeParmType *T) { return true; }
};
+/// \brief Represents the result of substituting a type for a template
+/// type parameter.
+///
+/// Within an instantiated template, all template type parameters have
+/// been replaced with these. They are used solely to record that a
+/// type was originally written as a template type parameter;
+/// therefore they are never canonical.
+class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode {
+ // The original type parameter.
+ const TemplateTypeParmType *Replaced;
+
+ SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon)
+ : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()),
+ Replaced(Param) { }
+
+ friend class ASTContext;
+
+public:
+ IdentifierInfo *getName() const { return Replaced->getName(); }
+
+ /// Gets the template parameter that was substituted for.
+ const TemplateTypeParmType *getReplacedParameter() const {
+ return Replaced;
+ }
+
+ /// Gets the type that was substituted for the template
+ /// parameter.
+ QualType getReplacementType() const {
+ return getCanonicalTypeInternal();
+ }
+
+ virtual void getAsStringInternal(std::string &InnerString,
+ const PrintingPolicy &Policy) const;
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getReplacementType(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getReplacedParameter(), getReplacementType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const TemplateTypeParmType *Replaced,
+ QualType Replacement) {
+ ID.AddPointer(Replaced);
+ ID.AddPointer(Replacement.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == SubstTemplateTypeParm;
+ }
+ static bool classof(const SubstTemplateTypeParmType *T) { return true; }
+};
+
/// \brief Represents the type of a template specialization as written
/// in the source code.
///
BuiltinType> {
};
+/// \brief Wrapper for template type parameters.
+class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc,
+ TemplateTypeParmType> {
+};
+
+/// \brief Wrapper for substituted template type parameters.
+class SubstTemplateTypeParmTypeLoc :
+ public TypeSpecTypeLoc<SubstTemplateTypeParmTypeLoc,
+ SubstTemplateTypeParmType> {
+};
/// \brief Wrapper for source info for ObjC interfaces.
class ObjCInterfaceTypeLoc : public TypeSpecTypeLoc<ObjCInterfaceTypeLoc,
VariableArrayType> {
};
-
// None of these types have proper implementations yet.
class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> {
ElaboratedType> {
};
-class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc,
- TemplateTypeParmType> {
-};
-
class TemplateSpecializationTypeLoc
: public TypeSpecTypeLoc<TemplateSpecializationTypeLoc,
TemplateSpecializationType> {
TYPE(Enum, TagType)
NON_CANONICAL_TYPE(Elaborated, Type)
DEPENDENT_TYPE(TemplateTypeParm, Type)
+NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
TYPE(TemplateSpecialization, Type)
NON_CANONICAL_TYPE(QualifiedName, Type)
DEPENDENT_TYPE(Typename, Type)
/// \brief a DecltypeType record.
TYPE_DECLTYPE = 24,
/// \brief An ElaboratedType record.
- TYPE_ELABORATED = 25
+ TYPE_ELABORATED = 25,
+ /// \brief A SubstTemplateTypeParmType record.
+ TYPE_SUBST_TEMPLATE_TYPE_PARM = 26
};
/// \brief The type IDs for special types constructed by semantic
break;
}
+ case Type::SubstTemplateTypeParm: {
+ return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
+ getReplacementType().getTypePtr());
+ }
+
case Type::Elaborated: {
return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType().getTypePtr());
}
return QualType(Decl->TypeForDecl, 0);
}
+/// \brief Retrieve a substitution-result type.
+QualType
+ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
+ QualType Replacement) {
+ assert(Replacement->isCanonical()
+ && "replacement types must always be canonical");
+
+ llvm::FoldingSetNodeID ID;
+ SubstTemplateTypeParmType::Profile(ID, Parm, Replacement);
+ void *InsertPos = 0;
+ SubstTemplateTypeParmType *SubstParm
+ = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!SubstParm) {
+ SubstParm = new (*this, TypeAlignment)
+ SubstTemplateTypeParmType(Parm, Replacement);
+ Types.push_back(SubstParm);
+ SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
+ }
+
+ return QualType(SubstParm, 0);
+}
+
/// \brief Retrieve the template type parameter type for a template
/// parameter or parameter pack with the given depth, index, and (optionally)
/// name.
case TypeOfExpr:
case TypeOf:
case TemplateTypeParm:
+ case SubstTemplateTypeParm:
case TemplateSpecialization:
case QualifiedName:
case Typename:
InnerString = Name->getName() + InnerString;
}
+void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
+ getReplacementType().getAsStringInternal(InnerString, Policy);
+}
+
std::string
TemplateSpecializationType::PrintTemplateArgumentList(
const TemplateArgument *Args,
Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos);
}
+
+ case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
+ unsigned Idx = 0;
+ QualType Parm = GetType(Record[Idx++]);
+ QualType Replacement = GetType(Record[Idx++]);
+ return
+ Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
+ Replacement);
+ }
}
// Suppress a GCC warning
return QualType();
void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
+void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
+ SubstTemplateTypeParmTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
Code = pch::TYPE_ELABORATED;
}
+void
+PCHTypeWriter::VisitSubstTemplateTypeParmType(
+ const SubstTemplateTypeParmType *T) {
+ Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
+ Writer.AddTypeRef(T->getReplacementType(), Record);
+ Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM;
+}
+
void
PCHTypeWriter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
}
+void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
+ SubstTemplateTypeParmTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
#include "clang/Basic/TargetInfo.h"
using namespace clang;
+/// Determines whether we should have an a.k.a. clause when
+/// pretty-printing a type. There are two main criteria:
+///
+/// 1) Some types provide very minimal sugar that doesn't impede the
+/// user's understanding --- for example, elaborated type
+/// specifiers. If this is all the sugar we see, we don't want an
+/// a.k.a. clause.
+/// 2) Some types are technically sugared but are much more familiar
+/// when seen in their sugared form --- for example, va_list,
+/// vector types, and the magic Objective C types. We don't
+/// want to desugar these, even if we do produce an a.k.a. clause.
+static bool ShouldAKA(ASTContext &Context, QualType QT,
+ QualType& DesugaredQT) {
+
+ bool AKA = false;
+ QualifierCollector Qc;
+
+ while (true) {
+ const Type *Ty = Qc.strip(QT);
+
+ // Don't aka just because we saw an elaborated type...
+ if (isa<ElaboratedType>(Ty)) {
+ QT = cast<ElaboratedType>(Ty)->desugar();
+ continue;
+ }
+
+ // ...or a qualified name type...
+ if (isa<QualifiedNameType>(Ty)) {
+ QT = cast<QualifiedNameType>(Ty)->desugar();
+ continue;
+ }
+
+ // ...or a substituted template type parameter.
+ if (isa<SubstTemplateTypeParmType>(Ty)) {
+ QT = cast<SubstTemplateTypeParmType>(Ty)->desugar();
+ continue;
+ }
+
+ // Don't desugar template specializations.
+ if (isa<TemplateSpecializationType>(Ty))
+ break;
+
+ // Don't desugar magic Objective-C types.
+ if (QualType(Ty,0) == Context.getObjCIdType() ||
+ QualType(Ty,0) == Context.getObjCClassType() ||
+ QualType(Ty,0) == Context.getObjCSelType() ||
+ QualType(Ty,0) == Context.getObjCProtoType())
+ break;
+
+ // Don't desugar va_list.
+ if (QualType(Ty,0) == Context.getBuiltinVaListType())
+ break;
+
+ // Otherwise, do a single-step desugar.
+ QualType Underlying;
+ bool IsSugar = false;
+ switch (Ty->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Base)
+#define TYPE(Class, Base) \
+ case Type::Class: { \
+ const Class##Type *CTy = cast<Class##Type>(Ty); \
+ if (CTy->isSugared()) { \
+ IsSugar = true; \
+ Underlying = CTy->desugar(); \
+ } \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+
+ // If it wasn't sugared, we're done.
+ if (!IsSugar)
+ break;
+
+ // If the desugared type is a vector type, we don't want to expand
+ // it, it will turn into an attribute mess. People want their "vec4".
+ if (isa<VectorType>(Underlying))
+ break;
+
+ // Otherwise, we're tearing through something opaque; note that
+ // we'll eventually need an a.k.a. clause and keep going.
+ AKA = true;
+ QT = Underlying;
+ continue;
+ }
+
+ // If we ever tore through opaque sugar
+ if (AKA) {
+ DesugaredQT = Qc.apply(QT);
+ return true;
+ }
+
+ return false;
+}
+
/// \brief Convert the given type to a string suitable for printing as part of
/// a diagnostic.
///
// FIXME: Playing with std::string is really slow.
std::string S = Ty.getAsString(Context.PrintingPolicy);
- // If this is a sugared type (like a typedef, typeof, etc), then unwrap one
- // level of the sugar so that the type is more obvious to the user.
- QualType DesugaredTy = Ty.getDesugaredType();
-
- if (Ty != DesugaredTy &&
- // If the desugared type is a vector type, we don't want to expand it,
- // it will turn into an attribute mess. People want their "vec4".
- !isa<VectorType>(DesugaredTy) &&
-
- // Don't aka just because we saw an elaborated type...
- (!isa<ElaboratedType>(Ty) ||
- cast<ElaboratedType>(Ty)->desugar() != DesugaredTy) &&
-
- // ...or a qualified name type...
- (!isa<QualifiedNameType>(Ty) ||
- cast<QualifiedNameType>(Ty)->desugar() != DesugaredTy) &&
-
- // ...or a non-dependent template specialization.
- (!isa<TemplateSpecializationType>(Ty) || Ty->isDependentType()) &&
-
- // Don't desugar magic Objective-C types.
- Ty.getUnqualifiedType() != Context.getObjCIdType() &&
- Ty.getUnqualifiedType() != Context.getObjCClassType() &&
- Ty.getUnqualifiedType() != Context.getObjCSelType() &&
- Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
-
- // Not va_list.
- Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
+ // Consider producing an a.k.a. clause if removing all the direct
+ // sugar gives us something "significantly different".
+
+ QualType DesugaredTy;
+ if (ShouldAKA(Context, Ty, DesugaredTy)) {
S = "'"+S+"' (aka '";
S += DesugaredTy.getAsString(Context.PrintingPolicy);
S += "')";
== TemplateArgument::Type &&
"Template argument kind mismatch");
- return TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
+ QualType Replacement
+ = TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
+
+ // TODO: only do this uniquing once, at the start of instantiation.
+ return getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
}
// The template type parameter comes from an inner template (e.g.,
return QualType(T, 0);
}
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
+ const SubstTemplateTypeParmType *T) {
+ // Nothing to do
+ return QualType(T, 0);
+}
+
template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
const TemplateSpecializationType *T) {