aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-02-18 22:53:11 +0000
committerChris Lattner <sabre@nondot.org>2009-02-18 22:53:11 +0000
commitb7d2553edd2532d29b98b9e76bcf6a62bc48b417 (patch)
tree763eb32b281e1e27c695c165c5680be2ab868b13
parentb5da3e94b72a0106abd69c2a84bf650e773fa4ac (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.h7
-rw-r--r--lib/AST/ASTContext.cpp86
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;
}
//===----------------------------------------------------------------------===//