diff options
author | Chris Lattner <sabre@nondot.org> | 2009-02-18 22:53:11 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-02-18 22:53:11 +0000 |
commit | b7d2553edd2532d29b98b9e76bcf6a62bc48b417 (patch) | |
tree | 763eb32b281e1e27c695c165c5680be2ab868b13 | |
parent | b5da3e94b72a0106abd69c2a84bf650e773fa4ac (diff) |
fix some subtle bugs handling the mix of cvr qualifiers, addr spaces,
and gc attrs. Add an assert to check that we never
get ExtQualType(ExtQualType(T)).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64970 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Type.h | 7 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 86 |
2 files changed, 57 insertions, 36 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index c8ceafb132..644be13f5f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -485,8 +485,11 @@ class ExtQualType : public Type, public llvm::FoldingSetNode { ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace, QualType::GCAttrTypes gcAttr) : - Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base), - AddressSpace(AddrSpace), GCAttrType(gcAttr) { } + Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base), + AddressSpace(AddrSpace), GCAttrType(gcAttr) { + assert(!isa<ExtQualType>(BaseType) && + "Cannot have ExtQualType of ExtQualType"); + } friend class ASTContext; // ASTContext creates these. public: Type *getBaseType() const { return BaseType; } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index bd9279fb50..024fbf8968 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -715,71 +715,89 @@ QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) { QualType CanT = getCanonicalType(T); if (CanT.getAddressSpace() == AddressSpace) return T; + + // If we are composing extended qualifiers together, merge together into one + // ExtQualType node. + unsigned CVRQuals = T.getCVRQualifiers(); + QualType::GCAttrTypes GCAttr = QualType::GCNone; + Type *TypeNode = T.getTypePtr(); - // Type's cannot have multiple ExtQuals, therefore we know we only have to deal - // with CVR qualifiers from here on out. - assert(CanT.getAddressSpace() == 0 && - "Type is already address space qualified"); + if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) { + // If this type already has an address space specified, it cannot get + // another one. + assert(EQT->getAddressSpace() == 0 && + "Type cannot be in multiple addr spaces!"); + GCAttr = EQT->getObjCGCAttr(); + TypeNode = EQT->getBaseType(); + } - // Check if we've already instantiated an address space qual'd type of this - // type. + // Check if we've already instantiated this type. llvm::FoldingSetNodeID ID; - ExtQualType::Profile(ID, T.getTypePtr(), AddressSpace, T.getObjCGCAttr()); + ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr); void *InsertPos = 0; if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(EXTQy, 0); - + return QualType(EXTQy, CVRQuals); + // If the base type isn't canonical, this won't be a canonical type either, // so fill in the canonical type field. QualType Canonical; - if (!T->isCanonical()) { + if (!TypeNode->isCanonical()) { Canonical = getAddrSpaceQualType(CanT, AddressSpace); - // Get the new insert position for the node we care about. + // Update InsertPos, the previous call could have invalidated it. ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos); assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; } - ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical, - AddressSpace, - QualType::GCNone); + ExtQualType *New = + new (*this, 8) ExtQualType(TypeNode, Canonical, AddressSpace, GCAttr); ExtQualTypes.InsertNode(New, InsertPos); Types.push_back(New); - return QualType(New, T.getCVRQualifiers()); + return QualType(New, CVRQuals); } -QualType ASTContext::getObjCGCQualType(QualType T, - QualType::GCAttrTypes attr) { +QualType ASTContext::getObjCGCQualType(QualType T, + QualType::GCAttrTypes GCAttr) { QualType CanT = getCanonicalType(T); - if (CanT.getObjCGCAttr() == attr) + if (CanT.getObjCGCAttr() == GCAttr) return T; - // Type's cannot have multiple ExtQuals, therefore we know we only have to deal - // with CVR qualifiers from here on out. - assert(CanT.getObjCGCAttr() == QualType::GCNone && - "Type is already gc qualified"); + // If we are composing extended qualifiers together, merge together into one + // ExtQualType node. + unsigned CVRQuals = T.getCVRQualifiers(); + Type *TypeNode = T.getTypePtr(); + unsigned AddressSpace = 0; + + if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) { + // If this type already has an address space specified, it cannot get + // another one. + assert(EQT->getObjCGCAttr() == QualType::GCNone && + "Type cannot be in multiple addr spaces!"); + AddressSpace = EQT->getAddressSpace(); + TypeNode = EQT->getBaseType(); + } // Check if we've already instantiated an gc qual'd type of this type. llvm::FoldingSetNodeID ID; - ExtQualType::Profile(ID, T.getTypePtr(), T.getAddressSpace(), attr); + ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr); void *InsertPos = 0; if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(EXTQy, 0); + return QualType(EXTQy, CVRQuals); // If the base 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 = getObjCGCQualType(CanT, attr); + Canonical = getObjCGCQualType(CanT, GCAttr); - // Get the new insert position for the node we care about. + // Update InsertPos, the previous call could have invalidated it. ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos); assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; } - ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical, - 0, attr); + ExtQualType *New = + new (*this, 8) ExtQualType(TypeNode, Canonical, AddressSpace, GCAttr); ExtQualTypes.InsertNode(New, InsertPos); Types.push_back(New); - return QualType(New, T.getCVRQualifiers()); + return QualType(New, CVRQuals); } /// getComplexType - Return the uniqued reference to the type for a complex @@ -2394,16 +2412,16 @@ bool ASTContext::isObjCObjectPointerType(QualType Ty) const { /// garbage collection attribute. /// QualType::GCAttrTypes ASTContext::getObjCGCAttrKind(const QualType &Ty) const { - QualType::GCAttrTypes attr = QualType::GCNone; + QualType::GCAttrTypes GCAttrs = QualType::GCNone; if (getLangOptions().ObjC1 && getLangOptions().getGCMode() != LangOptions::NonGC) { - attr = Ty.getObjCGCAttr(); + GCAttrs = Ty.getObjCGCAttr(); // Default behavious under objective-c's gc is for objective-c pointers // be treated as though they were declared as __strong. - if (attr == QualType::GCNone && isObjCObjectPointerType(Ty)) - attr = QualType::Strong; + if (GCAttrs == QualType::GCNone && isObjCObjectPointerType(Ty)) + GCAttrs = QualType::Strong; } - return attr; + return GCAttrs; } //===----------------------------------------------------------------------===// |