Refactor the representation of qualifiers to bring ExtQualType out of the
Type hierarchy. Demote 'volatile' to extended-qualifier status. Audit our
use of qualifiers and fix a few places that weren't dealing with qualifiers
quite right; many more remain.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82705 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 8fe5852..a2a88af 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -59,6 +59,13 @@
}
{
+ llvm::FoldingSet<ExtQuals>::iterator
+ I = ExtQualNodes.begin(), E = ExtQualNodes.end();
+ while (I != E)
+ Deallocate(&*I++);
+ }
+
+ {
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end();
while (I != E) {
@@ -525,6 +532,10 @@
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
+///
+/// FIXME: Pointers into different addr spaces could have different sizes and
+/// alignment requirements: getPointerInfo should take an AddrSpace, this
+/// should take a QualType, &c.
std::pair<uint64_t, unsigned>
ASTContext::getTypeInfo(const Type *T) {
uint64_t Width=0;
@@ -656,10 +667,6 @@
Width = std::max(llvm::NextPowerOf2(Width - 1), (uint64_t)8);
Align = Width;
break;
- case Type::ExtQual:
- // FIXME: Pointers into different addr spaces could have different sizes and
- // alignment requirements: getPointerInfo should take an AddrSpace.
- return getTypeInfo(QualType(cast<ExtQualType>(T)->getBaseType(), 0));
case Type::ObjCObjectPointer:
Width = Target.getPointerWidth(0);
Align = Target.getPointerAlign(0);
@@ -1002,52 +1009,58 @@
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
+QualType ASTContext::getExtQualType(const Type *TypeNode, Qualifiers Quals) {
+ unsigned Fast = Quals.getFastQualifiers();
+ Quals.removeFastQualifiers();
+
+ // Check if we've already instantiated this type.
+ llvm::FoldingSetNodeID ID;
+ ExtQuals::Profile(ID, TypeNode, Quals);
+ void *InsertPos = 0;
+ if (ExtQuals *EQ = ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos)) {
+ assert(EQ->getQualifiers() == Quals);
+ QualType T = QualType(EQ, Fast);
+ return T;
+ }
+
+ ExtQuals *New = new (*this, 8) ExtQuals(*this, TypeNode, Quals);
+ ExtQualNodes.InsertNode(New, InsertPos);
+ QualType T = QualType(New, Fast);
+ return T;
+}
+
+QualType ASTContext::getVolatileType(QualType T) {
+ QualType CanT = getCanonicalType(T);
+ if (CanT.isVolatileQualified()) return T;
+
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
+ Quals.addVolatile();
+
+ return getExtQualType(TypeNode, Quals);
+}
+
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();
+ // If we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
- 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();
- }
+ // If this type already has an address space specified, it cannot get
+ // another one.
+ assert(!Quals.hasAddressSpace() &&
+ "Type cannot be in multiple addr spaces!");
+ Quals.addAddressSpace(AddressSpace);
- // Check if we've already instantiated this type.
- llvm::FoldingSetNodeID ID;
- ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
- void *InsertPos = 0;
- if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
- 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 (!TypeNode->isCanonical()) {
- Canonical = getAddrSpaceQualType(CanT, AddressSpace);
-
- // 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(TypeNode, Canonical, AddressSpace, GCAttr);
- ExtQualTypes.InsertNode(New, InsertPos);
- Types.push_back(New);
- return QualType(New, CVRQuals);
+ return getExtQualType(TypeNode, Quals);
}
QualType ASTContext::getObjCGCQualType(QualType T,
- QualType::GCAttrTypes GCAttr) {
+ Qualifiers::GC GCAttr) {
QualType CanT = getCanonicalType(T);
if (CanT.getObjCGCAttr() == GCAttr)
return T;
@@ -1059,75 +1072,48 @@
return getPointerType(ResultType);
}
}
- // 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 ObjCGC specified, it cannot get
- // another one.
- assert(EQT->getObjCGCAttr() == QualType::GCNone &&
- "Type cannot have multiple ObjCGCs!");
- AddressSpace = EQT->getAddressSpace();
- TypeNode = EQT->getBaseType();
- }
+ // If we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
- // Check if we've already instantiated an gc qual'd type of this type.
- llvm::FoldingSetNodeID ID;
- ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
- void *InsertPos = 0;
- if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(EXTQy, CVRQuals);
+ // If this type already has an ObjCGC specified, it cannot get
+ // another one.
+ assert(!Quals.hasObjCGCAttr() &&
+ "Type cannot have multiple ObjCGCs!");
+ Quals.addObjCGCAttr(GCAttr);
- // If the base type isn't canonical, this won't be a canonical type either,
- // so fill in the canonical type field.
- // FIXME: Isn't this also not canonical if the base type is a array
- // or pointer type? I can't find any documentation for objc_gc, though...
- QualType Canonical;
- if (!T->isCanonical()) {
- Canonical = getObjCGCQualType(CanT, GCAttr);
-
- // 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(TypeNode, Canonical, AddressSpace, GCAttr);
- ExtQualTypes.InsertNode(New, InsertPos);
- Types.push_back(New);
- return QualType(New, CVRQuals);
+ return getExtQualType(TypeNode, Quals);
}
QualType ASTContext::getNoReturnType(QualType T) {
- QualifierSet qs;
- qs.strip(T);
+ QualType ResultType;
if (T->isPointerType()) {
QualType Pointee = T->getAs<PointerType>()->getPointeeType();
- QualType ResultType = getNoReturnType(Pointee);
+ ResultType = getNoReturnType(Pointee);
ResultType = getPointerType(ResultType);
- ResultType.setCVRQualifiers(T.getCVRQualifiers());
- return qs.apply(ResultType, *this);
- }
- if (T->isBlockPointerType()) {
+ } else if (T->isBlockPointerType()) {
QualType Pointee = T->getAs<BlockPointerType>()->getPointeeType();
- QualType ResultType = getNoReturnType(Pointee);
+ ResultType = getNoReturnType(Pointee);
ResultType = getBlockPointerType(ResultType);
- ResultType.setCVRQualifiers(T.getCVRQualifiers());
- return qs.apply(ResultType, *this);
- }
- if (!T->isFunctionType())
- assert(0 && "can't noreturn qualify non-pointer to function or block type");
+ } else {
+ assert (T->isFunctionType()
+ && "can't noreturn qualify non-pointer to function or block type");
- if (const FunctionNoProtoType *F = T->getAs<FunctionNoProtoType>()) {
- return getFunctionNoProtoType(F->getResultType(), true);
+ if (const FunctionNoProtoType *F = T->getAs<FunctionNoProtoType>()) {
+ ResultType = getFunctionNoProtoType(F->getResultType(), true);
+ } else {
+ const FunctionProtoType *F = T->getAs<FunctionProtoType>();
+ ResultType
+ = getFunctionType(F->getResultType(), F->arg_type_begin(),
+ F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
+ F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
+ F->getNumExceptions(), F->exception_begin(), true);
+ }
}
- const FunctionProtoType *F = T->getAs<FunctionProtoType>();
- return getFunctionType(F->getResultType(), F->arg_type_begin(),
- F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
- F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
- F->getNumExceptions(), F->exception_begin(), true);
+
+ return getQualifiedType(ResultType, T.getQualifiers());
}
/// getComplexType - Return the uniqued reference to the type for a complex
@@ -1645,8 +1631,8 @@
const QualType *ExArray, bool NoReturn) {
if (LangOpts.CPlusPlus) {
for (unsigned i = 0; i != NumArgs; ++i)
- assert(!ArgArray[i].getCVRQualifiers() &&
- "C++ arguments can't have toplevel CVR qualifiers!");
+ assert(!ArgArray[i].hasQualifiers() &&
+ "C++ arguments can't have toplevel qualifiers!");
}
// Unique functions, to guarantee there is only one function of a particular
@@ -2157,33 +2143,38 @@
/// to be free of any of these, allowing two canonical types to be compared
/// for exact equality with a simple pointer comparison.
CanQualType ASTContext::getCanonicalType(QualType T) {
- QualType CanType = T.getTypePtr()->getCanonicalTypeInternal();
+ QualifierCollector Quals;
+ const Type *Ptr = Quals.strip(T);
+ QualType CanType = Ptr->getCanonicalTypeInternal();
- // If the result has type qualifiers, make sure to canonicalize them as well.
- unsigned TypeQuals = T.getCVRQualifiers() | CanType.getCVRQualifiers();
- if (TypeQuals == 0)
+ // The canonical internal type will be the canonical type *except*
+ // that we push type qualifiers down through array types.
+
+ // If there are no new qualifiers to push down, stop here.
+ if (!Quals.hasQualifiers())
return CanQualType::CreateUnsafe(CanType);
- // If the type qualifiers are on an array type, get the canonical type of the
- // array with the qualifiers applied to the element type.
+ // If the type qualifiers are on an array type, get the canonical
+ // type of the array with the qualifiers applied to the element
+ // type.
ArrayType *AT = dyn_cast<ArrayType>(CanType);
if (!AT)
- return CanQualType::CreateUnsafe(CanType.getQualifiedType(TypeQuals));
+ return CanQualType::CreateUnsafe(getQualifiedType(CanType, Quals));
// Get the canonical version of the element with the extra qualifiers on it.
// This can recursively sink qualifiers through multiple levels of arrays.
- QualType NewEltTy=AT->getElementType().getWithAdditionalQualifiers(TypeQuals);
+ QualType NewEltTy = getQualifiedType(AT->getElementType(), Quals);
NewEltTy = getCanonicalType(NewEltTy);
if (ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
return CanQualType::CreateUnsafe(
getConstantArrayType(NewEltTy, CAT->getSize(),
CAT->getSizeModifier(),
- CAT->getIndexTypeQualifier()));
+ CAT->getIndexTypeCVRQualifiers()));
if (IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT))
return CanQualType::CreateUnsafe(
getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
- IAT->getIndexTypeQualifier()));
+ IAT->getIndexTypeCVRQualifiers()));
if (DependentSizedArrayType *DSAT = dyn_cast<DependentSizedArrayType>(AT))
return CanQualType::CreateUnsafe(
@@ -2191,7 +2182,7 @@
DSAT->getSizeExpr() ?
DSAT->getSizeExpr()->Retain() : 0,
DSAT->getSizeModifier(),
- DSAT->getIndexTypeQualifier(),
+ DSAT->getIndexTypeCVRQualifiers(),
DSAT->getBracketsRange()));
VariableArrayType *VAT = cast<VariableArrayType>(AT);
@@ -2199,7 +2190,7 @@
VAT->getSizeExpr() ?
VAT->getSizeExpr()->Retain() : 0,
VAT->getSizeModifier(),
- VAT->getIndexTypeQualifier(),
+ VAT->getIndexTypeCVRQualifiers(),
VAT->getBracketsRange()));
}
@@ -2316,68 +2307,47 @@
const ArrayType *ASTContext::getAsArrayType(QualType T) {
// Handle the non-qualified case efficiently.
- if (T.getCVRQualifiers() == 0) {
+ if (!T.hasQualifiers()) {
// Handle the common positive case fast.
if (const ArrayType *AT = dyn_cast<ArrayType>(T))
return AT;
}
- // Handle the common negative case fast, ignoring CVR qualifiers.
+ // Handle the common negative case fast.
QualType CType = T->getCanonicalTypeInternal();
-
- // Make sure to look through type qualifiers (like ExtQuals) for the negative
- // test.
- if (!isa<ArrayType>(CType) &&
- !isa<ArrayType>(CType.getUnqualifiedType()))
+ if (!isa<ArrayType>(CType))
return 0;
- // Apply any CVR qualifiers from the array type to the element type. This
+ // Apply any qualifiers from the array type to the element type. This
// implements C99 6.7.3p8: "If the specification of an array type includes
// any type qualifiers, the element type is so qualified, not the array type."
// If we get here, we either have type qualifiers on the type, or we have
// sugar such as a typedef in the way. If we have type qualifiers on the type
// we must propagate them down into the element type.
- unsigned CVRQuals = T.getCVRQualifiers();
- unsigned AddrSpace = 0;
- Type *Ty = T.getTypePtr();
- // Rip through ExtQualType's and typedefs to get to a concrete type.
- while (1) {
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(Ty)) {
- AddrSpace = EXTQT->getAddressSpace();
- Ty = EXTQT->getBaseType();
- } else {
- T = Ty->getDesugaredType();
- if (T.getTypePtr() == Ty && T.getCVRQualifiers() == 0)
- break;
- CVRQuals |= T.getCVRQualifiers();
- Ty = T.getTypePtr();
- }
- }
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T.getDesugaredType());
// If we have a simple case, just return now.
const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
- if (ATy == 0 || (AddrSpace == 0 && CVRQuals == 0))
+ if (ATy == 0 || Qs.empty())
return ATy;
// Otherwise, we have an array and we have qualifiers on it. Push the
// qualifiers into the array element type and return a new array type.
// Get the canonical version of the element with the extra qualifiers on it.
// This can recursively sink qualifiers through multiple levels of arrays.
- QualType NewEltTy = ATy->getElementType();
- if (AddrSpace)
- NewEltTy = getAddrSpaceQualType(NewEltTy, AddrSpace);
- NewEltTy = NewEltTy.getWithAdditionalQualifiers(CVRQuals);
+ QualType NewEltTy = getQualifiedType(ATy->getElementType(), Qs);
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
CAT->getSizeModifier(),
- CAT->getIndexTypeQualifier()));
+ CAT->getIndexTypeCVRQualifiers()));
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
IAT->getSizeModifier(),
- IAT->getIndexTypeQualifier()));
+ IAT->getIndexTypeCVRQualifiers()));
if (const DependentSizedArrayType *DSAT
= dyn_cast<DependentSizedArrayType>(ATy))
@@ -2386,15 +2356,15 @@
DSAT->getSizeExpr() ?
DSAT->getSizeExpr()->Retain() : 0,
DSAT->getSizeModifier(),
- DSAT->getIndexTypeQualifier(),
+ DSAT->getIndexTypeCVRQualifiers(),
DSAT->getBracketsRange()));
const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
return cast<ArrayType>(getVariableArrayType(NewEltTy,
VAT->getSizeExpr() ?
- VAT->getSizeExpr()->Retain() : 0,
+ VAT->getSizeExpr()->Retain() : 0,
VAT->getSizeModifier(),
- VAT->getIndexTypeQualifier(),
+ VAT->getIndexTypeCVRQualifiers(),
VAT->getBracketsRange()));
}
@@ -2416,17 +2386,17 @@
QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
// int x[restrict 4] -> int *restrict
- return PtrTy.getQualifiedType(PrettyArrayType->getIndexTypeQualifier());
+ return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers());
}
QualType ASTContext::getBaseElementType(QualType QT) {
- QualifierSet qualifiers;
+ QualifierCollector Qs;
while (true) {
- const Type *UT = qualifiers.strip(QT);
+ const Type *UT = Qs.strip(QT);
if (const ArrayType *AT = getAsArrayType(QualType(UT,0))) {
QT = AT->getElementType();
} else {
- return qualifiers.apply(QT, *this);
+ return Qs.apply(QT);
}
}
}
@@ -2651,11 +2621,11 @@
QualType FieldTypes[4];
// const int *isa;
- FieldTypes[0] = getPointerType(IntTy.getQualifiedType(QualType::Const));
+ FieldTypes[0] = getPointerType(IntTy.withConst());
// int flags;
FieldTypes[1] = IntTy;
// const char *str;
- FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));
+ FieldTypes[2] = getPointerType(CharTy.withConst());
// long length;
FieldTypes[3] = LongTy;
@@ -3139,9 +3109,9 @@
return;
}
- if (T->isObjCInterfaceType()) {
+ if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
// @encode(class_name)
- ObjCInterfaceDecl *OI = T->getAs<ObjCInterfaceType>()->getDecl();
+ ObjCInterfaceDecl *OI = OIT->getDecl();
S += '{';
const IdentifierInfo *II = OI->getIdentifier();
S += II->getName();
@@ -3388,24 +3358,24 @@
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
/// garbage collection attribute.
///
-QualType::GCAttrTypes ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
- QualType::GCAttrTypes GCAttrs = QualType::GCNone;
+Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
+ Qualifiers::GC GCAttrs = Qualifiers::GCNone;
if (getLangOptions().ObjC1 &&
getLangOptions().getGCMode() != LangOptions::NonGC) {
GCAttrs = Ty.getObjCGCAttr();
// Default behavious under objective-c's gc is for objective-c pointers
// (or pointers to them) be treated as though they were declared
// as __strong.
- if (GCAttrs == QualType::GCNone) {
+ if (GCAttrs == Qualifiers::GCNone) {
if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
- GCAttrs = QualType::Strong;
+ GCAttrs = Qualifiers::Strong;
else if (Ty->isPointerType())
return getObjCGCAttrKind(Ty->getAs<PointerType>()->getPointeeType());
}
// Non-pointers have none gc'able attribute regardless of the attribute
// set on them.
else if (!Ty->isAnyPointerType() && !Ty->isBlockPointerType())
- return QualType::GCNone;
+ return Qualifiers::GCNone;
}
return GCAttrs;
}
@@ -3766,11 +3736,38 @@
if (LHSCan == RHSCan)
return LHS;
- // If the qualifiers are different, the types aren't compatible
- // Note that we handle extended qualifiers later, in the
- // case for ExtQualType.
- if (LHSCan.getCVRQualifiers() != RHSCan.getCVRQualifiers())
+ // If the qualifiers are different, the types aren't compatible... mostly.
+ Qualifiers LQuals = LHSCan.getQualifiers();
+ Qualifiers RQuals = RHSCan.getQualifiers();
+ if (LQuals != RQuals) {
+ // If any of these qualifiers are different, we have a type
+ // mismatch.
+ if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
+ LQuals.getAddressSpace() != RQuals.getAddressSpace())
+ return QualType();
+
+ // Exactly one GC qualifier difference is allowed: __strong is
+ // okay if the other type has no GC qualifier but is an Objective
+ // C object pointer (i.e. implicitly strong by default). We fix
+ // this by pretending that the unqualified type was actually
+ // qualified __strong.
+ Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
+ Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
+ assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
+
+ if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
+ return QualType();
+
+ if (GC_L == Qualifiers::Strong && RHSCan->isObjCObjectPointerType()) {
+ return mergeTypes(LHS, getObjCGCQualType(RHS, Qualifiers::Strong));
+ }
+ if (GC_R == Qualifiers::Strong && LHSCan->isObjCObjectPointerType()) {
+ return mergeTypes(getObjCGCQualType(LHS, Qualifiers::Strong), RHS);
+ }
return QualType();
+ }
+
+ // Okay, qualifiers are equal.
Type::TypeClass LHSClass = LHSCan->getTypeClass();
Type::TypeClass RHSClass = RHSCan->getTypeClass();
@@ -3780,59 +3777,6 @@
if (LHSClass == Type::FunctionProto) LHSClass = Type::FunctionNoProto;
if (RHSClass == Type::FunctionProto) RHSClass = Type::FunctionNoProto;
- // Strip off objc_gc attributes off the top level so they can be merged.
- // This is a complete mess, but the attribute itself doesn't make much sense.
- if (RHSClass == Type::ExtQual) {
- QualType::GCAttrTypes GCAttr = RHSCan.getObjCGCAttr();
- if (GCAttr != QualType::GCNone) {
- QualType::GCAttrTypes GCLHSAttr = LHSCan.getObjCGCAttr();
- // __weak attribute must appear on both declarations.
- // __strong attribue is redundant if other decl is an objective-c
- // object pointer (or decorated with __strong attribute); otherwise
- // issue error.
- if ((GCAttr == QualType::Weak && GCLHSAttr != GCAttr) ||
- (GCAttr == QualType::Strong && GCLHSAttr != GCAttr &&
- !LHSCan->isObjCObjectPointerType()))
- return QualType();
-
- RHS = QualType(cast<ExtQualType>(RHS.getDesugaredType())->getBaseType(),
- RHS.getCVRQualifiers());
- QualType Result = mergeTypes(LHS, RHS);
- if (!Result.isNull()) {
- if (Result.getObjCGCAttr() == QualType::GCNone)
- Result = getObjCGCQualType(Result, GCAttr);
- else if (Result.getObjCGCAttr() != GCAttr)
- Result = QualType();
- }
- return Result;
- }
- }
- if (LHSClass == Type::ExtQual) {
- QualType::GCAttrTypes GCAttr = LHSCan.getObjCGCAttr();
- if (GCAttr != QualType::GCNone) {
- QualType::GCAttrTypes GCRHSAttr = RHSCan.getObjCGCAttr();
- // __weak attribute must appear on both declarations. __strong
- // __strong attribue is redundant if other decl is an objective-c
- // object pointer (or decorated with __strong attribute); otherwise
- // issue error.
- if ((GCAttr == QualType::Weak && GCRHSAttr != GCAttr) ||
- (GCAttr == QualType::Strong && GCRHSAttr != GCAttr &&
- !RHSCan->isObjCObjectPointerType()))
- return QualType();
-
- LHS = QualType(cast<ExtQualType>(LHS.getDesugaredType())->getBaseType(),
- LHS.getCVRQualifiers());
- QualType Result = mergeTypes(LHS, RHS);
- if (!Result.isNull()) {
- if (Result.getObjCGCAttr() == QualType::GCNone)
- Result = getObjCGCQualType(Result, GCAttr);
- else if (Result.getObjCGCAttr() != GCAttr)
- Result = QualType();
- }
- return Result;
- }
- }
-
// Same as above for arrays
if (LHSClass == Type::VariableArray || LHSClass == Type::IncompleteArray)
LHSClass = Type::ConstantArray;
@@ -3988,34 +3932,6 @@
case Type::FixedWidthInt:
// Distinct fixed-width integers are not compatible.
return QualType();
- case Type::ExtQual:
- // FIXME: ExtQual types can be compatible even if they're not
- // identical!
- return QualType();
- // First attempt at an implementation, but I'm not really sure it's
- // right...
-#if 0
- ExtQualType* LQual = cast<ExtQualType>(LHSCan);
- ExtQualType* RQual = cast<ExtQualType>(RHSCan);
- if (LQual->getAddressSpace() != RQual->getAddressSpace() ||
- LQual->getObjCGCAttr() != RQual->getObjCGCAttr())
- return QualType();
- QualType LHSBase, RHSBase, ResultType, ResCanUnqual;
- LHSBase = QualType(LQual->getBaseType(), 0);
- RHSBase = QualType(RQual->getBaseType(), 0);
- ResultType = mergeTypes(LHSBase, RHSBase);
- if (ResultType.isNull()) return QualType();
- ResCanUnqual = getCanonicalType(ResultType).getUnqualifiedType();
- if (LHSCan.getUnqualifiedType() == ResCanUnqual)
- return LHS;
- if (RHSCan.getUnqualifiedType() == ResCanUnqual)
- return RHS;
- ResultType = getAddrSpaceQualType(ResultType, LQual->getAddressSpace());
- ResultType = getObjCGCQualType(ResultType, LQual->getObjCGCAttr());
- ResultType.setCVRQualifiers(LHSCan.getCVRQualifiers());
- return ResultType;
-#endif
-
case Type::TemplateSpecialization:
assert(false && "Dependent types have no size");
break;
@@ -4231,7 +4147,7 @@
break;
// FIXME: There's no way to have a built-in with an rvalue ref arg.
case 'C':
- Type = Type.getQualifiedType(QualType::Const);
+ Type = Type.withConst();
break;
}
}