aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h4
-rw-r--r--include/clang/AST/CanonicalType.h8
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h9
-rw-r--r--include/clang/AST/Type.h33
-rw-r--r--include/clang/AST/TypeLoc.h47
-rw-r--r--include/clang/AST/TypeNodes.def1
-rw-r--r--include/clang/Basic/Specifiers.h2
-rw-r--r--include/clang/Sema/DeclSpec.h4
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--lib/AST/ASTContext.cpp18
-rw-r--r--lib/AST/ASTImporter.cpp21
-rw-r--r--lib/AST/ItaniumMangle.cpp16
-rw-r--r--lib/AST/MicrosoftMangle.cpp4
-rw-r--r--lib/AST/Type.cpp10
-rw-r--r--lib/AST/TypePrinter.cpp15
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp4
-rw-r--r--lib/Parse/ParseDeclCXX.cpp2
-rw-r--r--lib/Sema/DeclSpec.cpp2
-rw-r--r--lib/Sema/SemaDecl.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp5
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp7
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp2
-rw-r--r--lib/Sema/SemaType.cpp59
-rw-r--r--lib/Sema/TreeTransform.h35
-rw-r--r--lib/Serialization/ASTReader.cpp13
-rw-r--r--lib/Serialization/ASTWriter.cpp13
-rw-r--r--test/SemaCXX/underlying_type.cpp10
-rw-r--r--tools/libclang/CIndex.cpp8
29 files changed, 334 insertions, 27 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index f519af712c..4f4d949735 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -779,6 +779,10 @@ public:
/// getDecltypeType - C++0x decltype.
QualType getDecltypeType(Expr *e) const;
+ /// getUnaryTransformType - unary type transforms
+ QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType,
+ UnaryTransformType::UTTKind UKind) const;
+
/// getAutoType - C++0x deduced auto type.
QualType getAutoType(QualType DeducedType) const;
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index fb00d86301..2518814904 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -632,6 +632,14 @@ struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
};
+template <>
+struct CanProxyAdaptor<UnaryTransformType>
+ : public CanProxyBase<UnaryTransformType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind)
+};
+
template<>
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 33171bd003..d97bb376a0 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -750,6 +750,11 @@ DEF_TRAVERSE_TYPE(DecltypeType, {
TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
})
+DEF_TRAVERSE_TYPE(UnaryTransformType, {
+ TRY_TO(TraverseType(T->getBaseType()));
+ TRY_TO(TraverseType(T->getUnderlyingType()));
+ })
+
DEF_TRAVERSE_TYPE(AutoType, {
TRY_TO(TraverseType(T->getDeducedType()));
})
@@ -966,6 +971,10 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, {
TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
})
+DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
+ TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+ })
+
DEF_TRAVERSE_TYPELOC(AutoType, {
TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
})
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 1e8642f76a..b6c6b5616c 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -2825,6 +2825,39 @@ public:
Expr *E);
};
+/// \brief A unary type transform, which is a type constructed from another
+class UnaryTransformType : public Type {
+public:
+ enum UTTKind {
+ EnumUnderlyingType
+ };
+
+private:
+ /// The untransformed type.
+ QualType BaseType;
+ /// The transformed type if not dependent, otherwise the same as BaseType.
+ QualType UnderlyingType;
+
+ UTTKind UKind;
+protected:
+ UnaryTransformType(QualType BaseTy, QualType UnderlyingTy, UTTKind UKind,
+ QualType CanonicalTy);
+ friend class ASTContext;
+public:
+ bool isSugared() const { return !isDependentType(); }
+ QualType desugar() const { return UnderlyingType; }
+
+ QualType getUnderlyingType() const { return UnderlyingType; }
+ QualType getBaseType() const { return BaseType; }
+
+ UTTKind getUTTKind() const { return UKind; }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == UnaryTransform;
+ }
+ static bool classof(const UnaryTransformType *) { return true; }
+};
+
class TagType : public Type {
/// Stores the TagDecl associated with this type. The decl may point to any
/// TagDecl that declares the entity.
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index a1df744c2a..f5669f7fc0 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -1410,6 +1410,53 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
DecltypeType> {
};
+struct UnaryTransformTypeLocInfo {
+ // FIXME: While there's only one unary transform right now, future ones may
+ // need different representations
+ SourceLocation KWLoc, LParenLoc, RParenLoc;
+ TypeSourceInfo *UnderlyingTInfo;
+};
+
+class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ UnaryTransformTypeLoc,
+ UnaryTransformType,
+ UnaryTransformTypeLocInfo> {
+public:
+ SourceLocation getKWLoc() const { return getLocalData()->KWLoc; }
+ void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; }
+
+ SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; }
+ void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; }
+
+ SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; }
+
+ TypeSourceInfo* getUnderlyingTInfo() const {
+ return getLocalData()->UnderlyingTInfo;
+ }
+ void setUnderlyingTInfo(TypeSourceInfo *TInfo) {
+ getLocalData()->UnderlyingTInfo = TInfo;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getKWLoc(), getRParenLoc());
+ }
+
+ SourceRange getParensRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+ void setParensRange(SourceRange Range) {
+ setLParenLoc(Range.getBegin());
+ setRParenLoc(Range.getEnd());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKWLoc(Loc);
+ setRParenLoc(Loc);
+ setLParenLoc(Loc);
+ }
+};
+
class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
AutoTypeLoc,
AutoType> {
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index b2591cc0fb..0792d0d9b3 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -84,6 +84,7 @@ NON_CANONICAL_TYPE(Typedef, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type)
ABSTRACT_TYPE(Tag, Type)
TYPE(Record, TagType)
TYPE(Enum, TagType)
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 042fd02fbe..d21bda7d9a 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -54,7 +54,7 @@ namespace clang {
TST_typeofType,
TST_typeofExpr,
TST_decltype, // C++0x decltype
- TST_underlying_type, // __underlying_type for C++0x
+ TST_underlyingType, // __underlying_type for C++0x
TST_auto, // C++0x auto
TST_unknown_anytype, // __unknown_anytype extension
TST_error // erroneous type
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index d3e943ede0..be1f5f8c79 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -249,7 +249,7 @@ public:
static const TST TST_typeofType = clang::TST_typeofType;
static const TST TST_typeofExpr = clang::TST_typeofExpr;
static const TST TST_decltype = clang::TST_decltype;
- static const TST TST_underlying_type = clang::TST_underlying_type;
+ static const TST TST_underlyingType = clang::TST_underlyingType;
static const TST TST_auto = clang::TST_auto;
static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
static const TST TST_error = clang::TST_error;
@@ -346,7 +346,7 @@ private:
static bool isTypeRep(TST T) {
return (T == TST_typename || T == TST_typeofType ||
- T == TST_underlying_type);
+ T == TST_underlyingType);
}
static bool isExprRep(TST T) {
return (T == TST_typeofExpr || T == TST_decltype);
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index b6ee854a3b..2cbfd9f3d6 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -814,6 +814,9 @@ public:
QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
QualType BuildDecltypeType(Expr *E, SourceLocation Loc);
+ QualType BuildUnaryTransformType(QualType BaseType,
+ UnaryTransformType::UTTKind UKind,
+ SourceLocation Loc);
//===--------------------------------------------------------------------===//
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index ff02675898..ae87b29147 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -589,7 +589,9 @@ namespace clang {
/// \brief A SubstTemplateTypeParmPackType record.
TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
/// \brief A AutoType record.
- TYPE_AUTO = 38
+ TYPE_AUTO = 38,
+ /// \brief A UnaryTransformType record.
+ TYPE_UNARY_TRANSFORM = 39
};
/// \brief The type IDs for special types constructed by semantic
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e664855067..f356c908e9 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -975,6 +975,9 @@ ASTContext::getTypeInfo(const Type *T) const {
return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType()
.getTypePtr());
+ case Type::UnaryTransform:
+ return getTypeInfo(cast<UnaryTransformType>(T)->getUnderlyingType());
+
case Type::Elaborated:
return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
@@ -1605,6 +1608,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::Decltype:
+ case Type::UnaryTransform:
case Type::DependentName:
case Type::InjectedClassName:
case Type::TemplateSpecialization:
@@ -2802,6 +2806,20 @@ QualType ASTContext::getDecltypeType(Expr *e) const {
return QualType(dt, 0);
}
+/// getUnaryTransformationType - We don't unique these, since the memory
+/// savings are minimal and these are rare.
+QualType ASTContext::getUnaryTransformType(QualType BaseType,
+ QualType UnderlyingType,
+ UnaryTransformType::UTTKind Kind)
+ const {
+ UnaryTransformType *Ty =
+ new UnaryTransformType (BaseType, UnderlyingType, Kind,
+ UnderlyingType->isDependentType() ?
+ QualType() : UnderlyingType);
+ Types.push_back(Ty);
+ return QualType(Ty, 0);
+}
+
/// getAutoType - We only unique auto types after they've been deduced.
QualType ASTContext::getAutoType(QualType DeducedType) const {
void *InsertPos = 0;
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index dc881ba869..8904a9561c 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -64,6 +64,7 @@ namespace {
// FIXME: DependentTypeOfExprType
QualType VisitTypeOfType(const TypeOfType *T);
QualType VisitDecltypeType(const DecltypeType *T);
+ QualType VisitUnaryTransformType(const UnaryTransformType *T);
QualType VisitAutoType(const AutoType *T);
// FIXME: DependentDecltypeType
QualType VisitRecordType(const RecordType *T);
@@ -604,7 +605,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
cast<TypeOfType>(T2)->getUnderlyingType()))
return false;
break;
-
+
+ case Type::UnaryTransform:
+ if (!IsStructurallyEquivalent(Context,
+ cast<UnaryTransformType>(T1)->getUnderlyingType(),
+ cast<UnaryTransformType>(T1)->getUnderlyingType()))
+ return false;
+ break;
+
case Type::Decltype:
if (!IsStructurallyEquivalent(Context,
cast<DecltypeType>(T1)->getUnderlyingExpr(),
@@ -1572,6 +1580,17 @@ QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
return Importer.getToContext().getDecltypeType(ToExpr);
}
+QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
+ QualType ToBaseType = Importer.Import(T->getBaseType());
+ QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
+ if (ToBaseType.isNull() || ToUnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getUnaryTransformType(ToBaseType,
+ ToUnderlyingType,
+ T->getUTTKind());
+}
+
QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
// FIXME: Make sure that the "to" context supports C++0x!
QualType FromDeduced = T->getDeducedType();
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index e368c8927f..aad6e9c48d 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1939,6 +1939,22 @@ void CXXNameMangler::mangleType(const DecltypeType *T) {
Out << 'E';
}
+void CXXNameMangler::mangleType(const UnaryTransformType *T) {
+ // If this is dependent, we need to record that. If not, we simply
+ // mangle it as the underlying type since they are equivalent.
+ if (T->isDependentType()) {
+ Out << 'U';
+
+ switch (T->getUTTKind()) {
+ case UnaryTransformType::EnumUnderlyingType:
+ Out << "3eut";
+ break;
+ }
+ }
+
+ mangleType(T->getUnderlyingType());
+}
+
void CXXNameMangler::mangleType(const AutoType *T) {
QualType D = T->getDeducedType();
// <builtin-type> ::= Da # dependent auto
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 5424bebc81..4f920f9aac 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -1113,6 +1113,10 @@ void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T) {
assert(false && "Don't know how to mangle DecltypeTypes yet!");
}
+void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T) {
+ assert(false && "Don't know how to mangle UnaryTransformationTypes yet!");
+}
+
void MicrosoftCXXNameMangler::mangleType(const AutoType *T) {
assert(false && "Don't know how to mangle AutoTypes yet!");
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 9f576db535..d287552844 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1535,6 +1535,16 @@ static TagDecl *getInterestingTagDecl(TagDecl *decl) {
return decl;
}
+UnaryTransformType::UnaryTransformType(QualType BaseType,
+ QualType UnderlyingType,
+ UTTKind UKind,
+ QualType CanonicalType)
+ : Type(UnaryTransform, CanonicalType, UnderlyingType->isDependentType(),
+ UnderlyingType->isVariablyModifiedType(),
+ BaseType->containsUnexpandedParameterPack())
+ , BaseType(BaseType), UnderlyingType(UnderlyingType), UKind(UKind)
+{}
+
TagDecl *TagType::getDecl() const {
return getInterestingTagDecl(decl);
}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 0c5df7fae6..aad97fb9fc 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -94,6 +94,7 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::Decltype:
+ case Type::UnaryTransform:
case Type::Record:
case Type::Enum:
case Type::Elaborated:
@@ -512,6 +513,20 @@ void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
S = "decltype(" + s.str() + ")" + S;
}
+void TypePrinter::printUnaryTransform(const UnaryTransformType *T,
+ std::string &S) {
+ if (!S.empty())
+ S = ' ' + S;
+ std::string Str;
+ print(T->getBaseType(), Str);
+
+ switch (T->getUTTKind()) {
+ case UnaryTransformType::EnumUnderlyingType:
+ S = "__underlying_type(" + Str + ")" + S;
+ break;
+ }
+}
+
void TypePrinter::printAuto(const AutoType *T, std::string &S) {
// If the type has been deduced, do not print 'auto'.
if (T->isDeduced()) {
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 1c9d91a2e3..6c73865c3c 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1444,6 +1444,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T) {
case Type::Decltype:
T = cast<DecltypeType>(T)->getUnderlyingType();
break;
+ case Type::UnaryTransform:
+ T = cast<UnaryTransformType>(T)->getUnderlyingType();
+ break;
case Type::Attributed:
T = cast<AttributedType>(T)->getEquivalentType();
break;
@@ -1559,6 +1562,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::Decltype:
+ case Type::UnaryTransform:
case Type::Auto:
llvm_unreachable("type should have been unwrapped!");
return llvm::DIType();
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index f623c8e5b6..d3b34b922d 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -603,7 +603,7 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
const char *PrevSpec = 0;
unsigned DiagID;
- if (DS.SetTypeSpecType(DeclSpec::TST_underlying_type, StartLoc, PrevSpec,
+ if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
DiagID, Result.release()))
Diag(StartLoc, DiagID) << PrevSpec;
}
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index d6f8f91bbf..5be16e7431 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -309,7 +309,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
case DeclSpec::TST_typeofExpr: return "typeof";
case DeclSpec::TST_auto: return "auto";
case DeclSpec::TST_decltype: return "(decltype)";
- case DeclSpec::TST_underlying_type: return "__underlying_type";
+ case DeclSpec::TST_underlyingType: return "__underlying_type";
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
case DeclSpec::TST_error: return "(error)";
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7bcd205b22..41e05d5cdb 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2865,7 +2865,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
case DeclSpec::TST_typename:
case DeclSpec::TST_typeofType:
case DeclSpec::TST_decltype:
- case DeclSpec::TST_underlying_type: {
+ case DeclSpec::TST_underlyingType: {
// Grab the type from the parser.
TypeSourceInfo *TSI = 0;
QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 8e7e1a12dd..d978c389b2 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3106,6 +3106,11 @@ bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) {
return false;
}
+bool UnnamedLocalNoLinkageFinder::VisitUnaryTransformType(
+ const UnaryTransformType*) {
+ return false;
+}
+
bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {
return Visit(T->getDeducedType());
}
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index f2ec09b132..c4627eb1e3 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -3886,6 +3886,13 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
OnlyDeduced, Depth, Used);
break;
+ case Type::UnaryTransform:
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef,
+ cast<UnaryTransformType>(T)->getUnderlyingType(),
+ OnlyDeduced, Depth, Used);
+ break;
+
case Type::PackExpansion:
MarkUsedTemplateParameters(SemaRef,
cast<PackExpansionType>(T)->getPattern(),
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 100c6a77a0..86d3bc1709 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -618,7 +618,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
switch (DS.getTypeSpecType()) {
case TST_typename:
case TST_typeofType:
- case TST_underlying_type: {
+ case TST_underlyingType: {
QualType T = DS.getRepAsType().get();
if (!T.isNull() && T->containsUnexpandedParameterPack())
return true;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 884144f99b..a2433cad51 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -836,26 +836,15 @@ static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) {
}
break;
}
- case DeclSpec::TST_underlying_type:
- // FIXME: Preserve type source info?
+ case DeclSpec::TST_underlyingType:
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
- if (!Result->isDependentType()) {
- if (Result->isEnumeralType()) {
- EnumDecl *ED = Result->getAs<EnumType>()->getDecl();
- S.DiagnoseUseOfDecl(ED, DS.getTypeSpecTypeLoc());
- QualType UnderlyingType = ED->getIntegerType();
- if (UnderlyingType.isNull()) {
- declarator.setInvalidType(true);
- Result = Context.IntTy;
- } else {
- Result = UnderlyingType;
- }
- } else {
- S.Diag(DS.getTypeSpecTypeLoc(),
- diag::err_only_enums_have_underlying_types);
- Result = Context.IntTy;
- }
+ Result = S.BuildUnaryTransformType(Result,
+ UnaryTransformType::EnumUnderlyingType,
+ DS.getTypeSpecTypeLoc());
+ if (Result.isNull()) {
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
}
break;
@@ -2397,6 +2386,16 @@ namespace {
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
+ void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
+ // FIXME: This holds only because we only have one unary transform.
+ assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
+ TL.setKWLoc(DS.getTypeSpecTypeLoc());
+ TL.setParensRange(DS.getTypeofParensRange());
+ assert(DS.getRepAsType());
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ TL.setUnderlyingTInfo(TInfo);
+ }
void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
// By default, use the source location of the type specifier.
TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
@@ -3397,3 +3396,27 @@ QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
return Context.getDecltypeType(E);
}
+
+QualType Sema::BuildUnaryTransformType(QualType BaseType,
+ UnaryTransformType::UTTKind UKind,
+ SourceLocation Loc) {
+ switch (UKind) {
+ case UnaryTransformType::EnumUnderlyingType:
+ if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
+ Diag(Loc, diag::err_only_enums_have_underlying_types);
+ return QualType();
+ } else {
+ QualType Underlying = BaseType;
+ if (!BaseType->isDependentType()) {
+ EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
+ assert(ED && "EnumType has no EnumDecl");
+ DiagnoseUseOfDecl(ED, Loc);
+ Underlying = ED->getIntegerType();
+ }
+ assert(!Underlying.isNull());
+ return Context.getUnaryTransformType(BaseType, Underlying,
+ UnaryTransformType::EnumUnderlyingType);
+ }
+ }
+ llvm_unreachable("unknown unary transform type");
+}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index db65e2ba30..396a978260 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -702,6 +702,11 @@ public:
/// By default, builds a new TypeOfType with the given underlying type.
QualType RebuildTypeOfType(QualType Underlying);
+ /// \brief Build a new unary transform type.
+ QualType RebuildUnaryTransformType(QualType BaseType,
+ UnaryTransformType::UTTKind UKind,
+ SourceLocation Loc);
+
/// \brief Build a new C++0x decltype type.
///
/// By default, performs semantic analysis when building the decltype type.
@@ -4159,6 +4164,29 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
}
template<typename Derived>
+QualType TreeTransform<Derived>::TransformUnaryTransformType(
+ TypeLocBuilder &TLB,
+ UnaryTransformTypeLoc TL) {
+ QualType Result = TL.getType();
+ if (Result->isDependentType()) {
+ const UnaryTransformType *T = TL.getTypePtr();
+ QualType NewBase =
+ getDerived().TransformType(TL.getUnderlyingTInfo())->getType();
+ Result = getDerived().RebuildUnaryTransformType(NewBase,
+ T->getUTTKind(),
+ TL.getKWLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ UnaryTransformTypeLoc NewTL = TLB.push<UnaryTransformTypeLoc>(Result);
+ NewTL.setKWLoc(TL.getKWLoc());
+ NewTL.setParensRange(TL.getParensRange());
+ NewTL.setUnderlyingTInfo(TL.getUnderlyingTInfo());
+ return Result;
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
AutoTypeLoc TL) {
const AutoType *T = TL.getTypePtr();
@@ -8053,6 +8081,13 @@ QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnaryTransformType(QualType BaseType,
+ UnaryTransformType::UTTKind UKind,
+ SourceLocation Loc) {
+ return SemaRef.BuildUnaryTransformType(BaseType, UKind, Loc);
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
TemplateName Template,
SourceLocation TemplateNameLoc,
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 0ab1704b11..240df2cde8 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -3199,6 +3199,13 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
case TYPE_DECLTYPE:
return Context->getDecltypeType(ReadExpr(*Loc.F));