Implement a new type node, UnaryTransformType, designed to represent a

type that turns one type into another. This is used as the basis to
implement __underlying_type properly - with TypeSourceInfo and proper
behavior in the face of templates.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132017 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sean Hunt 2011-05-24 22:41:36 +00:00
Родитель cd583ff142
Коммит ca63c20034
29 изменённых файлов: 334 добавлений и 27 удалений

Просмотреть файл

@ -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;

Просмотреть файл

@ -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)

Просмотреть файл

@ -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()));
})

Просмотреть файл

@ -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.

Просмотреть файл

@ -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> {

Просмотреть файл

@ -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)

Просмотреть файл

@ -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

Просмотреть файл

@ -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);

Просмотреть файл

@ -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.

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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();

Просмотреть файл

@ -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

Просмотреть файл

@ -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!");
}

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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()) {

Просмотреть файл

@ -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();

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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)";
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -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());
}

Просмотреть файл

@ -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(),

Просмотреть файл

@ -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;

Просмотреть файл

@ -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");
}

Просмотреть файл

@ -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.
@ -4158,6 +4163,29 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
return Result;
}
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) {
@ -8052,6 +8080,13 @@ QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E,
return SemaRef.BuildDecltypeType(E, Loc);
}
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,

Просмотреть файл

@ -3199,6 +3199,13 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
case TYPE_DECLTYPE:
return Context->getDecltypeType(ReadExpr(*Loc.F));
case TYPE_UNARY_TRANSFORM: {
QualType BaseType = GetType(Record[0]);
QualType UnderlyingType = GetType(Record[1]);
UnaryTransformType::UTTKind UKind = (UnaryTransformType::UTTKind)Record[2];
return Context->getUnaryTransformType(BaseType, UnderlyingType, UKind);
}
case TYPE_AUTO:
return Context->getAutoType(GetType(Record[0]));
@ -3515,6 +3522,12 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation(Record, Idx));
}
void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
TL.setKWLoc(ReadSourceLocation(Record, Idx));
TL.setLParenLoc(ReadSourceLocation(Record, Idx));
TL.setRParenLoc(ReadSourceLocation(Record, Idx));
TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
}
void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
TL.setNameLoc(ReadSourceLocation(Record, Idx));
}

Просмотреть файл

@ -223,6 +223,13 @@ void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) {
Code = TYPE_DECLTYPE;
}
void ASTTypeWriter::VisitUnaryTransformType(const UnaryTransformType *T) {
Writer.AddTypeRef(T->getBaseType(), Record);
Writer.AddTypeRef(T->getUnderlyingType(), Record);
Record.push_back(T->getUTTKind());
Code = TYPE_UNARY_TRANSFORM;
}
void ASTTypeWriter::VisitAutoType(const AutoType *T) {
Writer.AddTypeRef(T->getDeducedType(), Record);
Code = TYPE_AUTO;
@ -494,6 +501,12 @@ void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
}
void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
Writer.AddSourceLocation(TL.getKWLoc(), Record);
Writer.AddSourceLocation(TL.getLParenLoc(), Record);
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record);
}
void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
}

Просмотреть файл

@ -25,3 +25,13 @@ static_assert(is_same_type<int, __underlying_type(g)>::value,
__underlying_type(f) h;
static_assert(is_same_type<char, decltype(h)>::value,
"h has the wrong type");
template <typename T>
struct underlying_type {
typedef __underlying_type(T) type; // expected-error {{only enumeration types}}
};
static_assert(is_same_type<underlying_type<f>::type, char>::value,
"f has the wrong underlying type in the template");
underlying_type<int>::type e; // expected-note {{requested here}}

Просмотреть файл

@ -350,6 +350,7 @@ public:
bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
bool VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL);
bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
bool VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL);
bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL);
bool VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL);
@ -1553,6 +1554,13 @@ bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
return false;
}
bool CursorVisitor::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
return Visit(TSInfo->getTypeLoc());
return false;
}
bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc()))
return true;