зеркало из https://github.com/microsoft/clang.git
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:
Родитель
cd583ff142
Коммит
ca63c20034
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче