diff options
Diffstat (limited to 'clang/lib/AST')
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 51 | ||||
| -rw-r--r-- | clang/lib/AST/Type.cpp | 42 | ||||
| -rw-r--r-- | clang/lib/AST/TypeSerialization.cpp | 51 |
3 files changed, 132 insertions, 12 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d20387dd95e..f3243c25ae7 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -85,6 +85,7 @@ void ASTContext::PrintStats() const { unsigned NumBuiltin = 0, NumPointer = 0, NumArray = 0, NumFunctionP = 0; unsigned NumVector = 0, NumComplex = 0, NumBlockPointer = 0; unsigned NumFunctionNP = 0, NumTypeName = 0, NumTagged = 0, NumReference = 0; + unsigned NumMemberPointer = 0; unsigned NumTagStruct = 0, NumTagUnion = 0, NumTagEnum = 0, NumTagClass = 0; unsigned NumObjCInterfaces = 0, NumObjCQualifiedInterfaces = 0; @@ -101,6 +102,8 @@ void ASTContext::PrintStats() const { ++NumBlockPointer; else if (isa<ReferenceType>(T)) ++NumReference; + else if (isa<MemberPointerType>(T)) + ++NumMemberPointer; else if (isa<ComplexType>(T)) ++NumComplex; else if (isa<ArrayType>(T)) @@ -142,6 +145,7 @@ void ASTContext::PrintStats() const { fprintf(stderr, " %d pointer types\n", NumPointer); fprintf(stderr, " %d block pointer types\n", NumBlockPointer); fprintf(stderr, " %d reference types\n", NumReference); + fprintf(stderr, " %d member pointer types\n", NumMemberPointer); fprintf(stderr, " %d complex types\n", NumComplex); fprintf(stderr, " %d array types\n", NumArray); fprintf(stderr, " %d vector types\n", NumVector); @@ -164,6 +168,7 @@ void ASTContext::PrintStats() const { fprintf(stderr, "Total bytes = %d\n", int(NumBuiltin*sizeof(BuiltinType)+ NumPointer*sizeof(PointerType)+NumArray*sizeof(ArrayType)+ NumComplex*sizeof(ComplexType)+NumVector*sizeof(VectorType)+ + NumMemberPointer*sizeof(MemberPointerType)+ NumFunctionP*sizeof(FunctionTypeProto)+ NumFunctionNP*sizeof(FunctionTypeNoProto)+ NumTypeName*sizeof(TypedefType)+NumTagged*sizeof(TagType)+ @@ -374,7 +379,19 @@ ASTContext::getTypeInfo(const Type *T) { // FIXME: This is wrong for struct layout: a reference in a struct has // pointer size. return getTypeInfo(cast<ReferenceType>(T)->getPointeeType()); - + case Type::MemberPointer: { + // Note that this is not only platform- but also ABI-dependent. We follow + // the GCC ABI, where pointers to data are one pointer large, pointers to + // functions two pointers. But if we want to support ABI compatibility with + // other compilers too, we need to delegate this completely to TargetInfo. + QualType Pointee = cast<MemberPointerType>(T)->getPointeeType(); + unsigned AS = Pointee.getAddressSpace(); + Width = Target.getPointerWidth(AS); + if (Pointee->isFunctionType()) + Width *= 2; + Align = Target.getPointerAlign(AS); + // GCC aligns at single pointer width. + } case Type::Complex: { // Complex types have the same alignment as their elements, but twice the // size. @@ -808,6 +825,38 @@ QualType ASTContext::getReferenceType(QualType T) { return QualType(New, 0); } +/// getMemberPointerType - Return the uniqued reference to the type for a +/// member pointer to the specified type, in the specified class. +QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) +{ + // Unique pointers, to guarantee there is only one pointer of a particular + // structure. + llvm::FoldingSetNodeID ID; + MemberPointerType::Profile(ID, T, Cls); + + void *InsertPos = 0; + if (MemberPointerType *PT = + MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(PT, 0); + + // If the pointee or class type isn't canonical, this won't be a canonical + // type either, so fill in the canonical type field. + QualType Canonical; + if (!T->isCanonical()) { + Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls)); + + // Get the new insert position for the node we care about. + MemberPointerType *NewIP = + MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + } + void *Mem = Allocator.Allocate(sizeof(MemberPointerType), 8); + MemberPointerType *New = new (Mem) MemberPointerType(T, Cls, Canonical); + Types.push_back(New); + MemberPointerTypes.InsertNode(New, InsertPos); + return QualType(New, 0); +} + /// getConstantArrayType - Return the unique reference to the type for an /// array of the specified element type. QualType ASTContext::getConstantArrayType(QualType EltTy, diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 94968920391..ebaa0113555 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -288,6 +288,24 @@ const ReferenceType *Type::getAsReferenceType() const { return getDesugaredType()->getAsReferenceType(); } +const MemberPointerType *Type::getAsMemberPointerType() const { + // If this is directly a member pointer type, return it. + if (const MemberPointerType *MTy = dyn_cast<MemberPointerType>(this)) + return MTy; + + // If the canonical form of this type isn't the right kind, reject it. + if (!isa<MemberPointerType>(CanonicalType)) { + // Look through type qualifiers + if (isa<MemberPointerType>(CanonicalType.getUnqualifiedType())) + return CanonicalType.getUnqualifiedType()->getAsMemberPointerType(); + return 0; + } + + // If this is a typedef for a member pointer type, strip the typedef off + // without losing all typedef information. + return getDesugaredType()->getAsMemberPointerType(); +} + /// isVariablyModifiedType (C99 6.7.5p3) - Return true for variable length /// array types and types that contain variable array types in their /// declarator @@ -300,8 +318,11 @@ bool Type::isVariablyModifiedType() const { if (const Type *T = getArrayElementTypeNoTypeQual()) return T->isVariablyModifiedType(); - // A pointer can point to a variably modified type - if (const PointerType *PT = getAsPointerType()) + // A pointer can point to a variably modified type. + // Also, C++ references and member pointers can point to a variably modified + // type, where VLAs appear as an extension to C++, and should be treated + // correctly. + if (const PointerLikeType *PT = getAsPointerLikeType()) return PT->getPointeeType()->isVariablyModifiedType(); // A function can return a variably modified type @@ -633,6 +654,7 @@ bool Type::isScalarType() const { return ASQT->getBaseType()->isScalarType(); return isa<PointerType>(CanonicalType) || isa<BlockPointerType>(CanonicalType) || + isa<MemberPointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) || isa<ObjCQualifiedIdType>(CanonicalType); } @@ -702,9 +724,9 @@ bool Type::isPODType() const { case Builtin: case Complex: case Pointer: + case MemberPointer: case Vector: case ExtVector: - // FIXME: pointer-to-member return true; case Tagged: @@ -951,6 +973,20 @@ void ReferenceType::getAsStringInternal(std::string &S) const { getPointeeType().getAsStringInternal(S); } +void MemberPointerType::getAsStringInternal(std::string &S) const { + std::string C; + Class->getAsStringInternal(C); + C += "::*"; + S = C + S; + + // Handle things like 'int (&A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(getPointeeType())) + S = '(' + S + ')'; + + getPointeeType().getAsStringInternal(S); +} + void ConstantArrayType::getAsStringInternal(std::string &S) const { S += '['; S += llvm::utostr(getSize().getZExtValue()); diff --git a/clang/lib/AST/TypeSerialization.cpp b/clang/lib/AST/TypeSerialization.cpp index 4f3eeca28c6..12c3d03c121 100644 --- a/clang/lib/AST/TypeSerialization.cpp +++ b/clang/lib/AST/TypeSerialization.cpp @@ -93,21 +93,29 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) { case Type::IncompleteArray: D.RegisterPtr(PtrID,IncompleteArrayType::CreateImpl(Context,D)); break; - + + case Type::MemberPointer: + D.RegisterPtr(PtrID, MemberPointerType::CreateImpl(Context, D)); + break; + case Type::Pointer: - D.RegisterPtr(PtrID,PointerType::CreateImpl(Context,D)); + D.RegisterPtr(PtrID, PointerType::CreateImpl(Context, D)); break; case Type::BlockPointer: - D.RegisterPtr(PtrID,BlockPointerType::CreateImpl(Context,D)); + D.RegisterPtr(PtrID, BlockPointerType::CreateImpl(Context, D)); break; - + + case Type::Reference: + D.RegisterPtr(PtrID, ReferenceType::CreateImpl(Context, D)); + break; + case Type::Tagged: - D.RegisterPtr(PtrID,TagType::CreateImpl(Context,D)); + D.RegisterPtr(PtrID, TagType::CreateImpl(Context, D)); break; - + case Type::TypeName: - D.RegisterPtr(PtrID,TypedefType::CreateImpl(Context,D)); + D.RegisterPtr(PtrID, TypedefType::CreateImpl(Context, D)); break; case Type::TypeOfExp: @@ -123,7 +131,7 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) { break; case Type::VariableArray: - D.RegisterPtr(PtrID,VariableArrayType::CreateImpl(Context,D)); + D.RegisterPtr(PtrID, VariableArrayType::CreateImpl(Context, D)); break; } } @@ -243,6 +251,33 @@ Type* PointerType::CreateImpl(ASTContext& Context, Deserializer& D) { } //===----------------------------------------------------------------------===// +// ReferenceType +//===----------------------------------------------------------------------===// + +void ReferenceType::EmitImpl(Serializer& S) const { + S.Emit(getPointeeType()); +} + +Type* ReferenceType::CreateImpl(ASTContext& Context, Deserializer& D) { + return Context.getReferenceType(QualType::ReadVal(D)).getTypePtr(); +} + +//===----------------------------------------------------------------------===// +// MemberPointerType +//===----------------------------------------------------------------------===// + +void MemberPointerType::EmitImpl(Serializer& S) const { + S.Emit(getPointeeType()); + S.Emit(QualType(Class, 0)); +} + +Type* MemberPointerType::CreateImpl(ASTContext& Context, Deserializer& D) { + QualType Pointee = QualType::ReadVal(D); + QualType Class = QualType::ReadVal(D); + return Context.getMemberPointerType(Pointee, Class.getTypePtr()).getTypePtr(); +} + +//===----------------------------------------------------------------------===// // TagType //===----------------------------------------------------------------------===// |

