diff options
Diffstat (limited to 'clang/lib')
35 files changed, 743 insertions, 892 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'. diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 0a0d29169f1..8934a676144 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -1686,8 +1686,8 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, // FIXME: This is really ugly; should be refactored somehow unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); llvm::Value *V = Builder.CreateStructGEP(LoadOfThis, idx, "tmp"); - LHS = LValue::MakeAddr(V, FieldType.getCVRQualifiers(), - QualType::GCNone, FieldType.getAddressSpace()); + assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs"); + LHS = LValue::MakeAddr(V, MakeQualifiers(FieldType)); } else { LHS = EmitLValueForField(LoadOfThis, Field, false, 0); } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 1dbb6e67f26..0b9b3fc2708 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -629,7 +629,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, (Name + ".addr").c_str()); // FIXME: What are the right qualifiers here? llvm::Function::arg_iterator End = - ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp,0), AI); + ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI); EmitParmDecl(*Arg, Temp); // Name the arguments used in expansion and increment AI. diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0074316b4c2..197fcac150f 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -788,7 +788,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::RValueReference: case Type::Vector: case Type::ExtVector: - case Type::ExtQual: case Type::FixedWidthInt: case Type::MemberPointer: case Type::TemplateSpecialization: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a7eebbf1fd1..309f38e080a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -166,9 +166,7 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E, ErrorUnsupported(E, Name); llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); return LValue::MakeAddr(llvm::UndefValue::get(Ty), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + MakeQualifiers(E->getType())); } /// EmitLValue - Emit code to compute a designator that specifies the location @@ -746,17 +744,16 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { llvm::Value *V = CGM.GetAddrOfGlobalVar(VD); if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); } else { llvm::Value *V = LocalDeclMap[VD]; assert(V && "DeclRefExpr not entered in LocalDeclMap?"); + + Qualifiers Quals = MakeQualifiers(E->getType()); // local variables do not get their gc attribute set. - QualType::GCAttrTypes attr = QualType::GCNone; // local static? - if (!NonGCable) - attr = getContext().getObjCGCAttrKind(E->getType()); + if (NonGCable) Quals.removeObjCGCAttr(); + if (VD->hasAttr<BlocksAttr>()) { V = Builder.CreateStructGEP(V, 1, "forwarding"); V = Builder.CreateLoad(V, false); @@ -765,8 +762,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { } if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), attr, - E->getType().getAddressSpace()); + LV = LValue::MakeAddr(V, Quals); } LValue::SetObjCNonGC(LV, NonGCable); setObjCGCLValueClass(getContext(), E, LV); @@ -775,9 +771,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { llvm::Value *V = CGM.GetAddrOfGlobalVar(VD); if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); setObjCGCLValueClass(getContext(), E, LV); return LV; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) { @@ -794,16 +788,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { V = Builder.CreateBitCast(V, ConvertType(NoProtoType), "tmp"); } } - return LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(V, MakeQualifiers(E->getType())); } else if (const ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(E->getDecl())) { llvm::Value *V = LocalDeclMap[IPD]; assert(V && "BlockVarDecl not entered in LocalDeclMap?"); - return LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(V, MakeQualifiers(E->getType())); } assert(0 && "Unimp declref"); //an invalid LValue, but the assert will @@ -812,10 +802,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { } LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) { - return LValue::MakeAddr(GetAddrOfBlockDecl(E), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(GetAddrOfBlockDecl(E), MakeQualifiers(E->getType())); } LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { @@ -831,10 +818,10 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { QualType T = E->getSubExpr()->getType()->getPointeeType(); assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type"); - LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), - T.getCVRQualifiers(), - getContext().getObjCGCAttrKind(T), - ExprTy.getAddressSpace()); + Qualifiers Quals = MakeQualifiers(T); + Quals.setAddressSpace(ExprTy.getAddressSpace()); + + LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals); // We should not generate __weak write barrier on indirect reference // of a pointer to object; as in void foo (__weak id *param); *param = 0; // But, we continue to generate __strong write barrier on indirect write @@ -851,18 +838,18 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { unsigned Idx = E->getOpcode() == UnaryOperator::Imag; return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(), Idx, "idx"), - ExprTy.getCVRQualifiers(), - QualType::GCNone, - ExprTy.getAddressSpace()); + MakeQualifiers(ExprTy)); } } LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { - return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), 0); + return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), + Qualifiers()); } LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) { - return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E), 0); + return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E), + Qualifiers()); } @@ -894,7 +881,7 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) { llvm::Constant *C = CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str()); - return LValue::MakeAddr(C, 0); + return LValue::MakeAddr(C, Qualifiers()); } LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { @@ -923,7 +910,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { Idx = Builder.CreateIntCast(Idx, llvm::Type::getInt32Ty(VMContext), IdxSigned, "vidx"); return LValue::MakeVectorElt(LHS.getAddress(), Idx, - E->getBase()->getType().getCVRQualifiers()); + E->getBase()->getType().getCVRQualifiers()); } // The base must be a pointer, which is not an aggregate. Emit it. @@ -973,10 +960,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { assert(!T.isNull() && "CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type"); - LValue LV = LValue::MakeAddr(Address, - T.getCVRQualifiers(), - getContext().getObjCGCAttrKind(T), - E->getBase()->getType().getAddressSpace()); + Qualifiers Quals = MakeQualifiers(T); + Quals.setAddressSpace(E->getBase()->getType().getAddressSpace()); + + LValue LV = LValue::MakeAddr(Address, Quals); if (getContext().getLangOptions().ObjC1 && getContext().getLangOptions().getGCMode() != LangOptions::NonGC) { LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext())); @@ -1009,9 +996,9 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { } else { const PointerType *PT = E->getBase()->getType()->getAs<PointerType>(); llvm::Value *Ptr = EmitScalarExpr(E->getBase()); - Base = LValue::MakeAddr(Ptr, PT->getPointeeType().getCVRQualifiers(), - QualType::GCNone, - PT->getPointeeType().getAddressSpace()); + Qualifiers Quals = MakeQualifiers(PT->getPointeeType()); + Quals.removeObjCGCAttr(); + Base = LValue::MakeAddr(Ptr, Quals); } // Encode the element access list into a vector of unsigned indices. @@ -1021,7 +1008,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { if (Base.isSimple()) { llvm::Constant *CV = GenerateConstantVector(VMContext, Indices); return LValue::MakeExtVectorElt(Base.getAddress(), CV, - Base.getQualifiers()); + Base.getVRQualifiers()); } assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); @@ -1037,7 +1024,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { } llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size()); return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV, - Base.getQualifiers()); + Base.getVRQualifiers()); } LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { @@ -1045,7 +1032,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { bool isNonGC = false; Expr *BaseExpr = E->getBase(); llvm::Value *BaseValue = NULL; - unsigned CVRQualifiers=0; + Qualifiers BaseQuals; // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. if (E->isArrow()) { @@ -1054,7 +1041,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { BaseExpr->getType()->getAs<PointerType>(); if (PTy->getPointeeType()->isUnionType()) isUnion = true; - CVRQualifiers = PTy->getPointeeType().getCVRQualifiers(); + BaseQuals = PTy->getPointeeType().getQualifiers(); } else if (isa<ObjCPropertyRefExpr>(BaseExpr->IgnoreParens()) || isa<ObjCImplicitSetterGetterRefExpr>( BaseExpr->IgnoreParens())) { @@ -1062,7 +1049,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { BaseValue = RV.getAggregateAddr(); if (BaseExpr->getType()->isUnionType()) isUnion = true; - CVRQualifiers = BaseExpr->getType().getCVRQualifiers(); + BaseQuals = BaseExpr->getType().getQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); if (BaseLV.isNonGC()) @@ -1072,14 +1059,14 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { QualType BaseTy = BaseExpr->getType(); if (BaseTy->isUnionType()) isUnion = true; - CVRQualifiers = BaseTy.getCVRQualifiers(); + BaseQuals = BaseTy.getQualifiers(); } FieldDecl *Field = dyn_cast<FieldDecl>(E->getMemberDecl()); // FIXME: Handle non-field member expressions assert(Field && "No code generation for non-field member references"); LValue MemExpLV = EmitLValueForField(BaseValue, Field, isUnion, - CVRQualifiers); + BaseQuals.getCVRQualifiers()); LValue::SetObjCNonGC(MemExpLV, isNonGC); setObjCGCLValueClass(getContext(), E, MemExpLV); return MemExpLV; @@ -1133,17 +1120,14 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, } if (Field->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - QualType::GCAttrTypes attr = getContext().getObjCGCAttrKind(Field->getType()); + + Qualifiers Quals = MakeQualifiers(Field->getType()); + Quals.addCVRQualifiers(CVRQualifiers); // __weak attribute on a field is ignored. - if (attr == QualType::Weak) - attr = QualType::GCNone; + if (Quals.getObjCGCAttr() == Qualifiers::Weak) + Quals.removeObjCGCAttr(); - LValue LV = - LValue::MakeAddr(V, - Field->getType().getCVRQualifiers()|CVRQualifiers, - attr, - Field->getType().getAddressSpace()); - return LV; + return LValue::MakeAddr(V, Quals); } LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){ @@ -1151,9 +1135,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){ llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral"); const Expr* InitExpr = E->getInitializer(); - LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers(), - QualType::GCNone, - E->getType().getAddressSpace()); + LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType())); if (E->getType()->isComplexType()) { EmitComplexExprIntoAddr(InitExpr, DeclPtr, false); @@ -1199,9 +1181,7 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) { EmitBlock(ContBlock); Temp = Builder.CreateLoad(Temp, "lv"); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } // ?: here should be an aggregate. @@ -1212,9 +1192,7 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) { llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); EmitAggExpr(E, Temp, false); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } /// EmitCastLValue - Casts are never lvalues. If a cast is needed by the code @@ -1254,18 +1232,14 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { GetAddressCXXOfBaseClass(LV.getAddress(), DerivedClassDecl, BaseClassDecl, /*NullCheckValue=*/false); - return LValue::MakeAddr(Base, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(Base, MakeQualifiers(E->getType())); } case CastExpr::CK_ToUnion: { llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); EmitAnyExpr(E->getSubExpr(), Temp, false); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } } } @@ -1327,9 +1301,7 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); EmitAggExpr(E, Temp, false); // FIXME: Are these qualifiers correct? - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { @@ -1340,23 +1312,17 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { "Can't have a scalar return unless the return type is a " "reference type!"); - return LValue::MakeAddr(RV.getScalarVal(), E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType())); } - return LValue::MakeAddr(RV.getAggregateAddr(), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) { // FIXME: This shouldn't require another copy. llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); EmitAggExpr(E, Temp, false); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - QualType::GCNone, E->getType().getAddressSpace()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } LValue @@ -1368,8 +1334,7 @@ CodeGenFunction::EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E) { LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "tmp"); EmitCXXConstructExpr(Temp, E); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - QualType::GCNone, E->getType().getAddressSpace()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } LValue @@ -1385,10 +1350,7 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { // Can only get l-value for message expression returning aggregate type RValue RV = EmitObjCMessageExpr(E); // FIXME: can this be volatile? - return LValue::MakeAddr(RV.getAggregateAddr(), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface, @@ -1408,22 +1370,23 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) { // FIXME: A lot of the code below could be shared with EmitMemberExpr. llvm::Value *BaseValue = 0; const Expr *BaseExpr = E->getBase(); - unsigned CVRQualifiers = 0; + Qualifiers BaseQuals; QualType ObjectTy; if (E->isArrow()) { BaseValue = EmitScalarExpr(BaseExpr); ObjectTy = BaseExpr->getType()->getPointeeType(); - CVRQualifiers = ObjectTy.getCVRQualifiers(); + BaseQuals = ObjectTy.getQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); // FIXME: this isn't right for bitfields. BaseValue = BaseLV.getAddress(); ObjectTy = BaseExpr->getType(); - CVRQualifiers = ObjectTy.getCVRQualifiers(); + BaseQuals = ObjectTy.getQualifiers(); } LValue LV = - EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), CVRQualifiers); + EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), + BaseQuals.getCVRQualifiers()); setObjCGCLValueClass(getContext(), E, LV); return LV; } @@ -1453,10 +1416,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { // Can only get l-value for message expression returning aggregate type RValue RV = EmitAnyExprToTemp(E); // FIXME: can this be volatile? - return LValue::MakeAddr(RV.getAggregateAddr(), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType()), - E->getType().getAddressSpace()); + return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 2e7e8686169..e19fb0065fc 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -181,7 +181,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { llvm::Value *CastPtr = Builder.CreateBitCast(DestPtr, CGF.ConvertType(PtrTy)); EmitInitializationToLValue(E->getSubExpr(), - LValue::MakeAddr(CastPtr, 0)); + LValue::MakeAddr(CastPtr, Qualifiers())); return; } @@ -316,7 +316,7 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { return; } - EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, 0)); + EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, Qualifiers())); } void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { @@ -429,15 +429,16 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { QualType ElementType = CGF.getContext().getCanonicalType(E->getType()); ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType(); - unsigned CVRqualifier = ElementType.getCVRQualifiers(); + // FIXME: were we intentionally ignoring address spaces and GC attributes? + Qualifiers Quals = CGF.MakeQualifiers(ElementType); for (uint64_t i = 0; i != NumArrayElements; ++i) { llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array"); if (i < NumInitElements) EmitInitializationToLValue(E->getInit(i), - LValue::MakeAddr(NextVal, CVRqualifier)); + LValue::MakeAddr(NextVal, Quals)); else - EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, CVRqualifier), + EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, Quals), ElementType); } return; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index b9569f589b3..21b45583e5a 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -791,8 +791,7 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr"); llvm::Value *lhs = LV.getAddress(); lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty)); - LV = LValue::MakeAddr(lhs, ValTy.getCVRQualifiers(), - CGF.getContext().getObjCGCAttrKind(ValTy)); + LV = LValue::MakeAddr(lhs, CGF.MakeQualifiers(ValTy)); } else NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec"); } else { diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index df6058303a1..b9f4f3471c9 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -112,6 +112,9 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); + Qualifiers Quals = CGF.MakeQualifiers(IvarTy); + Quals.addCVRQualifiers(CVRQualifiers); + if (Ivar->isBitField()) { // We need to compute the bit offset for the bit-field, the offset // is to the byte. Note, there is a subtle invariant here: we can @@ -124,11 +127,11 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); return LValue::MakeBitfield(V, BitOffset, BitFieldSize, IvarTy->isSignedIntegerType(), - IvarTy.getCVRQualifiers()|CVRQualifiers); + Quals.getCVRQualifiers()); } - LValue LV = LValue::MakeAddr(V, IvarTy.getCVRQualifiers()|CVRQualifiers, - CGF.CGM.getContext().getObjCGCAttrKind(IvarTy)); + + LValue LV = LValue::MakeAddr(V, Quals); return LV; } @@ -2992,21 +2995,20 @@ llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); } -static QualType::GCAttrTypes GetGCAttrTypeForType(ASTContext &Ctx, - QualType FQT) { +static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) { if (FQT.isObjCGCStrong()) - return QualType::Strong; + return Qualifiers::Strong; if (FQT.isObjCGCWeak()) - return QualType::Weak; + return Qualifiers::Weak; if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) - return QualType::Strong; + return Qualifiers::Strong; if (const PointerType *PT = FQT->getAs<PointerType>()) return GetGCAttrTypeForType(Ctx, PT->getPointeeType()); - return QualType::GCNone; + return Qualifiers::GCNone; } void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, @@ -3123,11 +3125,11 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, } // At this point, we are done with Record/Union and array there of. // For other arrays we are down to its element type. - QualType::GCAttrTypes GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); + Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType()); - if ((ForStrongLayout && GCAttr == QualType::Strong) - || (!ForStrongLayout && GCAttr == QualType::Weak)) { + if ((ForStrongLayout && GCAttr == Qualifiers::Strong) + || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { if (IsUnion) { uint64_t UnionIvarSize = FieldSize / WordSizeInBits; if (UnionIvarSize > MaxUnionIvarSize) { @@ -3140,8 +3142,8 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, FieldSize / WordSizeInBits)); } } else if ((ForStrongLayout && - (GCAttr == QualType::GCNone || GCAttr == QualType::Weak)) - || (!ForStrongLayout && GCAttr != QualType::Weak)) { + (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)) + || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) { if (IsUnion) { // FIXME: Why the asymmetry? We divide by word size in bits on other // side. diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index d9dd94d4a63..ee9dc524c6e 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -118,12 +118,6 @@ class LValue { // use getKVCRefExpr } LVType; - enum ObjCType { - None = 0, // object with no gc attribute. - Weak, // __weak object expression - Strong // __strong object expression - }; - llvm::Value *V; union { @@ -146,9 +140,8 @@ class LValue { const ObjCImplicitSetterGetterRefExpr *KVCRefExpr; }; - bool Volatile:1; - // FIXME: set but never used, what effect should it have? - bool Restrict:1; + // 'const' is unused here + Qualifiers Quals; // objective-c's ivar bool Ivar:1; @@ -163,20 +156,13 @@ class LValue { // Lvalue is a global reference of an objective-c object bool GlobalObjCRef : 1; - // objective-c's gc attributes - unsigned ObjCType : 2; - - // address space - unsigned AddressSpace; - private: - static void SetQualifiers(unsigned Qualifiers, LValue& R) { - R.Volatile = (Qualifiers&QualType::Volatile)!=0; - R.Restrict = (Qualifiers&QualType::Restrict)!=0; + void SetQualifiers(Qualifiers Quals) { + this->Quals = Quals; + // FIXME: Convenient place to set objc flags to 0. This should really be // done in a user-defined constructor instead. - R.ObjCType = None; - R.Ivar = R.ObjIsArray = R.NonGC = R.GlobalObjCRef = false; + this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; } public: @@ -187,21 +173,20 @@ public: bool isPropertyRef() const { return LVType == PropertyRef; } bool isKVCRef() const { return LVType == KVCRef; } - bool isVolatileQualified() const { return Volatile; } - bool isRestrictQualified() const { return Restrict; } - unsigned getQualifiers() const { - return (Volatile ? QualType::Volatile : 0) | - (Restrict ? QualType::Restrict : 0); + bool isVolatileQualified() const { return Quals.hasVolatile(); } + bool isRestrictQualified() const { return Quals.hasRestrict(); } + unsigned getVRQualifiers() const { + return Quals.getCVRQualifiers() & ~Qualifiers::Const; } bool isObjCIvar() const { return Ivar; } bool isObjCArray() const { return ObjIsArray; } bool isNonGC () const { return NonGC; } bool isGlobalObjCRef() const { return GlobalObjCRef; } - bool isObjCWeak() const { return ObjCType == Weak; } - bool isObjCStrong() const { return ObjCType == Strong; } + bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; } + bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; } - unsigned getAddressSpace() const { return AddressSpace; } + unsigned getAddressSpace() const { return Quals.getAddressSpace(); } static void SetObjCIvar(LValue& R, bool iValue) { R.Ivar = iValue; @@ -216,14 +201,6 @@ public: static void SetObjCNonGC(LValue& R, bool iValue) { R.NonGC = iValue; } - static void SetObjCType(QualType::GCAttrTypes GCAttrs, LValue& R) { - if (GCAttrs == QualType::Weak) - R.ObjCType = Weak; - else if (GCAttrs == QualType::Strong) - R.ObjCType = Strong; - else - R.ObjCType = None; - } // simple lvalue llvm::Value *getAddress() const { assert(isSimple()); return V; } @@ -262,48 +239,44 @@ public: return KVCRefExpr; } - static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers, - QualType::GCAttrTypes GCAttrs = QualType::GCNone, - unsigned AddressSpace = 0) { + static LValue MakeAddr(llvm::Value *V, Qualifiers Quals) { LValue R; R.LVType = Simple; R.V = V; - SetQualifiers(Qualifiers,R); - R.AddressSpace = AddressSpace; - SetObjCType(GCAttrs, R); + R.SetQualifiers(Quals); return R; } static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = VectorElt; R.V = Vec; R.VectorIdx = Idx; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = ExtVectorElt; R.V = Vec; R.VectorElts = Elts; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit, unsigned short Size, bool IsSigned, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = BitField; R.V = V; R.BitfieldData.StartBit = StartBit; R.BitfieldData.Size = Size; R.BitfieldData.IsSigned = IsSigned; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } @@ -311,20 +284,20 @@ public: // the lvalue. However, this complicates the code a bit, and I haven't figured // out how to make it go wrong yet. static LValue MakePropertyRef(const ObjCPropertyRefExpr *E, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = PropertyRef; R.PropertyRefExpr = E; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } static LValue MakeKVCRef(const ObjCImplicitSetterGetterRefExpr *E, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = KVCRef; R.KVCRefExpr = E; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } }; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 651dc951774..6b6b1494e49 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -496,6 +496,12 @@ public: // Helpers //===--------------------------------------------------------------------===// + Qualifiers MakeQualifiers(QualType T) { + Qualifiers Quals = T.getQualifiers(); + Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T)); + return Quals; + } + /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty, diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 6826122ad98..87b3d1144f4 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -267,7 +267,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case Type::VariableArray: { const VariableArrayType &A = cast<VariableArrayType>(Ty); - assert(A.getIndexTypeQualifier() == 0 && + assert(A.getIndexTypeCVRQualifiers() == 0 && "FIXME: We only handle trivial array types so far!"); // VLAs resolve to the innermost element type; this matches // the return of alloca, and there isn't any obviously better choice. @@ -275,7 +275,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { } case Type::IncompleteArray: { const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty); - assert(A.getIndexTypeQualifier() == 0 && + assert(A.getIndexTypeCVRQualifiers() == 0 && "FIXME: We only handle trivial array types so far!"); // int X[] -> [0 x int] return llvm::ArrayType::get(ConvertTypeForMemRecursive(A.getElementType()), 0); @@ -312,10 +312,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { return GetFunctionType(getFunctionInfo(FNPT), true); } - case Type::ExtQual: - return - ConvertTypeRecursive(QualType(cast<ExtQualType>(Ty).getBaseType(), 0)); - case Type::ObjCInterface: { // Objective-C interfaces are always opaque (outside of the // runtime, which can do whatever it likes); we never refine diff --git a/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp index 878f13d516d..83dc0e64dcf 100644 --- a/clang/lib/CodeGen/Mangle.cpp +++ b/clang/lib/CodeGen/Mangle.cpp @@ -84,7 +84,7 @@ namespace { void manglePrefix(const DeclContext *DC); void mangleTemplatePrefix(const NamedDecl *ND); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); - void mangleCVQualifiers(unsigned Quals); + void mangleQualifiers(Qualifiers Quals); void mangleType(QualType T); // Declare manglers for every type class. @@ -459,7 +459,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND) { // FIXME: no class template support Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) - mangleCVQualifiers(Method->getTypeQualifiers()); + mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers())); // Check if we have a template. const TemplateArgumentList *TemplateArgs = 0; @@ -637,14 +637,16 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { } } -void CXXNameMangler::mangleCVQualifiers(unsigned Quals) { +void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const - if (Quals & QualType::Restrict) + if (Quals.hasRestrict()) Out << 'r'; - if (Quals & QualType::Volatile) + if (Quals.hasVolatile()) Out << 'V'; - if (Quals & QualType::Const) + if (Quals.hasConst()) Out << 'K'; + + // FIXME: For now, just drop all extension qualifiers on the floor. } void CXXNameMangler::mangleType(QualType T) { @@ -655,10 +657,10 @@ void CXXNameMangler::mangleType(QualType T) { if (IsSubstitutable && mangleSubstitution(T)) return; - if (unsigned CVRQualifiers = T.getCVRQualifiers()) { - // <type> ::= <CV-qualifiers> <type> - mangleCVQualifiers(CVRQualifiers); - + if (Qualifiers Quals = T.getQualifiers()) { + mangleQualifiers(Quals); + // Recurse: even if the qualified type isn't yet substitutable, + // the unqualified type might be. mangleType(T.getUnqualifiedType()); } else { switch (T->getTypeClass()) { @@ -669,7 +671,7 @@ void CXXNameMangler::mangleType(QualType T) { return; #define TYPE(CLASS, PARENT) \ case Type::CLASS: \ - mangleType(static_cast<CLASS##Type*>(T.getTypePtr())); \ + mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \ break; #include "clang/AST/TypeNodes.def" } @@ -830,7 +832,7 @@ void CXXNameMangler::mangleType(const MemberPointerType *T) { mangleType(QualType(T->getClass(), 0)); QualType PointeeType = T->getPointeeType(); if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) { - mangleCVQualifiers(FPT->getTypeQuals()); + mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals())); mangleType(FPT); } else mangleType(PointeeType); @@ -912,11 +914,6 @@ void CXXNameMangler::mangleType(const TypenameType *T) { assert(false && "can't mangle dependent typenames yet"); } -// FIXME: For now, just drop all extension qualifiers on the floor. -void CXXNameMangler::mangleType(const ExtQualType *T) { - mangleType(QualType(T->getBaseType(), 0)); -} - void CXXNameMangler::mangleExpression(const Expr *E) { // <expression> ::= <unary operator-name> <expression> // ::= <binary operator-name> <expression> <expression> diff --git a/clang/lib/Frontend/DocumentXML.cpp b/clang/lib/Frontend/DocumentXML.cpp index a6af2f8ecfa..d92d4cb7b8d 100644 --- a/clang/lib/Frontend/DocumentXML.cpp +++ b/clang/lib/Frontend/DocumentXML.cpp @@ -135,7 +135,7 @@ void DocumentXML::finalize() { for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end(); i != e; ++i) { - if (i->first.getCVRQualifiers() != 0) { + if (i->first.hasQualifiers()) { writeTypeToXML(i->first); addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); toParent(); @@ -205,7 +205,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType) { addTypeRecursively(pType.getTypePtr()); // beautifier: a non-qualified type shall be transparent - if (pType.getCVRQualifiers() == 0) + if (!pType.hasQualifiers()) { Types[pType] = BasicTypes[pType.getTypePtr()]; } diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index c493e39776b..73c0b8d9911 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -1764,18 +1764,11 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { unsigned Code = Stream.ReadCode(); switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) { case pch::TYPE_EXT_QUAL: { - assert(Record.size() == 3 && + assert(Record.size() == 2 && "Incorrect encoding of extended qualifier type"); QualType Base = GetType(Record[0]); - QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1]; - unsigned AddressSpace = Record[2]; - - QualType T = Base; - if (GCAttr != QualType::GCNone) - T = Context->getObjCGCQualType(T, GCAttr); - if (AddressSpace) - T = Context->getAddrSpaceQualType(T, AddressSpace); - return T; + Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]); + return Context->getQualifiedType(Base, Quals); } case pch::TYPE_FIXED_WIDTH_INT: { @@ -1984,8 +1977,8 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { QualType PCHReader::GetType(pch::TypeID ID) { - unsigned Quals = ID & 0x07; - unsigned Index = ID >> 3; + unsigned FastQuals = ID & Qualifiers::FastMask; + unsigned Index = ID >> Qualifiers::FastWidth; if (Index < pch::NUM_PREDEF_TYPE_IDS) { QualType T; @@ -2026,15 +2019,15 @@ QualType PCHReader::GetType(pch::TypeID ID) { } assert(!T.isNull() && "Unknown predefined type"); - return T.getQualifiedType(Quals); + return T.withFastQualifiers(FastQuals); } Index -= pch::NUM_PREDEF_TYPE_IDS; //assert(Index < TypesLoaded.size() && "Type index out-of-range"); - if (!TypesLoaded[Index]) - TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr(); + if (TypesLoaded[Index].isNull()) + TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]); - return QualType(TypesLoaded[Index], Quals); + return TypesLoaded[Index].withFastQualifiers(FastQuals); } Decl *PCHReader::GetDecl(pch::DeclID ID) { @@ -2155,7 +2148,7 @@ void PCHReader::PrintStats() { unsigned NumTypesLoaded = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(), - (Type *)0); + QualType()); unsigned NumDeclsLoaded = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(), (Decl *)0); diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index 531c6f78184..8ef846f7672 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -64,13 +64,6 @@ namespace { }; } -void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) { - Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record); - Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values - Record.push_back(T->getAddressSpace()); - Code = pch::TYPE_EXT_QUAL; -} - void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) { assert(false && "Built-in types are never serialized"); } @@ -115,7 +108,7 @@ void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) { void PCHTypeWriter::VisitArrayType(const ArrayType *T) { Writer.AddTypeRef(T->getElementType(), Record); Record.push_back(T->getSizeModifier()); // FIXME: stable values - Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values + Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values } void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { @@ -1087,7 +1080,7 @@ void PCHWriter::WriteComments(ASTContext &Context) { //===----------------------------------------------------------------------===// /// \brief Write the representation of a type to the PCH stream. -void PCHWriter::WriteType(const Type *T) { +void PCHWriter::WriteType(QualType T) { pch::TypeID &ID = TypeIDs[T]; if (ID == 0) // we haven't seen this type before. ID = NextTypeID++; @@ -1104,22 +1097,30 @@ void PCHWriter::WriteType(const Type *T) { // Emit the type's representation. PCHTypeWriter W(*this, Record); - switch (T->getTypeClass()) { - // For all of the concrete, non-dependent types, call the - // appropriate visitor function. + + if (T.hasNonFastQualifiers()) { + Qualifiers Qs = T.getQualifiers(); + AddTypeRef(T.getUnqualifiedType(), Record); + Record.push_back(Qs.getAsOpaqueValue()); + W.Code = pch::TYPE_EXT_QUAL; + } else { + switch (T->getTypeClass()) { + // For all of the concrete, non-dependent types, call the + // appropriate visitor function. #define TYPE(Class, Base) \ - case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break; + case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break; #define ABSTRACT_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" - // For all of the dependent type nodes (which only occur in C++ - // templates), produce an error. + // For all of the dependent type nodes (which only occur in C++ + // templates), produce an error. #define TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" - assert(false && "Cannot serialize dependent type nodes"); - break; + assert(false && "Cannot serialize dependent type nodes"); + break; + } } // Emit the serialized record. @@ -1136,9 +1137,8 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) { // Emit all of the types that need to be emitted (so far). while (!TypesToEmit.empty()) { - const Type *T = TypesToEmit.front(); + QualType T = TypesToEmit.front(); TypesToEmit.pop(); - assert(!isa<BuiltinType>(T) && "Built-in types are not serialized"); WriteType(T); } @@ -1975,6 +1975,26 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { return; } + unsigned FastQuals = T.getFastQualifiers(); + T.removeFastQualifiers(); + + if (T.hasNonFastQualifiers()) { + pch::TypeID &ID = TypeIDs[T]; + if (ID == 0) { + // We haven't seen these qualifiers applied to this type before. + // Assign it a new ID. This is the only time we enqueue a + // qualified type, and it has no CV qualifiers. + ID = NextTypeID++; + TypesToEmit.push(T); + } + + // Encode the type qualifiers in the type reference. + Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); + return; + } + + assert(!T.hasQualifiers()); + if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) { pch::TypeID ID = 0; switch (BT->getKind()) { @@ -2010,20 +2030,20 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { break; } - Record.push_back((ID << 3) | T.getCVRQualifiers()); + Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); return; } - pch::TypeID &ID = TypeIDs[T.getTypePtr()]; + pch::TypeID &ID = TypeIDs[T]; if (ID == 0) { // We haven't seen this type before. Assign it a new ID and put it - // into the queu of types to emit. + // into the queue of types to emit. ID = NextTypeID++; - TypesToEmit.push(T.getTypePtr()); + TypesToEmit.push(T); } // Encode the type qualifiers in the type reference. - Record.push_back((ID << 3) | T.getCVRQualifiers()); + Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); } void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) { diff --git a/clang/lib/Frontend/RewriteObjC.cpp b/clang/lib/Frontend/RewriteObjC.cpp index 57b1fc31a84..55ab78e638b 100644 --- a/clang/lib/Frontend/RewriteObjC.cpp +++ b/clang/lib/Frontend/RewriteObjC.cpp @@ -1937,8 +1937,7 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { void RewriteObjC::SynthSelGetUidFunctionDecl() { IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); llvm::SmallVector<QualType, 16> ArgTys; - ArgTys.push_back(Context->getPointerType( - Context->CharTy.getQualifiedType(QualType::Const))); + ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/, 0); @@ -2084,8 +2083,7 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { void RewriteObjC::SynthGetClassFunctionDecl() { IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); llvm::SmallVector<QualType, 16> ArgTys; - ArgTys.push_back(Context->getPointerType( - Context->CharTy.getQualifiedType(QualType::Const))); + ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/, 0); @@ -2099,8 +2097,7 @@ void RewriteObjC::SynthGetClassFunctionDecl() { void RewriteObjC::SynthGetMetaClassFunctionDecl() { IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); llvm::SmallVector<QualType, 16> ArgTys; - ArgTys.push_back(Context->getPointerType( - Context->CharTy.getQualifiedType(QualType::Const))); + ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/, 0); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 63b252a536a..81f7283e23f 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -44,9 +44,7 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val, // If this is a sugared type (like a typedef, typeof, etc), then unwrap one // level of the sugar so that the type is more obvious to the user. - QualType DesugaredTy = Ty->getDesugaredType(true); - DesugaredTy.setCVRQualifiers(DesugaredTy.getCVRQualifiers() | - Ty.getCVRQualifiers()); + QualType DesugaredTy = Ty.getDesugaredType(true); if (Ty != DesugaredTy && // If the desugared type is a vector type, we don't want to expand it, diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index d1a8b6dedfe..ab085fb8ee7 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -186,12 +186,12 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { "Destination type is not pointer or pointer to member."); QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType; - llvm::SmallVector<unsigned, 8> cv1, cv2; + llvm::SmallVector<Qualifiers, 8> cv1, cv2; // Find the qualifications. while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { - cv1.push_back(UnwrappedSrcType.getCVRQualifiers()); - cv2.push_back(UnwrappedDestType.getCVRQualifiers()); + cv1.push_back(UnwrappedSrcType.getQualifiers()); + cv2.push_back(UnwrappedDestType.getQualifiers()); } assert(cv1.size() > 0 && "Must have at least one pointer level."); @@ -199,13 +199,14 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { // unwrapping, of course). QualType SrcConstruct = Self.Context.VoidTy; QualType DestConstruct = Self.Context.VoidTy; - for (llvm::SmallVector<unsigned, 8>::reverse_iterator i1 = cv1.rbegin(), - i2 = cv2.rbegin(); + ASTContext &Context = Self.Context; + for (llvm::SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(), + i2 = cv2.rbegin(); i1 != cv1.rend(); ++i1, ++i2) { - SrcConstruct = Self.Context.getPointerType( - SrcConstruct.getQualifiedType(*i1)); - DestConstruct = Self.Context.getPointerType( - DestConstruct.getQualifiedType(*i2)); + SrcConstruct + = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1)); + DestConstruct + = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2)); } // Test if they're compatible. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 084b2efcf36..ec27814870c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1814,14 +1814,16 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, // constant expression folding, like struct {char x[(int)(char*)2];} SizeIsNegative = false; - if (const PointerType* PTy = dyn_cast<PointerType>(T)) { + QualifierCollector Qs; + const Type *Ty = Qs.strip(T); + + if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) { QualType Pointee = PTy->getPointeeType(); QualType FixedType = TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative); if (FixedType.isNull()) return FixedType; FixedType = Context.getPointerType(FixedType); - FixedType.setCVRQualifiers(T.getCVRQualifiers()); - return FixedType; + return Qs.apply(FixedType); } const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T); @@ -2968,7 +2970,7 @@ void Sema::CheckMain(FunctionDecl* FD) { // char const * const * // char * const * - QualifierSet qs; + QualifierCollector qs; const PointerType* PT; if ((PT = qs.strip(AT)->getAs<PointerType>()) && (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) && diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 5cced5a92e9..390a8048db2 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2046,13 +2046,13 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; if (FTI.TypeQuals != 0) { - if (FTI.TypeQuals & QualType::Const) + if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "const" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Volatile) + if (FTI.TypeQuals & Qualifiers::Volatile) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "volatile" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Restrict) + if (FTI.TypeQuals & Qualifiers::Restrict) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "restrict" << SourceRange(D.getIdentifierLoc()); } @@ -2159,13 +2159,13 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; if (FTI.TypeQuals != 0 && !D.isInvalidType()) { - if (FTI.TypeQuals & QualType::Const) + if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "const" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Volatile) + if (FTI.TypeQuals & Qualifiers::Volatile) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "volatile" << SourceRange(D.getIdentifierLoc()); - if (FTI.TypeQuals & QualType::Restrict) + if (FTI.TypeQuals & Qualifiers::Restrict) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "restrict" << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); @@ -2844,10 +2844,8 @@ Sema::getAssignOperatorMethod(ParmVarDecl *ParmDecl, // If class's assignment operator argument is const/volatile qualified, // look for operator = (const/volatile B&). Otherwise, look for // operator = (B&). - if (ParmDecl->getType().isConstQualified()) - RHSType.addConst(); - if (ParmDecl->getType().isVolatileQualified()) - RHSType.addVolatile(); + RHSType = Context.getCVRQualifiedType(RHSType, + ParmDecl->getType().getCVRQualifiers()); ExprOwningPtr<Expr> LHS(this, new (Context) DeclRefExpr(ParmDecl, LHSType, SourceLocation())); @@ -3575,7 +3573,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, // -- Otherwise, the reference shall be to a non-volatile const // type (i.e., cv1 shall be const), or the reference shall be an // rvalue reference and the initializer expression shall be an rvalue. - if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) { + if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) { if (!ICS) Diag(DeclLoc, diag::err_not_reference_to_const_init) << T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value") diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 9695814860c..5bc8818dbad 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -566,7 +566,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, // of the anonymous union objects and, eventually, the field we // found via name lookup. bool BaseObjectIsPointer = false; - unsigned ExtraQuals = 0; + Qualifiers BaseQuals; if (BaseObject) { // BaseObject is an anonymous struct/union variable (and is, // therefore, not part of another non-anonymous record). @@ -574,8 +574,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, MarkDeclarationReferenced(Loc, BaseObject); BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(), SourceLocation()); - ExtraQuals - = Context.getCanonicalType(BaseObject->getType()).getCVRQualifiers(); + BaseQuals + = Context.getCanonicalType(BaseObject->getType()).getQualifiers(); } else if (BaseObjectExpr) { // The caller provided the base object expression. Determine // whether its a pointer and whether it adds any qualifiers to the @@ -585,7 +585,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, BaseObjectIsPointer = true; ObjectType = ObjectPtr->getPointeeType(); } - ExtraQuals = Context.getCanonicalType(ObjectType).getCVRQualifiers(); + BaseQuals + = Context.getCanonicalType(ObjectType).getQualifiers(); } else { // We've found a member of an anonymous struct/union that is // inside a non-anonymous struct/union, so in a well-formed @@ -608,7 +609,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method) << Field->getDeclName()); } - ExtraQuals = MD->getTypeQualifiers(); + BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers()); } if (!BaseObjectExpr) @@ -619,24 +620,35 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, // Build the implicit member references to the field of the // anonymous struct/union. Expr *Result = BaseObjectExpr; - unsigned BaseAddrSpace = BaseObjectExpr->getType().getAddressSpace(); + Qualifiers ResultQuals = BaseQuals; for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator FI = AnonFields.rbegin(), FIEnd = AnonFields.rend(); FI != FIEnd; ++FI) { QualType MemberType = (*FI)->getType(); - if (!(*FI)->isMutable()) { - unsigned combinedQualifiers - = MemberType.getCVRQualifiers() | ExtraQuals; - MemberType = MemberType.getQualifiedType(combinedQualifiers); - } - if (BaseAddrSpace != MemberType.getAddressSpace()) - MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace); + Qualifiers MemberTypeQuals = + Context.getCanonicalType(MemberType).getQualifiers(); + + // CVR attributes from the base are picked up by members, + // except that 'mutable' members don't pick up 'const'. + if ((*FI)->isMutable()) + ResultQuals.removeConst(); + + // GC attributes are never picked up by members. + ResultQuals.removeObjCGCAttr(); + + // TR 18037 does not allow fields to be declared with address spaces. + assert(!MemberTypeQuals.hasAddressSpace()); + + Qualifiers NewQuals = ResultQuals + MemberTypeQuals; + if (NewQuals != MemberTypeQuals) + MemberType = Context.getQualifiedType(MemberType, NewQuals); + MarkDeclarationReferenced(Loc, *FI); // FIXME: Might this end up being a qualified name? Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); BaseObjectIsPointer = false; - ExtraQuals = Context.getCanonicalType(MemberType).getCVRQualifiers(); + ResultQuals = NewQuals; } return Owned(Result); @@ -948,11 +960,10 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>()) MemberType = RefType->getPointeeType(); - else if (!FD->isMutable()) { - unsigned combinedQualifiers - = MemberType.getCVRQualifiers() | MD->getTypeQualifiers(); - MemberType = MemberType.getQualifiedType(combinedQualifiers); - } + else if (!FD->isMutable()) + MemberType + = Context.getQualifiedType(MemberType, + Qualifiers::fromCVRMask(MD->getTypeQualifiers())); } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { if (!Method->isStatic()) { Ctx = Method->getParent(); @@ -1135,7 +1146,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, // - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) { - if (Dcl->getType().getCVRQualifiers() == QualType::Const && + if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const && Dcl->getInit()) { ValueDependent = Dcl->getInit()->isValueDependent(); } @@ -1174,7 +1185,7 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, PredefinedExpr::ComputeName(Context, IT, currentDecl).length(); llvm::APInt LengthI(32, Length + 1); - ResTy = Context.CharTy.getQualifiedType(QualType::Const); + ResTy = Context.CharTy.withConst(); ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); } return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); @@ -2235,14 +2246,16 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) MemberType = Ref->getPointeeType(); else { - unsigned BaseAddrSpace = BaseType.getAddressSpace(); - unsigned combinedQualifiers = - MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers(); - if (FD->isMutable()) - combinedQualifiers &= ~QualType::Const; - MemberType = MemberType.getQualifiedType(combinedQualifiers); - if (BaseAddrSpace != MemberType.getAddressSpace()) - MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace); + Qualifiers BaseQuals = BaseType.getQualifiers(); + BaseQuals.removeObjCGCAttr(); + if (FD->isMutable()) BaseQuals.removeConst(); + + Qualifiers MemberQuals + = Context.getCanonicalType(MemberType).getQualifiers(); + + Qualifiers Combined = BaseQuals + MemberQuals; + if (Combined != MemberQuals) + MemberType = Context.getQualifiedType(MemberType, Combined); } MarkDeclarationReferenced(MemberLoc, FD); @@ -3510,7 +3523,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType(); QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); - QualType destPointee = lhptee.getQualifiedType(rhptee.getCVRQualifiers()); + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(LHS, destType); // add qualifiers if necessary ImpCastExprToType(RHS, destType); // promote to void* @@ -3519,7 +3533,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType(); - QualType destPointee = rhptee.getQualifiedType(lhptee.getCVRQualifiers()); + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(RHS, destType); // add qualifiers if necessary ImpCastExprToType(LHS, destType); // promote to void* @@ -3534,14 +3549,16 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // ignore qualifiers on void (C99 6.5.15p3, clause 6) if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) { // Figure out necessary qualifiers (C99 6.5.15p6) - QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers()); + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(LHS, destType); // add qualifiers if necessary ImpCastExprToType(RHS, destType); // promote to void* return destType; } if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { - QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers()); + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(LHS, destType); // add qualifiers if necessary ImpCastExprToType(RHS, destType); // promote to void* diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index ff6ae50533a..e93929e94b9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -972,7 +972,7 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { = ToPtrType->getPointeeType()->getAs<BuiltinType>()) { // This conversion is considered only when there is an // explicit appropriate pointer target type (C++ 4.2p2). - if (ToPtrType->getPointeeType().getCVRQualifiers() == 0 && + if (!ToPtrType->getPointeeType().hasQualifiers() && ((StrLit->isWide() && ToPointeeType->isWideCharType()) || (!StrLit->isWide() && (ToPointeeType->getKind() == BuiltinType::Char_U || @@ -1316,10 +1316,7 @@ QualType Sema::CheckPointerToMemberOperands( // argument. // We probably need a "MemberFunctionClosureType" or something like that. QualType Result = MemPtr->getPointeeType(); - if (LType.isConstQualified()) - Result.addConst(); - if (LType.isVolatileQualified()) - Result.addVolatile(); + Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers()); return Result; } @@ -1662,14 +1659,33 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (LMemPtr && RMemPtr) { QualType LPointee = LMemPtr->getPointeeType(); QualType RPointee = RMemPtr->getPointeeType(); + + QualifierCollector LPQuals, RPQuals; + const Type *LPCan = LPQuals.strip(Context.getCanonicalType(LPointee)); + const Type *RPCan = RPQuals.strip(Context.getCanonicalType(RPointee)); + // First, we check that the unqualified pointee type is the same. If it's // not, there's no conversion that will unify the two pointers. - if (Context.getCanonicalType(LPointee).getUnqualifiedType() == - Context.getCanonicalType(RPointee).getUnqualifiedType()) { - // Second, we take the greater of the two cv qualifications. If neither + if (LPCan == RPCan) { + + // Second, we take the greater of the two qualifications. If neither // is greater than the other, the conversion is not possible. - unsigned Q = LPointee.getCVRQualifiers() | RPointee.getCVRQualifiers(); - if (Q == LPointee.getCVRQualifiers() || Q == RPointee.getCVRQualifiers()){ + + Qualifiers MergedQuals = LPQuals + RPQuals; + + bool CompatibleQuals = true; + if (MergedQuals.getCVRQualifiers() != LPQuals.getCVRQualifiers() && + MergedQuals.getCVRQualifiers() != RPQuals.getCVRQualifiers()) + CompatibleQuals = false; + else if (LPQuals.getAddressSpace() != RPQuals.getAddressSpace()) + // FIXME: + // C99 6.5.15 as modified by TR 18037: + // If the second and third operands are pointers into different + // address spaces, the address spaces must overlap. + CompatibleQuals = false; + // FIXME: GC qualifiers? + + if (CompatibleQuals) { // Third, we check if either of the container classes is derived from // the other. QualType LContainer(LMemPtr->getClass(), 0); @@ -1687,8 +1703,9 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // The type 'Q Pointee (MoreDerived::*)' is the common type. // We don't use ImpCastExprToType here because this could still fail // for ambiguous or inaccessible conversions. - QualType Common = Context.getMemberPointerType( - LPointee.getQualifiedType(Q), MoreDerived.getTypePtr()); + LPointee = Context.getQualifiedType(LPointee, MergedQuals); + QualType Common + = Context.getMemberPointerType(LPointee, MoreDerived.getTypePtr()); if (PerformImplicitConversion(LHS, Common, "converting")) return QualType(); if (PerformImplicitConversion(RHS, Common, "converting")) @@ -1750,6 +1767,7 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { // What we do here is, we build the two possible composite types, and try the // conversions in both directions. If only one works, or if the two composite // types are the same, we have succeeded. + // FIXME: extended qualifiers? llvm::SmallVector<unsigned, 4> QualifierUnion; llvm::SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass; QualType Composite1 = T1, Composite2 = T2; @@ -1790,16 +1808,21 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) { I = QualifierUnion.begin(), E = QualifierUnion.end(); I != E; (void)++I, ++MOC) { + Qualifiers Quals = Qualifiers::fromCVRMask(*I); if (MOC->first && MOC->second) { // Rebuild member pointer type - Composite1 = Context.getMemberPointerType(Composite1.getQualifiedType(*I), - MOC->first); - Composite2 = Context.getMemberPointerType(Composite2.getQualifiedType(*I), - MOC->second); + Composite1 = Context.getMemberPointerType( + Context.getQualifiedType(Composite1, Quals), + MOC->first); + Composite2 = Context.getMemberPointerType( + Context.getQualifiedType(Composite2, Quals), + MOC->second); } else { // Rebuild pointer type - Composite1 = Context.getPointerType(Composite1.getQualifiedType(*I)); - Composite2 = Context.getPointerType(Composite2.getQualifiedType(*I)); + Composite1 + = Context.getPointerType(Context.getQualifiedType(Composite1, Quals)); + Composite2 + = Context.getPointerType(Context.getQualifiedType(Composite2, Quals)); } } diff --git a/clang/lib/Sema/SemaInherit.cpp b/clang/lib/Sema/SemaInherit.cpp index 01e856c1d6d..8f932ac7d15 100644 --- a/clang/lib/Sema/SemaInherit.cpp +++ b/clang/lib/Sema/SemaInherit.cpp @@ -59,7 +59,7 @@ BasePaths::decl_iterator BasePaths::found_decls_end() { /// an unqualified, canonical class type. bool BasePaths::isAmbiguous(QualType BaseType) { assert(BaseType->isCanonical() && "Base type must be the canonical type"); - assert(BaseType.getCVRQualifiers() == 0 && "Base type must be unqualified"); + assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified"); std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; return Subobjects.second + (Subobjects.first? 1 : 0) > 1; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 4232d54f4b6..edb854ccdd4 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -856,12 +856,12 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, ASTContext &Context) { QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType()); QualType CanonToPointee = Context.getCanonicalType(ToPointee); - unsigned Quals = CanonFromPointee.getCVRQualifiers(); + Qualifiers Quals = CanonFromPointee.getQualifiers(); // Exact qualifier match -> return the pointer type we're converting to. - if (CanonToPointee.getCVRQualifiers() == Quals) { + if (CanonToPointee.getQualifiers() == Quals) { // ToType is exactly what we need. Return it. - if (ToType.getTypePtr()) + if (!ToType.isNull()) return ToType; // Build a pointer to ToPointee. It has the right qualifiers @@ -870,7 +870,8 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, } // Just build a canonical type that has the right qualifiers. - return Context.getPointerType(CanonToPointee.getQualifiedType(Quals)); + return Context.getPointerType( + Context.getQualifiedType(CanonToPointee.getUnqualifiedType(), Quals)); } static bool isNullPointerConstantForConversion(Expr *Expr, @@ -2022,8 +2023,8 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, ImplicitConversionSequence Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) { QualType ClassType = Context.getTypeDeclType(Method->getParent()); - unsigned MethodQuals = Method->getTypeQualifiers(); - QualType ImplicitParamType = ClassType.getQualifiedType(MethodQuals); + QualType ImplicitParamType + = Context.getCVRQualifiedType(ClassType, Method->getTypeQualifiers()); // Set up the conversion sequence as a "bad" conversion, to allow us // to exit early. @@ -2831,27 +2832,27 @@ public: /// restrict *", and "int const volatile restrict *" to the set of /// pointer types. Returns true if the add of @p Ty itself succeeded, /// false otherwise. +/// +/// FIXME: what to do about extended qualifiers? bool BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) { + // Insert this type. if (!PointerTypes.insert(Ty)) return false; - if (const PointerType *PointerTy = Ty->getAs<PointerType>()) { - QualType PointeeTy = PointerTy->getPointeeType(); - // FIXME: Optimize this so that we don't keep trying to add the same types. - - // FIXME: Do we have to add CVR qualifiers at *all* levels to deal with all - // pointer conversions that don't cast away constness? - if (!PointeeTy.isConstQualified()) - AddPointerWithMoreQualifiedTypeVariants - (Context.getPointerType(PointeeTy.withConst())); - if (!PointeeTy.isVolatileQualified()) - AddPointerWithMoreQualifiedTypeVariants - (Context.getPointerType(PointeeTy.withVolatile())); - if (!PointeeTy.isRestrictQualified()) - AddPointerWithMoreQualifiedTypeVariants - (Context.getPointerType(PointeeTy.withRestrict())); + const PointerType *PointerTy = Ty->getAs<PointerType>(); + assert(PointerTy && "type was not a pointer type!"); + + QualType PointeeTy = PointerTy->getPointeeType(); + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); + + // Iterate through all strict supersets of BaseCVR. + for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { + if ((CVR | BaseCVR) != CVR) continue; + + QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); + PointerTypes.insert(Context.getPointerType(QPointeeTy)); } return true; @@ -2864,6 +2865,8 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) { /// restrict *", and "int const volatile restrict *" to the set of /// pointer types. Returns true if the add of @p Ty itself succeeded, /// false otherwise. +/// +/// FIXME: what to do about extended qualifiers? bool BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( QualType Ty) { @@ -2871,20 +2874,20 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( if (!MemberPointerTypes.insert(Ty)) return false; - if (const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>()) { - QualType PointeeTy = PointerTy->getPointeeType(); - const Type *ClassTy = PointerTy->getClass(); - // FIXME: Optimize this so that we don't keep trying to add the same types. - - if (!PointeeTy.isConstQualified()) - AddMemberPointerWithMoreQualifiedTypeVariants - (Context.getMemberPointerType(PointeeTy.withConst(), ClassTy)); - if (!PointeeTy.isVolatileQualified()) - AddMemberPointerWithMoreQualifiedTypeVariants - (Context.getMemberPointerType(PointeeTy.withVolatile(), ClassTy)); - if (!PointeeTy.isRestrictQualified()) - AddMemberPointerWithMoreQualifiedTypeVariants - (Context.getMemberPointerType(PointeeTy.withRestrict(), ClassTy)); + const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>(); + assert(PointerTy && "type was not a member pointer type!"); + + QualType PointeeTy = PointerTy->getPointeeType(); + const Type *ClassTy = PointerTy->getClass(); + + // Iterate through all strict supersets of the pointee type's CVR + // qualifiers. + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); + for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { + if ((CVR | BaseCVR) != CVR) continue; + + QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); + MemberPointerTypes.insert(Context.getMemberPointerType(QPointeeTy, ClassTy)); } return true; @@ -2924,7 +2927,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, // Add 'cv void*' to our set of types. if (!Ty->isVoidType()) { QualType QualVoid - = Context.VoidTy.getQualifiedType(PointeeTy.getCVRQualifiers()); + = Context.getCVRQualifiedType(Context.VoidTy, + PointeeTy.getCVRQualifiers()); AddPointerWithMoreQualifiedTypeVariants(Context.getPointerType(QualVoid)); } @@ -2936,7 +2940,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) { QualType BaseTy = Context.getCanonicalType(Base->getType()); - BaseTy = BaseTy.getQualifiedType(PointeeTy.getCVRQualifiers()); + BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(), + PointeeTy.getCVRQualifiers()); // Add the pointer type, recursively, so that we get all of // the indirect base classes, too. @@ -2997,7 +3002,8 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, if (!S.Context.getCanonicalType(T).isVolatileQualified()) { // volatile T& operator=(volatile T&, T) - ParamTypes[0] = S.Context.getLValueReferenceType(T.withVolatile()); + ParamTypes[0] + = S.Context.getLValueReferenceType(S.Context.getVolatileType(T)); ParamTypes[1] = T; S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, /*IsAssignmentOperator=*/true); @@ -3119,7 +3125,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet); // Volatile version - ParamTypes[0] = Context.getLValueReferenceType(ArithTy.withVolatile()); + ParamTypes[0] + = Context.getLValueReferenceType(Context.getVolatileType(ArithTy)); if (NumArgs == 1) AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); else @@ -3154,7 +3161,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) { // With volatile - ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile()); + ParamTypes[0] + = Context.getLValueReferenceType(Context.getVolatileType(*Ptr)); if (NumArgs == 1) AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); else @@ -3465,7 +3473,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) { // volatile version - ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile()); + ParamTypes[0] + = Context.getLValueReferenceType(Context.getVolatileType(*Ptr)); AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, /*IsAssigmentOperator=*/Op == OO_Equal); } @@ -3498,7 +3507,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, /*IsAssigmentOperator=*/Op == OO_Equal); // Add this built-in operator as a candidate (VQ is 'volatile'). - ParamTypes[0] = ArithmeticTypes[Left].withVolatile(); + ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]); ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, /*IsAssigmentOperator=*/Op == OO_Equal); @@ -3536,7 +3545,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, // Add this built-in operator as a candidate (VQ is 'volatile'). ParamTypes[0] = ArithmeticTypes[Left]; - ParamTypes[0].addVolatile(); + ParamTypes[0] = Context.getVolatileType(ParamTypes[0]); ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 4ffca8c8f5c..a73c261d97f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1295,22 +1295,19 @@ public: TypeWithHandler(const QualType &type, CXXCatchStmt *statement) : t(type), stmt(statement) {} + // An arbitrary order is fine as long as it places identical + // types next to each other. bool operator<(const TypeWithHandler &y) const { - if (t.getTypePtr() < y.t.getTypePtr()) + if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr()) return true; - else if (t.getTypePtr() > y.t.getTypePtr()) - return false; - else if (t.getCVRQualifiers() < y.t.getCVRQualifiers()) - return true; - else if (t.getCVRQualifiers() < y.t.getCVRQualifiers()) + if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr()) return false; else return getTypeSpecStartLoc() < y.getTypeSpecStartLoc(); } bool operator==(const TypeWithHandler& other) const { - return t.getTypePtr() == other.t.getTypePtr() - && t.getCVRQualifiers() == other.t.getCVRQualifiers(); + return t == other.t; } QualType getQualType() const { return t; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 8d4999bf6d6..2ad1a61b504 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -300,28 +300,30 @@ DeduceTemplateArguments(ASTContext &Context, } /// \brief Returns a completely-unqualified array type, capturing the -/// qualifiers in CVRQuals. +/// qualifiers in Quals. /// /// \param Context the AST context in which the array type was built. /// /// \param T a canonical type that may be an array type. /// -/// \param CVRQuals will receive the set of const/volatile/restrict qualifiers -/// that were applied to the element type of the array. +/// \param Quals will receive the full set of qualifiers that were +/// applied to the element type of the array. /// /// \returns if \p T is an array type, the completely unqualified array type /// that corresponds to T. Otherwise, returns T. static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T, - unsigned &CVRQuals) { + Qualifiers &Quals) { assert(T->isCanonical() && "Only operates on canonical types"); if (!isa<ArrayType>(T)) { - CVRQuals = T.getCVRQualifiers(); + Quals = T.getQualifiers(); return T.getUnqualifiedType(); } + assert(!T.hasQualifiers() && "canonical array type has qualifiers!"); + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) { QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(), - CVRQuals); + Quals); if (Elt == CAT->getElementType()) return T; @@ -331,7 +333,7 @@ static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T, if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) { QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(), - CVRQuals); + Quals); if (Elt == IAT->getElementType()) return T; @@ -340,7 +342,7 @@ static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T, const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T); QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(), - CVRQuals); + Quals); if (Elt == DSAT->getElementType()) return T; @@ -387,9 +389,9 @@ DeduceTemplateArguments(ASTContext &Context, // referred to by the reference) can be more cv-qualified than the // transformed A. if (TDF & TDF_ParamWithReferenceType) { - unsigned ExtraQualsOnParam - = Param.getCVRQualifiers() & ~Arg.getCVRQualifiers(); - Param.setCVRQualifiers(Param.getCVRQualifiers() & ~ExtraQualsOnParam); + Qualifiers Quals = Param.getQualifiers(); + Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiers()); + Param = Context.getQualifiedType(Param.getUnqualifiedType(), Quals); } // If the parameter type is not dependent, there is nothing to deduce. @@ -418,10 +420,10 @@ DeduceTemplateArguments(ASTContext &Context, // top level, so they can be matched with the qualifiers on the parameter. // FIXME: address spaces, ObjC GC qualifiers if (isa<ArrayType>(Arg)) { - unsigned CVRQuals = 0; - Arg = getUnqualifiedArrayType(Context, Arg, CVRQuals); - if (CVRQuals) { - Arg = Arg.getWithAdditionalQualifiers(CVRQuals); + Qualifiers Quals; + Arg = getUnqualifiedArrayType(Context, Arg, Quals); + if (Quals) { + Arg = Context.getQualifiedType(Arg, Quals); RecanonicalizeArg = true; } } @@ -437,8 +439,8 @@ DeduceTemplateArguments(ASTContext &Context, assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0"); - unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers(); - QualType DeducedType = Arg.getQualifiedType(Quals); + QualType DeducedType = Arg; + DeducedType.removeCVRQualifiers(Param.getCVRQualifiers()); if (RecanonicalizeArg) DeducedType = Context.getCanonicalType(DeducedType); @@ -2022,13 +2024,6 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, T = SemaRef.Context.getCanonicalType(T); switch (T->getTypeClass()) { - case Type::ExtQual: - MarkUsedTemplateParameters(SemaRef, - QualType(cast<ExtQualType>(T)->getBaseType(), 0), - OnlyDeduced, - Used); - break; - case Type::Pointer: MarkUsedTemplateParameters(SemaRef, cast<PointerType>(T)->getPointeeType(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 86b49d4f320..90a03972cc1 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -496,7 +496,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { PredefinedExpr::ComputeName(getSema().Context, IT, currentDecl).length(); llvm::APInt LengthI(32, Length + 1); - QualType ResTy = getSema().Context.CharTy.getQualifiedType(QualType::Const); + QualType ResTy = getSema().Context.CharTy.withConst(); ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); PredefinedExpr *PE = diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 6fee787a74e..c297694b9ff 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -312,7 +312,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, // Enforce C99 6.7.3p2: "Types other than pointer types derived from object // or incomplete types shall not be restrict-qualified." C++ also allows // restrict-qualified references. - if (TypeQuals & QualType::Restrict) { + if (TypeQuals & DeclSpec::TQ_restrict) { if (Result->isPointerType() || Result->isReferenceType()) { QualType EltTy = Result->isPointerType() ? Result->getAs<PointerType>()->getPointeeType() : @@ -324,13 +324,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, Diag(DS.getRestrictSpecLoc(), diag::err_typecheck_invalid_restrict_invalid_pointee) << EltTy << DS.getSourceRange(); - TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier. + TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier. } } else { Diag(DS.getRestrictSpecLoc(), diag::err_typecheck_invalid_restrict_not_pointer) << Result << DS.getSourceRange(); - TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier. + TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier. } } @@ -340,12 +340,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, if (Result->isFunctionType() && TypeQuals) { // Get some location to point at, either the C or V location. SourceLocation Loc; - if (TypeQuals & QualType::Const) + if (TypeQuals & DeclSpec::TQ_const) Loc = DS.getConstSpecLoc(); - else { - assert((TypeQuals & QualType::Volatile) && - "Has CV quals but not C or V?"); + else if (TypeQuals & DeclSpec::TQ_volatile) Loc = DS.getVolatileSpecLoc(); + else { + assert((TypeQuals & DeclSpec::TQ_restrict) && + "Has CVR quals but not C, V, or R?"); + Loc = DS.getRestrictSpecLoc(); } Diag(Loc, diag::warn_typecheck_function_qualifiers) << Result << DS.getSourceRange(); @@ -359,12 +361,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, // FIXME: Shouldn't we be checking SCS_typedef here? if (DS.getTypeSpecType() == DeclSpec::TST_typename && TypeQuals && Result->isReferenceType()) { - TypeQuals &= ~QualType::Const; - TypeQuals &= ~QualType::Volatile; + TypeQuals &= ~DeclSpec::TQ_const; + TypeQuals &= ~DeclSpec::TQ_volatile; } - Result = Result.getQualifiedType(TypeQuals); + Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals); + Result = Context.getQualifiedType(Result, Quals); } + return Result; } @@ -399,23 +403,25 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, return QualType(); } + Qualifiers Qs = Qualifiers::fromCVRMask(Quals); + // Enforce C99 6.7.3p2: "Types other than pointer types derived from // object or incomplete types shall not be restrict-qualified." - if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) { + if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) { Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) << T; - Quals &= ~QualType::Restrict; + Qs.removeRestrict(); } // Build the pointer type. - return Context.getPointerType(T).getQualifiedType(Quals); + return Context.getQualifiedType(Context.getPointerType(T), Qs); } /// \brief Build a reference type. /// /// \param T The type to which we'll be building a reference. /// -/// \param Quals The cvr-qualifiers to be applied to the reference type. +/// \param CVR The cvr-qualifiers to be applied to the reference type. /// /// \param Loc The location of the entity whose type involves this /// reference type or, if there is no such entity, the location of the @@ -426,8 +432,9 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, /// /// \returns A suitable reference type, if there are no /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, +QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR, SourceLocation Loc, DeclarationName Entity) { + Qualifiers Quals = Qualifiers::fromCVRMask(CVR); if (LValueRef) { if (const RValueReferenceType *R = T->getAs<RValueReferenceType>()) { // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a @@ -435,8 +442,8 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, // reference to cv TD" creates the type "lvalue reference to T". // We use the qualifiers (restrict or none) of the original reference, // not the new ones. This is consistent with GCC. - return Context.getLValueReferenceType(R->getPointeeType()). - getQualifiedType(T.getCVRQualifiers()); + QualType LVRT = Context.getLValueReferenceType(R->getPointeeType()); + return Context.getQualifiedType(LVRT, T.getQualifiers()); } } if (T->isReferenceType()) { @@ -449,7 +456,7 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, // typedef int& intref; // typedef intref& intref2; // - // Parser::ParserDeclaratorInternal diagnoses the case where + // Parser::ParseDeclaratorInternal diagnoses the case where // references are written directly; here, we handle the // collapsing of references-to-references as described in C++ // DR 106 and amended by C++ DR 540. @@ -466,10 +473,10 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, // Enforce C99 6.7.3p2: "Types other than pointer types derived from // object or incomplete types shall not be restrict-qualified." - if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) { + if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) { Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) << T; - Quals &= ~QualType::Restrict; + Quals.removeRestrict(); } // C++ [dcl.ref]p1: @@ -481,13 +488,13 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, // We diagnose extraneous cv-qualifiers for the non-typedef, // non-template type argument case within the parser. Here, we just // ignore any extraneous cv-qualifiers. - Quals &= ~QualType::Const; - Quals &= ~QualType::Volatile; + Quals.removeConst(); + Quals.removeVolatile(); // Handle restrict on references. if (LValueRef) - return Context.getLValueReferenceType(T).getQualifiedType(Quals); - return Context.getRValueReferenceType(T).getQualifiedType(Quals); + return Context.getQualifiedType(Context.getLValueReferenceType(T), Quals); + return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals); } /// \brief Build an array type. @@ -513,6 +520,7 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, SourceRange Brackets, DeclarationName Entity) { + SourceLocation Loc = Brackets.getBegin(); // C99 6.7.5.2p1: If the element type is an incomplete or function type, // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) @@ -706,15 +714,17 @@ QualType Sema::BuildFunctionType(QualType T, /// /// \param T the type to which the member pointer refers. /// \param Class the class type into which the member pointer points. -/// \param Quals Qualifiers applied to the member pointer type +/// \param CVR Qualifiers applied to the member pointer type /// \param Loc the location where this type begins /// \param Entity the name of the entity that will have this member pointer type /// /// \returns a member pointer type, if successful, or a NULL type if there was /// an error. QualType Sema::BuildMemberPointerType(QualType T, QualType Class, - unsigned Quals, SourceLocation Loc, + unsigned CVR, SourceLocation Loc, DeclarationName Entity) { + Qualifiers Quals = Qualifiers::fromCVRMask(CVR); + // Verify that we're not building a pointer to pointer to function with // exception specification. if (CheckDistantExceptionSpec(T)) { @@ -744,13 +754,13 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, // Enforce C99 6.7.3p2: "Types other than pointer types derived from // object or incomplete types shall not be restrict-qualified." - if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) { + if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) { Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) << T; // FIXME: If we're doing this as part of template instantiation, // we should return immediately. - Quals &= ~QualType::Restrict; + Quals.removeRestrict(); } if (!Class->isDependentType() && !Class->isRecordType()) { @@ -758,15 +768,15 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, return QualType(); } - return Context.getMemberPointerType(T, Class.getTypePtr()) - .getQualifiedType(Quals); + return Context.getQualifiedType( + Context.getMemberPointerType(T, Class.getTypePtr()), Quals); } /// \brief Build a block pointer type. /// /// \param T The type to which we'll be building a block pointer. /// -/// \param Quals The cvr-qualifiers to be applied to the block pointer type. +/// \param CVR The cvr-qualifiers to be applied to the block pointer type. /// /// \param Loc The location of the entity whose type involves this /// block pointer type or, if there is no such entity, the location of the @@ -777,15 +787,16 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, /// /// \returns A suitable block pointer type, if there are no /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildBlockPointerType(QualType T, unsigned Quals, +QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR, SourceLocation Loc, DeclarationName Entity) { - if (!T.getTypePtr()->isFunctionType()) { + if (!T->isFunctionType()) { Diag(Loc, diag::err_nonfunction_block_type); return QualType(); } - return Context.getBlockPointerType(T).getQualifiedType(Quals); + Qualifiers Quals = Qualifiers::fromCVRMask(CVR); + return Context.getQualifiedType(Context.getBlockPointerType(T), Quals); } QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) { @@ -921,8 +932,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case DeclaratorChunk::BlockPointer: if (ShouldBuildInfo) { if (SourceTy->isFunctionType()) - SourceTy = Context.getBlockPointerType(SourceTy) - .getQualifiedType(DeclType.Cls.TypeQuals); + SourceTy + = Context.getQualifiedType(Context.getBlockPointerType(SourceTy), + Qualifiers::fromCVRMask(DeclType.Cls.TypeQuals)); else // If not function type Context::getBlockPointerType asserts, // so just give up. @@ -939,8 +951,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case DeclaratorChunk::Pointer: //FIXME: Use ObjCObjectPointer for info when appropriate. if (ShouldBuildInfo) - SourceTy = Context.getPointerType(SourceTy) - .getQualifiedType(DeclType.Ptr.TypeQuals); + SourceTy = Context.getQualifiedType(Context.getPointerType(SourceTy), + Qualifiers::fromCVRMask(DeclType.Ptr.TypeQuals)); // Verify that we're not building a pointer to pointer to function with // exception specification. if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { @@ -957,14 +969,16 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name); break; - case DeclaratorChunk::Reference: + case DeclaratorChunk::Reference: { + Qualifiers Quals; + if (DeclType.Ref.HasRestrict) Quals.addRestrict(); + if (ShouldBuildInfo) { if (DeclType.Ref.LValueRef) SourceTy = Context.getLValueReferenceType(SourceTy); else SourceTy = Context.getRValueReferenceType(SourceTy); - unsigned Quals = DeclType.Ref.HasRestrict ? QualType::Restrict : 0; - SourceTy = SourceTy.getQualifiedType(Quals); + SourceTy = Context.getQualifiedType(SourceTy, Quals); } // Verify that we're not building a reference to pointer to function with @@ -974,15 +988,15 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); // Build the type anyway. } - T = BuildReferenceType(T, DeclType.Ref.LValueRef, - DeclType.Ref.HasRestrict ? QualType::Restrict : 0, + T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals, DeclType.Loc, Name); break; + } case DeclaratorChunk::Array: { if (ShouldBuildInfo) // We just need to get an array type, the exact type doesn't matter. SourceTy = Context.getIncompleteArrayType(SourceTy, ArrayType::Normal, - DeclType.Arr.TypeQuals); + DeclType.Arr.TypeQuals); // Verify that we're not building an array of pointers to function with // exception specification. @@ -1009,7 +1023,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, ASM = ArrayType::Normal; D.setInvalidType(true); } - T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals, + T = BuildArrayType(T, ASM, ArraySize, + Qualifiers::fromCVRMask(ATI.TypeQuals), SourceRange(DeclType.Loc, DeclType.EndLoc), Name); break; } @@ -1028,7 +1043,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } SourceTy = Context.getFunctionType(SourceTy, ArgTys.data(), ArgTys.size(), - FTI.isVariadic, FTI.TypeQuals); + FTI.isVariadic, + FTI.TypeQuals); } // If the function declarator has a prototype (i.e. it is not () and @@ -1132,7 +1148,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, Param->setType(ArgTy); } else { // Reject, but continue to parse 'float(const void)'. - if (ArgTy.getCVRQualifiers()) + if (ArgTy.hasQualifiers()) Diag(DeclType.Loc, diag::err_void_param_qualified); // Do not add 'void' to the ArgTys list. @@ -1198,8 +1214,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (ShouldBuildInfo) { QualType cls = !ClsType.isNull() ? ClsType : Context.IntTy; - SourceTy = Context.getMemberPointerType(SourceTy, cls.getTypePtr()) - .getQualifiedType(DeclType.Mem.TypeQuals); + SourceTy = Context.getQualifiedType( + Context.getMemberPointerType(SourceTy, cls.getTypePtr()), + Qualifiers::fromCVRMask(DeclType.Mem.TypeQuals)); } if (!ClsType.isNull()) @@ -1479,7 +1496,7 @@ bool Sema::CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID, SubIsPointer = true; } bool SubIsClass = CanonicalSubT->isRecordType(); - CanonicalSubT.setCVRQualifiers(0); + CanonicalSubT = CanonicalSubT.getUnqualifiedType(); BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); @@ -1501,7 +1518,7 @@ bool Sema::CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID, continue; } } - CanonicalSuperT.setCVRQualifiers(0); + CanonicalSuperT = CanonicalSuperT.getUnqualifiedType(); // If the types are the same, move on to the next type in the subset. if (CanonicalSubT == CanonicalSuperT) { Contained = true; @@ -1633,6 +1650,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { /// space for the type. static void HandleAddressSpaceTypeAttribute(QualType &Type, const AttributeList &Attr, Sema &S){ + // If this type is already address space qualified, reject it. // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers // for two or more different address spaces." @@ -1664,10 +1682,10 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, addrSpace.setIsSigned(false); } llvm::APSInt max(addrSpace.getBitWidth()); - max = QualType::MaxAddressSpace; + max = Qualifiers::MaxAddressSpace; if (addrSpace > max) { S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high) - << QualType::MaxAddressSpace << ASArgExpr->getSourceRange(); + << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange(); return; } @@ -1679,7 +1697,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, /// specified type. The attribute contains 1 argument, weak or strong. static void HandleObjCGCTypeAttribute(QualType &Type, const AttributeList &Attr, Sema &S) { - if (Type.getObjCGCAttr() != QualType::GCNone) { + if (Type.getObjCGCAttr() != Qualifiers::GCNone) { S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc); return; } @@ -1690,15 +1708,15 @@ static void HandleObjCGCTypeAttribute(QualType &Type, << "objc_gc" << 1; return; } - QualType::GCAttrTypes GCAttr; + Qualifiers::GC GCAttr; if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } if (Attr.getParameterName()->isStr("weak")) - GCAttr = QualType::Weak; + GCAttr = Qualifiers::Weak; else if (Attr.getParameterName()->isStr("strong")) - GCAttr = QualType::Strong; + GCAttr = Qualifiers::Strong; else { S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) << "objc_gc" << Attr.getParameterName(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index bd7fb4f2f89..ffbf69b51aa 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -188,7 +188,7 @@ public: /// not permitted (e.g., qualifiers on reference or function types). This /// is the right thing for template instantiation, but probably not for /// other clients. - QualType AddTypeQualifiers(QualType T, unsigned CVRQualifiers); + QualType AddTypeQualifiers(QualType T, Qualifiers Qs); /// \brief Transform the given statement. /// @@ -1935,13 +1935,16 @@ QualType TreeTransform<Derived>::TransformType(QualType T) { if (getDerived().AlreadyTransformed(T)) return T; + QualifierCollector Qs; + const Type *Ty = Qs.strip(T); + QualType Result; - switch (T->getTypeClass()) { + switch (Ty->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) \ case Type::CLASS: \ Result = getDerived().Transform##CLASS##Type( \ - static_cast<CLASS##Type*>(T.getTypePtr())); \ + static_cast<const CLASS##Type*>(Ty)); \ break; #include "clang/AST/TypeNodes.def" } @@ -1949,25 +1952,19 @@ QualType TreeTransform<Derived>::TransformType(QualType T) { if (Result.isNull() || T == Result) return Result; - return getDerived().AddTypeQualifiers(Result, T.getCVRQualifiers()); + return getDerived().AddTypeQualifiers(Result, Qs); } template<typename Derived> QualType -TreeTransform<Derived>::AddTypeQualifiers(QualType T, unsigned CVRQualifiers) { - if (CVRQualifiers && !T->isFunctionType() && !T->isReferenceType()) - return T.getWithAdditionalQualifiers(CVRQualifiers); +TreeTransform<Derived>::AddTypeQualifiers(QualType T, Qualifiers Quals) { + if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType()) + return SemaRef.Context.getQualifiedType(T, Quals); return T; } template<typename Derived> -QualType TreeTransform<Derived>::TransformExtQualType(const ExtQualType *T) { - // FIXME: Implement - return QualType(T, 0); -} - -template<typename Derived> QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) { // Nothing to do return QualType(T, 0); @@ -2076,7 +2073,7 @@ TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) { return getDerived().RebuildConstantArrayType(ElementType, T->getSizeModifier(), T->getSize(), - T->getIndexTypeQualifier()); + T->getIndexTypeCVRQualifiers()); } template<typename Derived> @@ -2103,7 +2100,7 @@ TreeTransform<Derived>::TransformConstantArrayWithExprType( T->getSizeModifier(), T->getSize(), Size.takeAs<Expr>(), - T->getIndexTypeQualifier(), + T->getIndexTypeCVRQualifiers(), T->getBracketsRange()); } @@ -2122,7 +2119,7 @@ TreeTransform<Derived>::TransformConstantArrayWithoutExprType( return getDerived().RebuildConstantArrayWithoutExprType(ElementType, T->getSizeModifier(), T->getSize(), - T->getIndexTypeQualifier()); + T->getIndexTypeCVRQualifiers()); } template<typename Derived> @@ -2138,7 +2135,7 @@ QualType TreeTransform<Derived>::TransformIncompleteArrayType( return getDerived().RebuildIncompleteArrayType(ElementType, T->getSizeModifier(), - T->getIndexTypeQualifier()); + T->getIndexTypeCVRQualifiers()); } template<typename Derived> @@ -2165,7 +2162,7 @@ QualType TreeTransform<Derived>::TransformVariableArrayType( return getDerived().RebuildVariableArrayType(ElementType, T->getSizeModifier(), move(Size), - T->getIndexTypeQualifier(), + T->getIndexTypeCVRQualifiers(), T->getBracketsRange()); } @@ -2193,7 +2190,7 @@ QualType TreeTransform<Derived>::TransformDependentSizedArrayType( return getDerived().RebuildDependentSizedArrayType(ElementType, T->getSizeModifier(), move(Size), - T->getIndexTypeQualifier(), + T->getIndexTypeCVRQualifiers(), T->getBracketsRange()); } @@ -4462,14 +4459,14 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { template<typename Derived> QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) { - return SemaRef.BuildPointerType(PointeeType, 0, + return SemaRef.BuildPointerType(PointeeType, Qualifiers(), getDerived().getBaseLocation(), getDerived().getBaseEntity()); } template<typename Derived> QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) { - return SemaRef.BuildBlockPointerType(PointeeType, 0, + return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), getDerived().getBaseLocation(), getDerived().getBaseEntity()); } @@ -4477,7 +4474,7 @@ QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) { template<typename Derived> QualType TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) { - return SemaRef.BuildReferenceType(ReferentType, true, 0, + return SemaRef.BuildReferenceType(ReferentType, true, Qualifiers(), getDerived().getBaseLocation(), getDerived().getBaseEntity()); } @@ -4485,7 +4482,7 @@ TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) { template<typename Derived> QualType TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) { - return SemaRef.BuildReferenceType(ReferentType, false, 0, + return SemaRef.BuildReferenceType(ReferentType, false, Qualifiers(), getDerived().getBaseLocation(), getDerived().getBaseEntity()); } @@ -4493,7 +4490,7 @@ TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) { template<typename Derived> QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, QualType ClassType) { - return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0, + return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(), getDerived().getBaseLocation(), getDerived().getBaseEntity()); } @@ -4700,7 +4697,7 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, QualType T) { if (T->isDependentType() || T->isRecordType() || (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) { - assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here"); + assert(!T.hasQualifiers() && "Can't get cv-qualifiers here"); return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW, T.getTypePtr()); } |