Refactor the representation of qualifiers to bring ExtQualType out of the
Type hierarchy. Demote 'volatile' to extended-qualifier status. Audit our
use of qualifiers and fix a few places that weren't dealing with qualifiers
quite right; many more remain.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82705 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 63b252a..81f7283 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -44,9 +44,7 @@
// 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/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index d1a8b6d..ab085fb 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -186,12 +186,12 @@
"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 @@
// 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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 084b2ef..ec27814 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1814,14 +1814,16 @@
// 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 @@
// 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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 5cced5a..390a804 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2046,13 +2046,13 @@
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 @@
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 @@
// 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 @@
// -- 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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9695814..5bc8818 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -566,7 +566,7 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
// - 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 @@
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 @@
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 @@
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 @@
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 @@
// 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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index ff6ae50..e93929e 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -972,7 +972,7 @@
= 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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
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/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp
index 01e856c..8f932ac 100644
--- a/lib/Sema/SemaInherit.cpp
+++ b/lib/Sema/SemaInherit.cpp
@@ -59,7 +59,7 @@
/// 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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 4232d54..edb854c 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -856,12 +856,12 @@
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 @@
}
// 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 @@
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 @@
/// 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.
+ const PointerType *PointerTy = Ty->getAs<PointerType>();
+ assert(PointerTy && "type was not a pointer type!");
- // 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()));
+ 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 @@
/// 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 @@
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.
+ const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
+ assert(PointerTy && "type was not a member pointer type!");
- 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));
+ 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/*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 @@
// 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/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 4ffca8c..a73c261 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1295,22 +1295,19 @@
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/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 8d4999b..2ad1a61 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -300,28 +300,30 @@
}
/// \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 @@
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 @@
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(),
- CVRQuals);
+ Quals);
if (Elt == DSAT->getElementType())
return T;
@@ -387,9 +389,9 @@
// 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 @@
// 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 @@
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 @@
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/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 86b49d4..90a0397 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -496,7 +496,7 @@
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/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 6fee787..c297694 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -312,7 +312,7 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
///
/// \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 @@
// 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 @@
// 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 @@
// 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 @@
// 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::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 @@
///
/// \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 @@
// 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 @@
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 @@
///
/// \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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
SubIsPointer = true;
}
bool SubIsClass = CanonicalSubT->isRecordType();
- CanonicalSubT.setCVRQualifiers(0);
+ CanonicalSubT = CanonicalSubT.getUnqualifiedType();
BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
@@ -1501,7 +1518,7 @@
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 @@
/// 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 @@
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 @@
/// 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 @@
<< "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/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index bd7fb4f..ffbf69b 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -188,7 +188,7 @@
/// 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 @@
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 @@
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 @@
return getDerived().RebuildConstantArrayType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2103,7 +2100,7 @@
T->getSizeModifier(),
T->getSize(),
Size.takeAs<Expr>(),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -2122,7 +2119,7 @@
return getDerived().RebuildConstantArrayWithoutExprType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2138,7 +2135,7 @@
return getDerived().RebuildIncompleteArrayType(ElementType,
T->getSizeModifier(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2165,7 +2162,7 @@
return getDerived().RebuildVariableArrayType(ElementType,
T->getSizeModifier(),
move(Size),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -2193,7 +2190,7 @@
return getDerived().RebuildDependentSizedArrayType(ElementType,
T->getSizeModifier(),
move(Size),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -4462,14 +4459,14 @@
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 @@
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 @@
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 @@
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 @@
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());
}