diff options
author | John McCall <rjmccall@apple.com> | 2009-09-24 19:53:00 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-09-24 19:53:00 +0000 |
commit | 8ccfcb51ee020c4ca0e76838a2ef57cb5bb77914 (patch) | |
tree | 13ac964a39ac7c94d225bf75d6c92141cdfefbc2 /clang/lib/Sema | |
parent | 6d98ede7e8511180699b41e12b2de5f979d8bb14 (diff) | |
download | bcm5719-llvm-8ccfcb51ee020c4ca0e76838a2ef57cb5bb77914.tar.gz bcm5719-llvm-8ccfcb51ee020c4ca0e76838a2ef57cb5bb77914.zip |
Refactor the representation of qualifiers to bring ExtQualType out of the
Type hierarchy. Demote 'volatile' to extended-qualifier status. Audit our
use of qualifiers and fix a few places that weren't dealing with qualifiers
quite right; many more remain.
llvm-svn: 82705
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 83 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 59 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInherit.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 95 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 43 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 132 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 47 |
13 files changed, 292 insertions, 237 deletions
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()); } |