From 395b475a4474f1c7574d927ad142ca0c7997cbca Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Wed, 24 Jun 2009 19:06:50 +0000 Subject: [PATCH] Add a DecltypeType type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74099 91177308-0d34-0410-b5e6-96231b3b80d8 --- clang.xcodeproj/project.pbxproj | 4 ++-- include/clang/AST/ASTContext.h | 3 +++ include/clang/AST/Type.h | 15 +++++++++++++++ include/clang/AST/TypeNodes.def | 1 + include/clang/Frontend/PCHBitCodes.h | 4 +++- lib/AST/ASTContext.cpp | 17 +++++++++++++++++ lib/AST/Type.cpp | 15 +++++++++++++++ lib/CodeGen/CGDebugInfo.cpp | 3 +++ lib/Frontend/PCHReader.cpp | 5 ++++- lib/Frontend/PCHWriter.cpp | 5 +++++ lib/Sema/SemaTemplateInstantiate.cpp | 12 ++++++++++++ 11 files changed, 80 insertions(+), 4 deletions(-) diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 73ef1beeca..26be7bb0b7 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -694,8 +694,8 @@ DEF165220F8D46980098507F /* Util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Util.h; path = clang/Driver/Util.h; sourceTree = ""; }; DEF165230F8D46980098507F /* Phases.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Phases.h; path = clang/Driver/Phases.h; sourceTree = ""; }; DEF165240F8D46980098507F /* DriverDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DriverDiagnostic.h; path = clang/Driver/DriverDiagnostic.h; sourceTree = ""; }; - DEF165700F8FB34D0098507F /* PCHWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriter.cpp; path = lib/Frontend/PCHWriter.cpp; sourceTree = ""; }; - DEF165740F8FB3510098507F /* PCHReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReader.cpp; path = lib/Frontend/PCHReader.cpp; sourceTree = ""; }; + DEF165700F8FB34D0098507F /* PCHWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriter.cpp; path = lib/Frontend/PCHWriter.cpp; sourceTree = ""; tabWidth = 2; }; + DEF165740F8FB3510098507F /* PCHReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReader.cpp; path = lib/Frontend/PCHReader.cpp; sourceTree = ""; tabWidth = 2; }; DEF165780F8FB3690098507F /* PCHWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PCHWriter.h; path = clang/Frontend/PCHWriter.h; sourceTree = ""; }; DEF1657B0F8FB36E0098507F /* PCHReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PCHReader.h; path = clang/Frontend/PCHReader.h; sourceTree = ""; }; DEF1657E0F8FB3730098507F /* PCHBitCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PCHBitCodes.h; path = clang/Frontend/PCHBitCodes.h; sourceTree = ""; }; diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index b686b0edd3..2d35b4d990 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -360,6 +360,9 @@ public: QualType getTypeOfExprType(Expr *e); QualType getTypeOfType(QualType t); + /// getDecltypeType - C++0x decltype. + QualType getDecltypeType(Expr *e); + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType getTagDeclType(TagDecl *Decl); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index ca55ea670b..fbbd5c5505 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1358,6 +1358,21 @@ public: static bool classof(const TypeOfType *) { return true; } }; +/// DecltypeType (C++0x) +class DecltypeType : public Type { + Expr *E; + DecltypeType(Expr *E, QualType can); + friend class ASTContext; // ASTContext creates these. +public: + Expr *getUnderlyingExpr() const { return E; } + + virtual void getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } + static bool classof(const DecltypeType *) { return true; } +}; + class TagType : public Type { /// Stores the TagDecl associated with this type. The decl will /// point to the TagDecl that actually defines the entity (or is a diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 5555a9b0ae..64a09d8002 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -69,6 +69,7 @@ TYPE(FunctionNoProto, FunctionType) NON_CANONICAL_TYPE(Typedef, Type) NON_CANONICAL_TYPE(TypeOfExpr, Type) NON_CANONICAL_TYPE(TypeOf, Type) +NON_CANONICAL_TYPE(Decltype, Type) ABSTRACT_TYPE(Tag, Type) TYPE(Record, TagType) TYPE(Enum, TagType) diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index e546a12c49..63222725d5 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -387,7 +387,9 @@ namespace clang { /// \brief An ObjCQualifiedInterfaceType record. TYPE_OBJC_QUALIFIED_INTERFACE = 22, /// \brief An ObjCObjectPointerType record. - TYPE_OBJC_OBJECT_POINTER = 23 + TYPE_OBJC_OBJECT_POINTER = 23, + /// \brief a DecltypeType record. + TYPE_DECLTYPE = 24 }; /// \brief The type IDs for special types constructed by semantic diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b80142fef3..e23bb34b05 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -460,6 +460,10 @@ ASTContext::getTypeInfo(const Type *T) { case Type::TypeOf: return getTypeInfo(cast(T)->getUnderlyingType().getTypePtr()); + case Type::Decltype: + return getTypeInfo(cast(T)->getUnderlyingExpr()->getType() + .getTypePtr()); + case Type::QualifiedName: return getTypeInfo(cast(T)->getNamedType().getTypePtr()); @@ -1659,6 +1663,19 @@ QualType ASTContext::getTypeOfType(QualType tofType) { return QualType(tot, 0); } +/// getDecltypeType - Unlike many "get" functions, we don't unique +/// DecltypeType AST's. The only motivation to unique these nodes would be +/// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be +/// an issue. This doesn't effect the type checker, since it operates +/// on canonical type's (which are always unique). +QualType ASTContext::getDecltypeType(Expr *e) { + // FIXME: Use the right type here! + QualType Canonical = getCanonicalType(e->getType()); + DecltypeType *dt = new (*this, 8) DecltypeType(e, Canonical); + Types.push_back(dt); + return QualType(dt, 0); +} + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType ASTContext::getTagDeclType(TagDecl *Decl) { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 7b45b21e5d..9894adf8d0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1052,6 +1052,11 @@ TypeOfExprType::TypeOfExprType(Expr *E, QualType can) assert(!isa(can) && "Invalid canonical type"); } +DecltypeType::DecltypeType(Expr *E, QualType can) + : Type(Decltype, can, E->isTypeDependent()), E(E) { + assert(!isa(can) && "Invalid canonical type"); +} + TagType::TagType(TypeClass TC, TagDecl *D, QualType can) : Type(TC, can, D->isDependentType()), decl(D, 0) {} @@ -1421,6 +1426,16 @@ void TypeOfType::getAsStringInternal(std::string &InnerString, const PrintingPol InnerString = "typeof(" + Tmp + ")" + InnerString; } +void DecltypeType::getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const { + if (!InnerString.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. + InnerString = ' ' + InnerString; + std::string Str; + llvm::raw_string_ostream s(Str); + getUnderlyingExpr()->printPretty(s, 0, Policy); + InnerString = "decltype(" + s.str() + ")" + InnerString; +} + void FunctionNoProtoType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { // If needed for precedence reasons, wrap the inner part in grouping parens. if (!S.empty()) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index a2b8d13e3c..fb1fefe6ff 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -810,6 +810,9 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, case Type::TypeOf: return Slot = getOrCreateType(cast(Ty)->getUnderlyingType(), Unit); + case Type::Decltype: + return Slot = getOrCreateType(cast(Ty)->getUnderlyingExpr() + ->getType(), Unit); } return Slot; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 96f21f1128..0ee0c90645 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1822,7 +1822,10 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { QualType UnderlyingType = GetType(Record[0]); return Context->getTypeOfType(UnderlyingType); } - + + case pch::TYPE_DECLTYPE: + return Context->getDecltypeType(ReadTypeExpr()); + case pch::TYPE_RECORD: assert(Record.size() == 1 && "incorrect encoding of record type"); return Context->getTypeDeclType(cast(GetDecl(Record[0]))); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 3b1eb080f2..d1f9b975e9 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -185,6 +185,11 @@ void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) { Code = pch::TYPE_TYPEOF; } +void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) { + Writer.AddStmt(T->getUnderlyingExpr()); + Code = pch::TYPE_DECLTYPE; +} + void PCHTypeWriter::VisitTagType(const TagType *T) { Writer.AddDeclRef(T->getDecl(), Record); assert(!T->isBeingDefined() && diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 1c4e907d4d..0f677488c7 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -546,6 +546,18 @@ TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T, return SemaRef.Context.getTypeOfType(Underlying); } +QualType +TemplateTypeInstantiator::InstantiateDecltypeType(const DecltypeType *T, + unsigned Quals) const { + Sema::OwningExprResult E + = SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs); + + if (E.isInvalid()) + return QualType(); + + return SemaRef.Context.getDecltypeType(E.takeAs()); +} + QualType TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T, unsigned Quals) const {