Add a DecltypeType type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74099 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index b80142f..e23bb34 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -460,6 +460,10 @@
case Type::TypeOf:
return getTypeInfo(cast<TypeOfType>(T)->getUnderlyingType().getTypePtr());
+ case Type::Decltype:
+ return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType()
+ .getTypePtr());
+
case Type::QualifiedName:
return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr());
@@ -1659,6 +1663,19 @@
return QualType(tot, 0);
}
+/// getDecltypeType - Unlike many "get<Type>" 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 7b45b21..9894adf 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1052,6 +1052,11 @@
assert(!isa<TypedefType>(can) && "Invalid canonical type");
}
+DecltypeType::DecltypeType(Expr *E, QualType can)
+ : Type(Decltype, can, E->isTypeDependent()), E(E) {
+ assert(!isa<TypedefType>(can) && "Invalid canonical type");
+}
+
TagType::TagType(TypeClass TC, TagDecl *D, QualType can)
: Type(TC, can, D->isDependentType()), decl(D, 0) {}
@@ -1421,6 +1426,16 @@
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 a2b8d13..fb1fefe 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -810,6 +810,9 @@
case Type::TypeOf:
return Slot = getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(),
Unit);
+ case Type::Decltype:
+ return Slot = getOrCreateType(cast<DecltypeType>(Ty)->getUnderlyingExpr()
+ ->getType(), Unit);
}
return Slot;
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 96f21f1..0ee0c90 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1822,7 +1822,10 @@
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<RecordDecl>(GetDecl(Record[0])));
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 3b1eb08..d1f9b97 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -185,6 +185,11 @@
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 1c4e907..0f67748 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -546,6 +546,18 @@
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<Expr>());
+}
+
QualType
TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
unsigned Quals) const {