aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-09-24 19:53:00 +0000
committerJohn McCall <rjmccall@apple.com>2009-09-24 19:53:00 +0000
commit0953e767ff7817f97b3ab20896b229891eeff45b (patch)
treeae766419bc367458454d0ff47206caf639a6934b /lib/Sema
parente7a5fd4a2969176d8b63a0a26039f895fc359ac4 (diff)
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
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.cpp4
-rw-r--r--lib/Sema/SemaCXXCast.cpp19
-rw-r--r--lib/Sema/SemaDecl.cpp10
-rw-r--r--lib/Sema/SemaDeclCXX.cpp20
-rw-r--r--lib/Sema/SemaExpr.cpp83
-rw-r--r--lib/Sema/SemaExprCXX.cpp59
-rw-r--r--lib/Sema/SemaInherit.cpp2
-rw-r--r--lib/Sema/SemaOverload.cpp95
-rw-r--r--lib/Sema/SemaStmt.cpp13
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp43
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp2
-rw-r--r--lib/Sema/SemaType.cpp132
-rw-r--r--lib/Sema/TreeTransform.h47
13 files changed, 292 insertions, 237 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 63b252a536..81f7283e23 100644
--- a/lib/Sema/Sema.cpp
+++ b/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/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index d1a8b6dedf..ab085fb8ee 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 084b2efcf3..ec27814870 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 5cced5a92e..390a8048db 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9695814860..5bc8818dba 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index ff6ae50533..e93929e94b 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/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/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp
index 01e856c1d6..8f932ac7d1 100644
--- a/lib/Sema/SemaInherit.cpp
+++ b/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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 4232d54f4b..edb854ccdd 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/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/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 4ffca8c8f5..a73c261d97 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/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/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 8d4999bf6d..2ad1a61b50 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/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.