diff options
author | John McCall <rjmccall@apple.com> | 2009-09-24 19:53:00 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-09-24 19:53:00 +0000 |
commit | 8ccfcb51ee020c4ca0e76838a2ef57cb5bb77914 (patch) | |
tree | 13ac964a39ac7c94d225bf75d6c92141cdfefbc2 /clang/lib/AST | |
parent | 6d98ede7e8511180699b41e12b2de5f979d8bb14 (diff) | |
download | bcm5719-llvm-8ccfcb51ee020c4ca0e76838a2ef57cb5bb77914.tar.gz bcm5719-llvm-8ccfcb51ee020c4ca0e76838a2ef57cb5bb77914.zip |
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.
llvm-svn: 82705
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 404 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 11 | ||||
-rw-r--r-- | clang/lib/AST/DeclarationName.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/StmtDumper.cpp | 9 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 229 |
7 files changed, 260 insertions, 407 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 8fe5852328f..a2a88af44f8 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -59,6 +59,13 @@ ASTContext::~ASTContext() { } { + 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 @@ unsigned ASTContext::getDeclAlignInBytes(const Decl *D) { /// 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 @@ ASTContext::getTypeInfo(const Type *T) { 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 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) { // 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 (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 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 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); + // 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); - // 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 @@ QualType ASTContext::getObjCGCQualType(QualType T, 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(); - } - // 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 we are composing extended qualifiers together, merge together + // into one ExtQuals node. + QualifierCollector Quals; + const Type *TypeNode = Quals.strip(T); - // 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); + // If this type already has an ObjCGC specified, it cannot get + // another one. + assert(!Quals.hasObjCGCAttr() && + "Type cannot have multiple ObjCGCs!"); + Quals.addObjCGCAttr(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 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, 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 @@ QualType ASTContext::getPointerDiffType() const { /// 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(); + + // The canonical internal type will be the canonical type *except* + // that we push type qualifiers down through array types. - // If the result has type qualifiers, make sure to canonicalize them as well. - unsigned TypeQuals = T.getCVRQualifiers() | CanType.getCVRQualifiers(); - if (TypeQuals == 0) + // 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 @@ CanQualType ASTContext::getCanonicalType(QualType T) { DSAT->getSizeExpr() ? DSAT->getSizeExpr()->Retain() : 0, DSAT->getSizeModifier(), - DSAT->getIndexTypeQualifier(), + DSAT->getIndexTypeCVRQualifiers(), DSAT->getBracketsRange())); VariableArrayType *VAT = cast<VariableArrayType>(AT); @@ -2199,7 +2190,7 @@ CanQualType ASTContext::getCanonicalType(QualType T) { VAT->getSizeExpr() ? VAT->getSizeExpr()->Retain() : 0, VAT->getSizeModifier(), - VAT->getIndexTypeQualifier(), + VAT->getIndexTypeCVRQualifiers(), VAT->getBracketsRange())); } @@ -2316,68 +2307,47 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) { 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 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { 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 ASTContext::getArrayDecayedType(QualType Ty) { 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 ASTContext::getCFConstantStringType() { 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 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, 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 @@ bool ASTContext::isObjCNSObjectType(QualType Ty) const { /// 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, 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; } } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index f3ea04305bb..fc04ed401bf 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -146,7 +146,7 @@ CXXRecordDecl::setBases(ASTContext &C, } bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { - return getCopyConstructor(Context, QualType::Const) != 0; + return getCopyConstructor(Context, Qualifiers::Const) != 0; } CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, @@ -167,8 +167,8 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, FoundTQs)) { - if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) || - (!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const))) + if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) || + (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const))) return cast<CXXConstructorDecl>(*Con); } @@ -508,7 +508,8 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { ClassTy = TD->getInjectedClassNameType(C); else ClassTy = C.getTagDeclType(getParent()); - ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers()); + ClassTy = C.getQualifiedType(ClassTy, + Qualifiers::fromCVRMask(getTypeQualifiers())); return C.getPointerType(ClassTy); } @@ -600,6 +601,8 @@ CXXConstructorDecl::isCopyConstructor(ASTContext &Context, if (PointeeType.getUnqualifiedType() != ClassTy) return false; + // FIXME: other qualifiers? + // We have a copy constructor. TypeQuals = PointeeType.getCVRQualifiers(); return true; diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp index a01a89201ae..101ddd25093 100644 --- a/clang/lib/AST/DeclarationName.cpp +++ b/clang/lib/AST/DeclarationName.cpp @@ -309,11 +309,11 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, switch (Kind) { case DeclarationName::CXXConstructorName: EKind = DeclarationNameExtra::CXXConstructor; - assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified"); + assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified"); break; case DeclarationName::CXXDestructorName: EKind = DeclarationNameExtra::CXXDestructor; - assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified"); + assert(!Ty.hasQualifiers() && "Destructor type must be unqualified"); break; case DeclarationName::CXXConversionFunctionName: EKind = DeclarationNameExtra::CXXConversionFunction; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 9d2d46fa0c1..dc9cee13a9c 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -825,7 +825,7 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { return LV_NotObjectType; // Allow qualified void which is an incomplete type other than void (yuck). - if (TR->isVoidType() && !Ctx.getCanonicalType(TR).getCVRQualifiers()) + if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers()) return LV_IncompleteVoidType; return LV_Valid; @@ -1120,7 +1120,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { // dereferencing to a pointer is always a gc'able candidate, // unless it is __weak. return T->isPointerType() && - (Ctx.getObjCGCAttrKind(T) != QualType::Weak); + (Ctx.getObjCGCAttrKind(T) != Qualifiers::Weak); } return false; } @@ -1397,7 +1397,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) return NoDiag(); if (Ctx.getLangOptions().CPlusPlus && - E->getType().getCVRQualifiers() == QualType::Const) { + E->getType().getCVRQualifiers() == Qualifiers::Const) { // C++ 7.1.5.1p2 // A variable of non-volatile const-qualified integral or enumeration // type initialized by an ICE can be used in ICEs. @@ -1635,7 +1635,7 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const { // Check that it is a cast to void*. if (const PointerType *PT = CE->getType()->getAs<PointerType>()) { QualType Pointee = PT->getPointeeType(); - if (Pointee.getCVRQualifiers() == 0 && + if (!Pointee.hasQualifiers() && Pointee->isVoidType() && // to void* CE->getSubExpr()->getType()->isIntegerType()) // from int. return CE->getSubExpr()->isNullPointerConstant(Ctx); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5123aaa7ca7..2aefae6fd74 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -783,7 +783,7 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { // In C++, const, non-volatile integers initialized with ICEs are ICEs. // In C, they can also be folded, although they are not ICEs. - if (E->getType().getCVRQualifiers() == QualType::Const) { + if (E->getType().getCVRQualifiers() == Qualifiers::Const) { if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) { if (APValue *V = D->getEvaluatedValue()) return Success(V->getInt(), E); diff --git a/clang/lib/AST/StmtDumper.cpp b/clang/lib/AST/StmtDumper.cpp index ed92da375f3..0465999a94c 100644 --- a/clang/lib/AST/StmtDumper.cpp +++ b/clang/lib/AST/StmtDumper.cpp @@ -87,13 +87,10 @@ namespace { fprintf(F, "'%s'", T.getAsString().c_str()); if (!T.isNull()) { - // If the type is directly a typedef, strip off typedefness to give at - // least one level of concreteness. - if (TypedefType *TDT = dyn_cast<TypedefType>(T)) { - QualType Simplified = - TDT->LookThroughTypedefs().getQualifiedType(T.getCVRQualifiers()); + // If the type is sugared, also dump a (shallow) desugared type. + QualType Simplified = T.getDesugaredType(); + if (Simplified != T) fprintf(F, ":'%s'", Simplified.getAsString().c_str()); - } } } void DumpStmt(const Stmt *Node) { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 27832116616..bda06ace1bc 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -101,12 +101,8 @@ const Type *Type::getArrayElementTypeNoTypeQual() const { return ATy->getElementType().getTypePtr(); // If the canonical form of this type isn't the right kind, reject it. - if (!isa<ArrayType>(CanonicalType)) { - // Look through type qualifiers - if (ArrayType *AT = dyn_cast<ArrayType>(CanonicalType.getUnqualifiedType())) - return AT->getElementType().getTypePtr(); + if (!isa<ArrayType>(CanonicalType)) return 0; - } // If this is a typedef for an array type, strip the typedef off without // losing all typedef information. @@ -125,8 +121,8 @@ const Type *Type::getArrayElementTypeNoTypeQual() const { /// decide whether it is worth providing a desugared form of the type /// or not. QualType QualType::getDesugaredType(bool ForDisplay) const { - return getTypePtr()->getDesugaredType(ForDisplay) - .getWithAdditionalQualifiers(getCVRQualifiers()); + QualifierCollector Qs; + return Qs.apply(Qs.strip(*this)->getDesugaredType(ForDisplay)); } /// getDesugaredType - Return the specified type with any "sugar" removed from @@ -181,8 +177,6 @@ QualType Type::getDesugaredType(bool ForDisplay) const { bool Type::isVoidType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Void; - if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType)) - return AS->getBaseType()->isVoidType(); return false; } @@ -190,15 +184,11 @@ bool Type::isObjectType() const { if (isa<FunctionType>(CanonicalType) || isa<ReferenceType>(CanonicalType) || isa<IncompleteArrayType>(CanonicalType) || isVoidType()) return false; - if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType)) - return AS->getBaseType()->isObjectType(); return true; } bool Type::isDerivedType() const { switch (CanonicalType->getTypeClass()) { - case ExtQual: - return cast<ExtQualType>(CanonicalType)->getBaseType()->isDerivedType(); case Pointer: case VariableArray: case ConstantArray: @@ -241,39 +231,19 @@ bool Type::isUnionType() const { bool Type::isComplexType() const { if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType)) return CT->getElementType()->isFloatingType(); - if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType)) - return AS->getBaseType()->isComplexType(); return false; } bool Type::isComplexIntegerType() const { // Check for GCC complex integer extension. - if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType)) - return CT->getElementType()->isIntegerType(); - if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType)) - return AS->getBaseType()->isComplexIntegerType(); - return false; + return getAsComplexIntegerType(); } const ComplexType *Type::getAsComplexIntegerType() const { - // Are we directly a complex type? - if (const ComplexType *CTy = dyn_cast<ComplexType>(this)) { - if (CTy->getElementType()->isIntegerType()) - return CTy; - return 0; - } - - // If the canonical form of this type isn't what we want, reject it. - if (!isa<ComplexType>(CanonicalType)) { - // Look through type qualifiers (e.g. ExtQualType's). - if (isa<ComplexType>(CanonicalType.getUnqualifiedType())) - return CanonicalType.getUnqualifiedType()->getAsComplexIntegerType(); - return 0; - } - - // If this is a typedef for a complex type, strip the typedef off without - // losing all typedef information. - return cast<ComplexType>(getDesugaredType()); + if (const ComplexType *Complex = getAs<ComplexType>()) + if (Complex->getElementType()->isIntegerType()) + return Complex; + return 0; } QualType Type::getPointeeType() const { @@ -335,9 +305,6 @@ const RecordType *Type::getAsStructureType() const { // losing all typedef information. return cast<RecordType>(getDesugaredType()); } - // Look through type qualifiers - if (isa<RecordType>(CanonicalType.getUnqualifiedType())) - return CanonicalType.getUnqualifiedType()->getAsStructureType(); return 0; } @@ -358,9 +325,6 @@ const RecordType *Type::getAsUnionType() const { return cast<RecordType>(getDesugaredType()); } - // Look through type qualifiers - if (isa<RecordType>(CanonicalType.getUnqualifiedType())) - return CanonicalType.getUnqualifiedType()->getAsUnionType(); return 0; } @@ -416,8 +380,6 @@ bool Type::isIntegerType() const { return true; if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isIntegerType(); - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isIntegerType(); return false; } @@ -431,24 +393,18 @@ bool Type::isIntegralType() const { // FIXME: In C++, enum types are never integral. if (isa<FixedWidthIntType>(CanonicalType)) return true; - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isIntegralType(); return false; } bool Type::isEnumeralType() const { if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) return TT->getDecl()->isEnum(); - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isEnumeralType(); return false; } bool Type::isBooleanType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Bool; - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isBooleanType(); return false; } @@ -458,16 +414,12 @@ bool Type::isCharType() const { BT->getKind() == BuiltinType::UChar || BT->getKind() == BuiltinType::Char_S || BT->getKind() == BuiltinType::SChar; - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isCharType(); return false; } bool Type::isWideCharType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::WChar; - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isWideCharType(); return false; } @@ -490,8 +442,6 @@ bool Type::isSignedIntegerType() const { if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isSignedIntegerType(); - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isSignedIntegerType(); return false; } @@ -514,8 +464,6 @@ bool Type::isUnsignedIntegerType() const { if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isUnsignedIntegerType(); - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isUnsignedIntegerType(); return false; } @@ -527,8 +475,6 @@ bool Type::isFloatingType() const { return CT->getElementType()->isFloatingType(); if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isFloatingType(); - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isFloatingType(); return false; } @@ -538,8 +484,6 @@ bool Type::isRealFloatingType() const { BT->getKind() <= BuiltinType::LongDouble; if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isRealFloatingType(); - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isRealFloatingType(); return false; } @@ -553,8 +497,6 @@ bool Type::isRealType() const { return true; if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isRealType(); - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isRealType(); return false; } @@ -568,8 +510,6 @@ bool Type::isArithmeticType() const { return ET->getDecl()->isDefinition(); if (isa<FixedWidthIntType>(CanonicalType)) return true; - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isArithmeticType(); return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType); } @@ -583,8 +523,6 @@ bool Type::isScalarType() const { return true; return false; } - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isScalarType(); if (isa<FixedWidthIntType>(CanonicalType)) return true; return isa<PointerType>(CanonicalType) || @@ -611,8 +549,6 @@ bool Type::isAggregateType() const { return true; } - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isAggregateType(); return isa<ArrayType>(CanonicalType); } @@ -620,8 +556,6 @@ bool Type::isAggregateType() const { /// according to the rules of C99 6.7.5p3. It is not legal to call this on /// incomplete types or dependent types. bool Type::isConstantSizeType() const { - if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType)) - return EXTQT->getBaseType()->isConstantSizeType(); assert(!isIncompleteType() && "This doesn't make sense for incomplete types"); assert(!isDependentType() && "This doesn't make sense for dependent types"); // The VAT must have a size, as it is known to be complete. @@ -634,8 +568,6 @@ bool Type::isConstantSizeType() const { bool Type::isIncompleteType() const { switch (CanonicalType->getTypeClass()) { default: return false; - case ExtQual: - return cast<ExtQualType>(CanonicalType)->getBaseType()->isIncompleteType(); case Builtin: // Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never // be completed. @@ -664,8 +596,6 @@ bool Type::isPODType() const { switch (CanonicalType->getTypeClass()) { // Everything not explicitly mentioned is not POD. default: return false; - case ExtQual: - return cast<ExtQualType>(CanonicalType)->getBaseType()->isPODType(); case VariableArray: case ConstantArray: // IncompleteArray is caught by isIncompleteType() above. @@ -827,21 +757,16 @@ QualType TypedefType::LookThroughTypedefs() const { return FirstType; // Otherwise, do the fully general loop. - unsigned TypeQuals = 0; - const TypedefType *TDT = this; - while (1) { - QualType CurType = TDT->getDecl()->getUnderlyingType(); + QualifierCollector Qs; + QualType CurType; + const TypedefType *TDT = this; + do { + CurType = TDT->getDecl()->getUnderlyingType(); + TDT = dyn_cast<TypedefType>(Qs.strip(CurType)); + } while (TDT); - /// FIXME: - /// FIXME: This is incorrect for ExtQuals! - /// FIXME: - TypeQuals |= CurType.getCVRQualifiers(); - - TDT = dyn_cast<TypedefType>(CurType); - if (TDT == 0) - return QualType(CurType.getTypePtr(), TypeQuals); - } + return Qs.apply(CurType); } TypeOfExprType::TypeOfExprType(Expr *E, QualType can) @@ -961,27 +886,20 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, Args[Idx].Profile(ID, Context); } -const Type *QualifierSet::strip(const Type* T) { - QualType DT = T->getDesugaredType(); - addCVR(DT.getCVRQualifiers()); +QualType QualifierCollector::apply(QualType QT) const { + if (!hasNonFastQualifiers()) + return QT.withFastQualifiers(getFastQualifiers()); - if (const ExtQualType* EQT = dyn_cast<ExtQualType>(DT)) { - if (EQT->getAddressSpace()) - addAddressSpace(EQT->getAddressSpace()); - if (EQT->getObjCGCAttr()) - addObjCGCAttrType(EQT->getObjCGCAttr()); - return EQT->getBaseType(); - } else { - // Use the sugared type unless desugaring found extra qualifiers. - return (DT.getCVRQualifiers() ? DT.getTypePtr() : T); - } + assert(Context && "extended qualifiers but no context!"); + return Context->getQualifiedType(QT, *this); } -QualType QualifierSet::apply(QualType QT, ASTContext& C) { - QT = QT.getWithAdditionalQualifiers(getCVRMask()); - if (hasObjCGCAttrType()) QT = C.getObjCGCQualType(QT, getObjCGCAttrType()); - if (hasAddressSpace()) QT = C.getAddrSpaceQualType(QT, getAddressSpace()); - return QT; +QualType QualifierCollector::apply(const Type *T) const { + if (!hasNonFastQualifiers()) + return QualType(T, getFastQualifiers()); + + assert(Context && "extended qualifiers but no context!"); + return Context->getQualifiedType(T, *this); } @@ -1012,14 +930,46 @@ void Type::dump() const { static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { - // Note: funkiness to ensure we get a space only between quals. - bool NonePrinted = true; - if (TypeQuals & QualType::Const) - S += "const", NonePrinted = false; - if (TypeQuals & QualType::Volatile) - S += (NonePrinted+" volatile"), NonePrinted = false; - if (TypeQuals & QualType::Restrict) - S += (NonePrinted+" restrict"), NonePrinted = false; + if (TypeQuals & Qualifiers::Const) { + if (!S.empty()) S += ' '; + S += "const"; + } + if (TypeQuals & Qualifiers::Volatile) { + if (!S.empty()) S += ' '; + S += "volatile"; + } + if (TypeQuals & Qualifiers::Restrict) { + if (!S.empty()) S += ' '; + S += "restrict"; + } +} + +std::string Qualifiers::getAsString() const { + LangOptions LO; + return getAsString(PrintingPolicy(LO)); +} + +// Appends qualifiers to the given string, separated by spaces. Will +// prefix a space if the string is non-empty. Will not append a final +// space. +void Qualifiers::getAsStringInternal(std::string &S, + const PrintingPolicy&) const { + AppendTypeQualList(S, getCVRQualifiers()); + if (unsigned AddressSpace = getAddressSpace()) { + if (!S.empty()) S += ' '; + S += "__attribute__((address_space("; + S += llvm::utostr_32(AddressSpace); + S += ")))"; + } + if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { + if (!S.empty()) S += ' '; + S += "__attribute__((objc_gc("; + if (GCAttrType == Qualifiers::Weak) + S += "weak"; + else + S += "strong"; + S += ")))"; + } } std::string QualType::getAsString() const { @@ -1041,13 +991,16 @@ QualType::getAsStringInternal(std::string &S, return; // Print qualifiers as appropriate. - if (unsigned Tq = getCVRQualifiers()) { + Qualifiers Quals = getQualifiers(); + if (!Quals.empty()) { std::string TQS; - AppendTypeQualList(TQS, Tq); - if (!S.empty()) - S = TQS + ' ' + S; - else - S = TQS; + Quals.getAsStringInternal(TQS, Policy); + + if (!S.empty()) { + TQS += ' '; + TQS += S; + } + std::swap(S, TQS); } getTypePtr()->getAsStringInternal(S, Policy); @@ -1084,25 +1037,6 @@ void ComplexType::getAsStringInternal(std::string &S, const PrintingPolicy &Poli S = "_Complex " + S; } -void ExtQualType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - bool NeedsSpace = false; - if (AddressSpace) { - S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S; - NeedsSpace = true; - } - if (GCAttrType != QualType::GCNone) { - if (NeedsSpace) - S += ' '; - S += "__attribute__((objc_gc("; - if (GCAttrType == QualType::Weak) - S += "weak"; - else - S += "strong"; - S += ")))"; - } - BaseType->getAsStringInternal(S, Policy); -} - void PointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { S = '*' + S; @@ -1195,8 +1129,8 @@ void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPoli void VariableArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { S += '['; - if (getIndexTypeQualifier()) { - AppendTypeQualList(S, getIndexTypeQualifier()); + if (getIndexTypeQualifiers().hasQualifiers()) { + AppendTypeQualList(S, getIndexTypeCVRQualifiers()); S += ' '; } @@ -1219,8 +1153,8 @@ void VariableArrayType::getAsStringInternal(std::string &S, const PrintingPolicy void DependentSizedArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { S += '['; - if (getIndexTypeQualifier()) { - AppendTypeQualList(S, getIndexTypeQualifier()); + if (getIndexTypeQualifiers().hasQualifiers()) { + AppendTypeQualList(S, getIndexTypeCVRQualifiers()); S += ' '; } @@ -1536,6 +1470,9 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString, } ObjCQIString += '>'; } + + PointeeType.getQualifiers().getAsStringInternal(ObjCQIString, Policy); + if (!isObjCIdType() && !isObjCQualifiedIdType()) ObjCQIString += " *"; // Don't forget the implicit pointer. else if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. |