Introduce an AttributedType, but don't actually use it anywhere yet.
The initial TreeTransform is a cop-out, but it's more-or-less equivalent to what we were doing before, or rather what we're doing now and might eventually stop doing in favor of using this type. I am simultaneously intrigued by the possibilities of rebuilding a dependent Attri llvm-svn: 122942
This commit is contained in:
parent
4072e59189
commit
8190451ddc
|
@ -109,6 +109,7 @@ class ASTContext {
|
|||
llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
|
||||
llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
|
||||
llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
|
||||
llvm::FoldingSet<AttributedType> AttributedTypes;
|
||||
|
||||
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
|
||||
|
@ -648,6 +649,10 @@ public:
|
|||
|
||||
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST);
|
||||
|
||||
QualType getAttributedType(AttributedType::Kind attrKind,
|
||||
QualType modifiedType,
|
||||
QualType equivalentType);
|
||||
|
||||
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
|
||||
QualType Replacement);
|
||||
|
||||
|
|
|
@ -726,6 +726,10 @@ DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
|
|||
|
||||
DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
|
||||
|
||||
DEF_TRAVERSE_TYPE(AttributedType, {
|
||||
TRY_TO(TraverseType(T->getModifiedType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(ParenType, {
|
||||
TRY_TO(TraverseType(T->getInnerType()));
|
||||
})
|
||||
|
@ -936,6 +940,10 @@ DEF_TRAVERSE_TYPELOC(ParenType, {
|
|||
TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(AttributedType, {
|
||||
TRY_TO(TraverseTypeLoc(TL.getModifiedLoc()));
|
||||
})
|
||||
|
||||
// FIXME: use the sourceloc on qualifier?
|
||||
DEF_TRAVERSE_TYPELOC(ElaboratedType, {
|
||||
if (TL.getTypePtr()->getQualifier()) {
|
||||
|
|
|
@ -993,9 +993,19 @@ protected:
|
|||
unsigned NumElements : 29 - NumTypeBits;
|
||||
};
|
||||
|
||||
class AttributedTypeBitfields {
|
||||
friend class AttributedType;
|
||||
|
||||
unsigned : NumTypeBits;
|
||||
|
||||
/// AttrKind - an AttributedType::Kind
|
||||
unsigned AttrKind : 32 - NumTypeBits;
|
||||
};
|
||||
|
||||
union {
|
||||
TypeBitfields TypeBits;
|
||||
ArrayTypeBitfields ArrayTypeBits;
|
||||
AttributedTypeBitfields AttributedTypeBits;
|
||||
BuiltinTypeBitfields BuiltinTypeBits;
|
||||
FunctionTypeBitfields FunctionTypeBits;
|
||||
ObjCObjectTypeBitfields ObjCObjectTypeBits;
|
||||
|
@ -2657,6 +2667,91 @@ public:
|
|||
static bool classof(const EnumType *) { return true; }
|
||||
};
|
||||
|
||||
/// AttributedType - An attributed type is a type to which a type
|
||||
/// attribute has been applied. The "modified type" is the
|
||||
/// fully-sugared type to which the attributed type was applied;
|
||||
/// generally it is not canonically equivalent to the attributed type.
|
||||
/// The "equivalent type" is the minimally-desugared type which the
|
||||
/// type is canonically equivalent to.
|
||||
///
|
||||
/// For example, in the following attributed type:
|
||||
/// int32_t __attribute__((vector_size(16)))
|
||||
/// - the modified type is the TypedefType for int32_t
|
||||
/// - the equivalent type is VectorType(16, int32_t)
|
||||
/// - the canonical type is VectorType(16, int)
|
||||
class AttributedType : public Type, public llvm::FoldingSetNode {
|
||||
public:
|
||||
// It is really silly to have yet another attribute-kind enum, but
|
||||
// clang::attr::Kind doesn't currently cover the pure type attrs.
|
||||
enum Kind {
|
||||
// Expression operand.
|
||||
address_space,
|
||||
regparm,
|
||||
vector_size,
|
||||
neon_vector_type,
|
||||
neon_polyvector_type,
|
||||
|
||||
FirstExprOperandKind = address_space,
|
||||
LastExprOperandKind = neon_polyvector_type,
|
||||
|
||||
// Enumerated operand (string or keyword).
|
||||
objc_gc,
|
||||
|
||||
FirstEnumOperandKind = objc_gc,
|
||||
LastEnumOperandKind = objc_gc,
|
||||
|
||||
// No operand.
|
||||
noreturn,
|
||||
cdecl,
|
||||
fastcall,
|
||||
stdcall,
|
||||
thiscall,
|
||||
pascal
|
||||
};
|
||||
|
||||
private:
|
||||
QualType ModifiedType;
|
||||
QualType EquivalentType;
|
||||
|
||||
friend class ASTContext; // creates these
|
||||
|
||||
AttributedType(QualType canon, Kind attrKind,
|
||||
QualType modified, QualType equivalent)
|
||||
: Type(Attributed, canon, canon->isDependentType(),
|
||||
canon->isVariablyModifiedType(),
|
||||
canon->containsUnexpandedParameterPack()),
|
||||
ModifiedType(modified), EquivalentType(equivalent) {
|
||||
AttributedTypeBits.AttrKind = attrKind;
|
||||
}
|
||||
|
||||
public:
|
||||
Kind getAttrKind() const {
|
||||
return static_cast<Kind>(AttributedTypeBits.AttrKind);
|
||||
}
|
||||
|
||||
QualType getModifiedType() const { return ModifiedType; }
|
||||
QualType getEquivalentType() const { return EquivalentType; }
|
||||
|
||||
bool isSugared() const { return true; }
|
||||
QualType desugar() const { return getEquivalentType(); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
|
||||
QualType modified, QualType equivalent) {
|
||||
ID.AddInteger(attrKind);
|
||||
ID.AddPointer(modified.getAsOpaquePtr());
|
||||
ID.AddPointer(equivalent.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == Attributed;
|
||||
}
|
||||
static bool classof(const AttributedType *T) { return true; }
|
||||
};
|
||||
|
||||
class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
|
||||
unsigned Depth : 15;
|
||||
unsigned ParameterPack : 1;
|
||||
|
|
|
@ -592,6 +592,130 @@ class SubstTemplateTypeParmTypeLoc :
|
|||
SubstTemplateTypeParmType> {
|
||||
};
|
||||
|
||||
struct AttributedLocInfo {
|
||||
union {
|
||||
Expr *ExprOperand;
|
||||
|
||||
/// A raw SourceLocation.
|
||||
unsigned EnumOperandLoc;
|
||||
};
|
||||
|
||||
SourceRange OperandParens;
|
||||
|
||||
SourceLocation AttrLoc;
|
||||
};
|
||||
|
||||
/// \brief Type source information for an attributed type.
|
||||
class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
AttributedTypeLoc,
|
||||
AttributedType,
|
||||
AttributedLocInfo> {
|
||||
public:
|
||||
AttributedType::Kind getAttrKind() const {
|
||||
return getTypePtr()->getAttrKind();
|
||||
}
|
||||
|
||||
bool hasAttrExprOperand() const {
|
||||
return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
|
||||
getAttrKind() <= AttributedType::LastExprOperandKind);
|
||||
}
|
||||
|
||||
bool hasAttrEnumOperand() const {
|
||||
return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
|
||||
getAttrKind() <= AttributedType::LastEnumOperandKind);
|
||||
}
|
||||
|
||||
bool hasAttrOperand() const {
|
||||
return hasAttrExprOperand() || hasAttrEnumOperand();
|
||||
}
|
||||
|
||||
/// The modified type, which is generally canonically different from
|
||||
/// the attribute type.
|
||||
/// int main(int, char**) __attribute__((noreturn))
|
||||
/// ~~~ ~~~~~~~~~~~~~
|
||||
TypeLoc getModifiedLoc() const {
|
||||
return getInnerTypeLoc();
|
||||
}
|
||||
|
||||
/// The location of the attribute name, i.e.
|
||||
/// __attribute__((regparm(1000)))
|
||||
/// ^~~~~~~
|
||||
SourceLocation getAttrNameLoc() const {
|
||||
return getLocalData()->AttrLoc;
|
||||
}
|
||||
void setAttrNameLoc(SourceLocation loc) {
|
||||
getLocalData()->AttrLoc = loc;
|
||||
}
|
||||
|
||||
/// The attribute's expression operand, if it has one.
|
||||
/// void *cur_thread __attribute__((address_space(21)))
|
||||
/// ^~
|
||||
Expr *getAttrExprOperand() const {
|
||||
assert(hasAttrExprOperand());
|
||||
return getLocalData()->ExprOperand;
|
||||
}
|
||||
void setAttrExprOperand(Expr *e) {
|
||||
assert(hasAttrExprOperand());
|
||||
getLocalData()->ExprOperand = e;
|
||||
}
|
||||
|
||||
/// The location of the attribute's enumerated operand, if it has one.
|
||||
/// void * __attribute__((objc_gc(weak)))
|
||||
/// ^~~~
|
||||
SourceLocation getAttrEnumOperandLoc() const {
|
||||
assert(hasAttrEnumOperand());
|
||||
return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
|
||||
}
|
||||
void setAttrEnumOperandLoc(SourceLocation loc) {
|
||||
assert(hasAttrEnumOperand());
|
||||
getLocalData()->EnumOperandLoc = loc.getRawEncoding();
|
||||
}
|
||||
|
||||
/// The location of the parentheses around the operand, if there is
|
||||
/// an operand.
|
||||
/// void * __attribute__((objc_gc(weak)))
|
||||
/// ^ ^
|
||||
SourceRange getAttrOperandParensRange() const {
|
||||
assert(hasAttrOperand());
|
||||
return getLocalData()->OperandParens;
|
||||
}
|
||||
void setAttrOperandParensRange(SourceRange range) {
|
||||
assert(hasAttrOperand());
|
||||
getLocalData()->OperandParens = range;
|
||||
}
|
||||
|
||||
SourceRange getLocalSourceRange() const {
|
||||
// Note that this does *not* include the range of the attribute
|
||||
// enclosure, e.g.:
|
||||
// __attribute__((foo(bar)))
|
||||
// ^~~~~~~~~~~~~~~ ~~
|
||||
// or
|
||||
// [[foo(bar)]]
|
||||
// ^~ ~~
|
||||
// That enclosure doesn't necessarily belong to a single attribute
|
||||
// anyway.
|
||||
SourceRange range(getAttrNameLoc());
|
||||
if (hasAttrOperand())
|
||||
range.setEnd(getAttrOperandParensRange().getEnd());
|
||||
return range;
|
||||
}
|
||||
|
||||
void initializeLocal(SourceLocation loc) {
|
||||
setAttrNameLoc(loc);
|
||||
if (hasAttrExprOperand()) {
|
||||
setAttrOperandParensRange(SourceRange(loc));
|
||||
setAttrExprOperand(0);
|
||||
} else if (hasAttrEnumOperand()) {
|
||||
setAttrOperandParensRange(SourceRange(loc));
|
||||
setAttrEnumOperandLoc(loc);
|
||||
}
|
||||
}
|
||||
|
||||
QualType getInnerType() const {
|
||||
return getTypePtr()->getModifiedType();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct ObjCProtocolListLocInfo {
|
||||
SourceLocation LAngleLoc;
|
||||
|
|
|
@ -88,6 +88,7 @@ ABSTRACT_TYPE(Tag, Type)
|
|||
TYPE(Record, TagType)
|
||||
TYPE(Enum, TagType)
|
||||
NON_CANONICAL_TYPE(Elaborated, Type)
|
||||
NON_CANONICAL_TYPE(Attributed, Type)
|
||||
DEPENDENT_TYPE(TemplateTypeParm, Type)
|
||||
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
|
||||
|
|
|
@ -553,7 +553,9 @@ namespace clang {
|
|||
/// \brief A ParenType record.
|
||||
TYPE_PAREN = 34,
|
||||
/// \brief A PackExpansionType record.
|
||||
TYPE_PACK_EXPANSION = 35
|
||||
TYPE_PACK_EXPANSION = 35,
|
||||
/// \brief An AttributedType record.
|
||||
TYPE_ATTRIBUTED = 36
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
|
|
|
@ -844,6 +844,10 @@ ASTContext::getTypeInfo(const Type *T) {
|
|||
case Type::Elaborated:
|
||||
return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
|
||||
|
||||
case Type::Attributed:
|
||||
return getTypeInfo(
|
||||
cast<AttributedType>(T)->getEquivalentType().getTypePtr());
|
||||
|
||||
case Type::TemplateSpecialization:
|
||||
assert(getCanonicalType(T) != T &&
|
||||
"Cannot request the size of a dependent type");
|
||||
|
@ -1875,6 +1879,27 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) {
|
|||
return QualType(Decl->TypeForDecl, 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
|
||||
QualType modifiedType,
|
||||
QualType equivalentType) {
|
||||
llvm::FoldingSetNodeID id;
|
||||
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
|
||||
|
||||
void *insertPos = 0;
|
||||
AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos);
|
||||
if (type) return QualType(type, 0);
|
||||
|
||||
QualType canon = getCanonicalType(equivalentType);
|
||||
type = new (*this, TypeAlignment)
|
||||
AttributedType(canon, attrKind, modifiedType, equivalentType);
|
||||
|
||||
Types.push_back(type);
|
||||
AttributedTypes.InsertNode(type, insertPos);
|
||||
|
||||
return QualType(type, 0);
|
||||
}
|
||||
|
||||
|
||||
/// \brief Retrieve a substitution-result type.
|
||||
QualType
|
||||
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
|
||||
|
|
|
@ -557,6 +557,17 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
return false;
|
||||
|
||||
break;
|
||||
|
||||
case Type::Attributed:
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
cast<AttributedType>(T1)->getModifiedType(),
|
||||
cast<AttributedType>(T2)->getModifiedType()))
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
cast<AttributedType>(T1)->getEquivalentType(),
|
||||
cast<AttributedType>(T2)->getEquivalentType()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case Type::Paren:
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
|
|
|
@ -229,4 +229,3 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
|
|||
TL = PTL->getInnerLoc();
|
||||
return TL;
|
||||
}
|
||||
|
||||
|
|
|
@ -674,6 +674,84 @@ void TypePrinter::printPackExpansion(const PackExpansionType *T,
|
|||
S += "...";
|
||||
}
|
||||
|
||||
void TypePrinter::printAttributed(const AttributedType *T,
|
||||
std::string &S) {
|
||||
print(T->getModifiedType(), S);
|
||||
|
||||
// TODO: not all attributes are GCC-style attributes.
|
||||
S += "__attribute__((";
|
||||
switch (T->getAttrKind()) {
|
||||
case AttributedType::address_space:
|
||||
S += "address_space(";
|
||||
S += T->getEquivalentType().getAddressSpace();
|
||||
S += ")";
|
||||
break;
|
||||
|
||||
case AttributedType::vector_size: {
|
||||
S += "__vector_size__(";
|
||||
if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
|
||||
S += vector->getNumElements();
|
||||
S += " * sizeof(";
|
||||
|
||||
std::string tmp;
|
||||
print(vector->getElementType(), tmp);
|
||||
S += tmp;
|
||||
S += ")";
|
||||
}
|
||||
S += ")";
|
||||
break;
|
||||
}
|
||||
|
||||
case AttributedType::neon_vector_type:
|
||||
case AttributedType::neon_polyvector_type: {
|
||||
if (T->getAttrKind() == AttributedType::neon_vector_type)
|
||||
S += "neon_vector_type(";
|
||||
else
|
||||
S += "neon_polyvector_type(";
|
||||
const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
|
||||
S += llvm::utostr_32(vector->getNumElements());
|
||||
S += ")";
|
||||
break;
|
||||
}
|
||||
|
||||
case AttributedType::regparm: {
|
||||
S += "regparm(";
|
||||
QualType t = T->getEquivalentType();
|
||||
while (!t->isFunctionType())
|
||||
t = t->getPointeeType();
|
||||
S += t->getAs<FunctionType>()->getRegParmType();
|
||||
S += ")";
|
||||
break;
|
||||
}
|
||||
|
||||
case AttributedType::objc_gc: {
|
||||
S += "objc_gc(";
|
||||
|
||||
QualType tmp = T->getEquivalentType();
|
||||
while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
|
||||
QualType next = tmp->getPointeeType();
|
||||
if (next == tmp) break;
|
||||
tmp = next;
|
||||
}
|
||||
|
||||
if (tmp.isObjCGCWeak())
|
||||
S += "weak";
|
||||
else
|
||||
S += "strong";
|
||||
S += ")";
|
||||
break;
|
||||
}
|
||||
|
||||
case AttributedType::noreturn: S += "noreturn"; break;
|
||||
case AttributedType::cdecl: S += "cdecl"; break;
|
||||
case AttributedType::fastcall: S += "fastcall"; break;
|
||||
case AttributedType::stdcall: S += "stdcall"; break;
|
||||
case AttributedType::thiscall: S += "thiscall"; break;
|
||||
case AttributedType::pascal: S += "pascal"; break;
|
||||
}
|
||||
S += "))";
|
||||
}
|
||||
|
||||
void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
|
||||
std::string &S) {
|
||||
if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
|
||||
|
|
|
@ -1324,6 +1324,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T) {
|
|||
case Type::Decltype:
|
||||
T = cast<DecltypeType>(T)->getUnderlyingType();
|
||||
break;
|
||||
case Type::Attributed:
|
||||
T = cast<AttributedType>(T)->getEquivalentType();
|
||||
case Type::Elaborated:
|
||||
T = cast<ElaboratedType>(T)->getNamedType();
|
||||
break;
|
||||
|
@ -1423,6 +1425,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
|
|||
case Type::MemberPointer:
|
||||
return CreateType(cast<MemberPointerType>(Ty), Unit);
|
||||
|
||||
case Type::Attributed:
|
||||
case Type::TemplateSpecialization:
|
||||
case Type::Elaborated:
|
||||
case Type::Paren:
|
||||
|
|
|
@ -3778,7 +3778,6 @@ QualType TreeTransform<Derived>::TransformInjectedClassNameType(
|
|||
return T;
|
||||
}
|
||||
|
||||
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
|
||||
TypeLocBuilder &TLB,
|
||||
|
@ -3945,6 +3944,43 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
|
|||
return Result;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::TransformAttributedType(
|
||||
TypeLocBuilder &TLB,
|
||||
AttributedTypeLoc TL) {
|
||||
const AttributedType *oldType = TL.getTypePtr();
|
||||
QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc());
|
||||
if (modifiedType.isNull())
|
||||
return QualType();
|
||||
|
||||
QualType result = TL.getType();
|
||||
|
||||
// FIXME: dependent operand expressions?
|
||||
if (getDerived().AlwaysRebuild() ||
|
||||
modifiedType != oldType->getModifiedType()) {
|
||||
// TODO: this is really lame; we should really be rebuilding the
|
||||
// equivalent type from first principles.
|
||||
QualType equivalentType
|
||||
= getDerived().TransformType(oldType->getEquivalentType());
|
||||
if (equivalentType.isNull())
|
||||
return QualType();
|
||||
result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
|
||||
modifiedType,
|
||||
equivalentType);
|
||||
}
|
||||
|
||||
AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
|
||||
newTL.setAttrNameLoc(TL.getAttrNameLoc());
|
||||
if (TL.hasAttrOperand())
|
||||
newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange());
|
||||
if (TL.hasAttrExprOperand())
|
||||
newTL.setAttrExprOperand(TL.getAttrExprOperand());
|
||||
else if (TL.hasAttrEnumOperand())
|
||||
newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType
|
||||
TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB,
|
||||
|
|
|
@ -2924,6 +2924,17 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
|
|||
return T;
|
||||
}
|
||||
|
||||
case TYPE_ATTRIBUTED: {
|
||||
if (Record.size() != 3) {
|
||||
Error("incorrect encoding of attributed type");
|
||||
return QualType();
|
||||
}
|
||||
QualType modifiedType = GetType(Record[0]);
|
||||
QualType equivalentType = GetType(Record[1]);
|
||||
AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record[2]);
|
||||
return Context->getAttributedType(kind, modifiedType, equivalentType);
|
||||
}
|
||||
|
||||
case TYPE_PAREN: {
|
||||
if (Record.size() != 1) {
|
||||
Error("incorrect encoding of paren type");
|
||||
|
@ -3197,6 +3208,22 @@ void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
|||
void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
|
||||
TL.setNameLoc(ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
|
||||
TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));
|
||||
if (TL.hasAttrOperand()) {
|
||||
SourceRange range;
|
||||
range.setBegin(ReadSourceLocation(Record, Idx));
|
||||
range.setEnd(ReadSourceLocation(Record, Idx));
|
||||
TL.setAttrOperandParensRange(range);
|
||||
}
|
||||
if (TL.hasAttrExprOperand()) {
|
||||
if (Record[Idx++])
|
||||
TL.setAttrExprOperand(Reader.ReadExpr(F));
|
||||
else
|
||||
TL.setAttrExprOperand(0);
|
||||
} else if (TL.hasAttrEnumOperand())
|
||||
TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
|
||||
TL.setNameLoc(ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
|
|
@ -228,6 +228,13 @@ void ASTTypeWriter::VisitEnumType(const EnumType *T) {
|
|||
Code = TYPE_ENUM;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitAttributedType(const AttributedType *T) {
|
||||
Writer.AddTypeRef(T->getModifiedType(), Record);
|
||||
Writer.AddTypeRef(T->getEquivalentType(), Record);
|
||||
Record.push_back(T->getAttrKind());
|
||||
Code = TYPE_ATTRIBUTED;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitSubstTemplateTypeParmType(
|
||||
const SubstTemplateTypeParmType *T) {
|
||||
|
@ -462,6 +469,21 @@ void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
|
|||
void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getAttrNameLoc(), Record);
|
||||
if (TL.hasAttrOperand()) {
|
||||
SourceRange range = TL.getAttrOperandParensRange();
|
||||
Writer.AddSourceLocation(range.getBegin(), Record);
|
||||
Writer.AddSourceLocation(range.getEnd(), Record);
|
||||
}
|
||||
if (TL.hasAttrExprOperand()) {
|
||||
Expr *operand = TL.getAttrExprOperand();
|
||||
Record.push_back(operand ? 1 : 0);
|
||||
if (operand) Writer.AddStmt(operand);
|
||||
} else if (TL.hasAttrEnumOperand()) {
|
||||
Writer.AddSourceLocation(TL.getAttrEnumOperandLoc(), Record);
|
||||
}
|
||||
}
|
||||
void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getNameLoc(), Record);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue