summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp404
-rw-r--r--clang/lib/AST/DeclCXX.cpp11
-rw-r--r--clang/lib/AST/DeclarationName.cpp4
-rw-r--r--clang/lib/AST/Expr.cpp8
-rw-r--r--clang/lib/AST/ExprConstant.cpp2
-rw-r--r--clang/lib/AST/StmtDumper.cpp9
-rw-r--r--clang/lib/AST/Type.cpp229
-rw-r--r--clang/lib/CodeGen/CGCXX.cpp4
-rw-r--r--clang/lib/CodeGen/CGCall.cpp2
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp1
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp158
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp11
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp3
-rw-r--r--clang/lib/CodeGen/CGObjCMac.cpp30
-rw-r--r--clang/lib/CodeGen/CGValue.h77
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h6
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp8
-rw-r--r--clang/lib/CodeGen/Mangle.cpp31
-rw-r--r--clang/lib/Frontend/DocumentXML.cpp4
-rw-r--r--clang/lib/Frontend/PCHReader.cpp27
-rw-r--r--clang/lib/Frontend/PCHWriter.cpp68
-rw-r--r--clang/lib/Frontend/RewriteObjC.cpp9
-rw-r--r--clang/lib/Sema/Sema.cpp4
-rw-r--r--clang/lib/Sema/SemaCXXCast.cpp19
-rw-r--r--clang/lib/Sema/SemaDecl.cpp10
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp20
-rw-r--r--clang/lib/Sema/SemaExpr.cpp83
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp59
-rw-r--r--clang/lib/Sema/SemaInherit.cpp2
-rw-r--r--clang/lib/Sema/SemaOverload.cpp95
-rw-r--r--clang/lib/Sema/SemaStmt.cpp13
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp43
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp2
-rw-r--r--clang/lib/Sema/SemaType.cpp132
-rw-r--r--clang/lib/Sema/TreeTransform.h47
35 files changed, 743 insertions, 892 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 8fe5852328f..a2a88af44f8 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -59,6 +59,13 @@ ASTContext::~ASTContext() {
}
{
+ llvm::FoldingSet<ExtQuals>::iterator
+ I = ExtQualNodes.begin(), E = ExtQualNodes.end();
+ while (I != E)
+ Deallocate(&*I++);
+ }
+
+ {
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end();
while (I != E) {
@@ -525,6 +532,10 @@ unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
+///
+/// FIXME: Pointers into different addr spaces could have different sizes and
+/// alignment requirements: getPointerInfo should take an AddrSpace, this
+/// should take a QualType, &c.
std::pair<uint64_t, unsigned>
ASTContext::getTypeInfo(const Type *T) {
uint64_t Width=0;
@@ -656,10 +667,6 @@ ASTContext::getTypeInfo(const Type *T) {
Width = std::max(llvm::NextPowerOf2(Width - 1), (uint64_t)8);
Align = Width;
break;
- case Type::ExtQual:
- // FIXME: Pointers into different addr spaces could have different sizes and
- // alignment requirements: getPointerInfo should take an AddrSpace.
- return getTypeInfo(QualType(cast<ExtQualType>(T)->getBaseType(), 0));
case Type::ObjCObjectPointer:
Width = Target.getPointerWidth(0);
Align = Target.getPointerAlign(0);
@@ -1002,52 +1009,58 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
+QualType ASTContext::getExtQualType(const Type *TypeNode, Qualifiers Quals) {
+ unsigned Fast = Quals.getFastQualifiers();
+ Quals.removeFastQualifiers();
+
+ // Check if we've already instantiated this type.
+ llvm::FoldingSetNodeID ID;
+ ExtQuals::Profile(ID, TypeNode, Quals);
+ void *InsertPos = 0;
+ if (ExtQuals *EQ = ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos)) {
+ assert(EQ->getQualifiers() == Quals);
+ QualType T = QualType(EQ, Fast);
+ return T;
+ }
+
+ ExtQuals *New = new (*this, 8) ExtQuals(*this, TypeNode, Quals);
+ ExtQualNodes.InsertNode(New, InsertPos);
+ QualType T = QualType(New, Fast);
+ return T;
+}
+
+QualType ASTContext::getVolatileType(QualType T) {
+ QualType CanT = getCanonicalType(T);
+ if (CanT.isVolatileQualified()) return T;
+
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
+ Quals.addVolatile();
+
+ return getExtQualType(TypeNode, Quals);
+}
+
QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) {
QualType CanT = getCanonicalType(T);
if (CanT.getAddressSpace() == AddressSpace)
return T;
- // If we are composing extended qualifiers together, merge together into one
- // ExtQualType node.
- unsigned CVRQuals = T.getCVRQualifiers();
- QualType::GCAttrTypes GCAttr = QualType::GCNone;
- Type *TypeNode = T.getTypePtr();
-
- if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) {
- // If this type already has an address space specified, it cannot get
- // another one.
- assert(EQT->getAddressSpace() == 0 &&
- "Type cannot be in multiple addr spaces!");
- GCAttr = EQT->getObjCGCAttr();
- TypeNode = EQT->getBaseType();
- }
+ // If we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
- // Check if we've already instantiated this type.
- llvm::FoldingSetNodeID ID;
- ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
- void *InsertPos = 0;
- if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(EXTQy, CVRQuals);
-
- // If the base type isn't canonical, this won't be a canonical type either,
- // so fill in the canonical type field.
- QualType Canonical;
- if (!TypeNode->isCanonical()) {
- Canonical = getAddrSpaceQualType(CanT, AddressSpace);
+ // If this type already has an address space specified, it cannot get
+ // another one.
+ assert(!Quals.hasAddressSpace() &&
+ "Type cannot be in multiple addr spaces!");
+ Quals.addAddressSpace(AddressSpace);
- // Update InsertPos, the previous call could have invalidated it.
- ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
- }
- ExtQualType *New =
- new (*this, 8) ExtQualType(TypeNode, Canonical, AddressSpace, GCAttr);
- ExtQualTypes.InsertNode(New, InsertPos);
- Types.push_back(New);
- return QualType(New, CVRQuals);
+ return getExtQualType(TypeNode, Quals);
}
QualType ASTContext::getObjCGCQualType(QualType T,
- QualType::GCAttrTypes GCAttr) {
+ Qualifiers::GC GCAttr) {
QualType CanT = getCanonicalType(T);
if (CanT.getObjCGCAttr() == GCAttr)
return T;
@@ -1059,75 +1072,48 @@ QualType ASTContext::getObjCGCQualType(QualType T,
return getPointerType(ResultType);
}
}
- // If we are composing extended qualifiers together, merge together into one
- // ExtQualType node.
- unsigned CVRQuals = T.getCVRQualifiers();
- Type *TypeNode = T.getTypePtr();
- unsigned AddressSpace = 0;
-
- if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) {
- // If this type already has an ObjCGC specified, it cannot get
- // another one.
- assert(EQT->getObjCGCAttr() == QualType::GCNone &&
- "Type cannot have multiple ObjCGCs!");
- AddressSpace = EQT->getAddressSpace();
- TypeNode = EQT->getBaseType();
- }
- // Check if we've already instantiated an gc qual'd type of this type.
- llvm::FoldingSetNodeID ID;
- ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
- void *InsertPos = 0;
- if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(EXTQy, CVRQuals);
+ // If we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
- // If the base type isn't canonical, this won't be a canonical type either,
- // so fill in the canonical type field.
- // FIXME: Isn't this also not canonical if the base type is a array
- // or pointer type? I can't find any documentation for objc_gc, though...
- QualType Canonical;
- if (!T->isCanonical()) {
- Canonical = getObjCGCQualType(CanT, GCAttr);
+ // If this type already has an ObjCGC specified, it cannot get
+ // another one.
+ assert(!Quals.hasObjCGCAttr() &&
+ "Type cannot have multiple ObjCGCs!");
+ Quals.addObjCGCAttr(GCAttr);
- // Update InsertPos, the previous call could have invalidated it.
- ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos);
- assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
- }
- ExtQualType *New =
- new (*this, 8) ExtQualType(TypeNode, Canonical, AddressSpace, GCAttr);
- ExtQualTypes.InsertNode(New, InsertPos);
- Types.push_back(New);
- return QualType(New, CVRQuals);
+ return getExtQualType(TypeNode, Quals);
}
QualType ASTContext::getNoReturnType(QualType T) {
- QualifierSet qs;
- qs.strip(T);
+ QualType ResultType;
if (T->isPointerType()) {
QualType Pointee = T->getAs<PointerType>()->getPointeeType();
- QualType ResultType = getNoReturnType(Pointee);
+ ResultType = getNoReturnType(Pointee);
ResultType = getPointerType(ResultType);
- ResultType.setCVRQualifiers(T.getCVRQualifiers());
- return qs.apply(ResultType, *this);
- }
- if (T->isBlockPointerType()) {
+ } else if (T->isBlockPointerType()) {
QualType Pointee = T->getAs<BlockPointerType>()->getPointeeType();
- QualType ResultType = getNoReturnType(Pointee);
+ ResultType = getNoReturnType(Pointee);
ResultType = getBlockPointerType(ResultType);
- ResultType.setCVRQualifiers(T.getCVRQualifiers());
- return qs.apply(ResultType, *this);
- }
- if (!T->isFunctionType())
- assert(0 && "can't noreturn qualify non-pointer to function or block type");
+ } else {
+ assert (T->isFunctionType()
+ && "can't noreturn qualify non-pointer to function or block type");
- if (const FunctionNoProtoType *F = T->getAs<FunctionNoProtoType>()) {
- return getFunctionNoProtoType(F->getResultType(), true);
+ if (const FunctionNoProtoType *F = T->getAs<FunctionNoProtoType>()) {
+ ResultType = getFunctionNoProtoType(F->getResultType(), true);
+ } else {
+ const FunctionProtoType *F = T->getAs<FunctionProtoType>();
+ ResultType
+ = getFunctionType(F->getResultType(), F->arg_type_begin(),
+ F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
+ F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
+ F->getNumExceptions(), F->exception_begin(), true);
+ }
}
- const FunctionProtoType *F = T->getAs<FunctionProtoType>();
- return getFunctionType(F->getResultType(), F->arg_type_begin(),
- F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
- F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
- F->getNumExceptions(), F->exception_begin(), true);
+
+ return getQualifiedType(ResultType, T.getQualifiers());
}
/// getComplexType - Return the uniqued reference to the type for a complex
@@ -1645,8 +1631,8 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
const QualType *ExArray, bool NoReturn) {
if (LangOpts.CPlusPlus) {
for (unsigned i = 0; i != NumArgs; ++i)
- assert(!ArgArray[i].getCVRQualifiers() &&
- "C++ arguments can't have toplevel CVR qualifiers!");
+ assert(!ArgArray[i].hasQualifiers() &&
+ "C++ arguments can't have toplevel qualifiers!");
}
// Unique functions, to guarantee there is only one function of a particular
@@ -2157,33 +2143,38 @@ QualType ASTContext::getPointerDiffType() const {
/// to be free of any of these, allowing two canonical types to be compared
/// for exact equality with a simple pointer comparison.
CanQualType ASTContext::getCanonicalType(QualType T) {
- QualType CanType = T.getTypePtr()->getCanonicalTypeInternal();
+ QualifierCollector Quals;
+ const Type *Ptr = Quals.strip(T);
+ QualType CanType = Ptr->getCanonicalTypeInternal();
+
+ // The canonical internal type will be the canonical type *except*
+ // that we push type qualifiers down through array types.
- // If the result has type qualifiers, make sure to canonicalize them as well.
- unsigned TypeQuals = T.getCVRQualifiers() | CanType.getCVRQualifiers();
- if (TypeQuals == 0)
+ // If there are no new qualifiers to push down, stop here.
+ if (!Quals.hasQualifiers())
return CanQualType::CreateUnsafe(CanType);
- // If the type qualifiers are on an array type, get the canonical type of the
- // array with the qualifiers applied to the element type.
+ // If the type qualifiers are on an array type, get the canonical
+ // type of the array with the qualifiers applied to the element
+ // type.
ArrayType *AT = dyn_cast<ArrayType>(CanType);
if (!AT)
- return CanQualType::CreateUnsafe(CanType.getQualifiedType(TypeQuals));
+ return CanQualType::CreateUnsafe(getQualifiedType(CanType, Quals));
// Get the canonical version of the element with the extra qualifiers on it.
// This can recursively sink qualifiers through multiple levels of arrays.
- QualType NewEltTy=AT->getElementType().getWithAdditionalQualifiers(TypeQuals);
+ QualType NewEltTy = getQualifiedType(AT->getElementType(), Quals);
NewEltTy = getCanonicalType(NewEltTy);
if (ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
return CanQualType::CreateUnsafe(
getConstantArrayType(NewEltTy, CAT->getSize(),
CAT->getSizeModifier(),
- CAT->getIndexTypeQualifier()));
+ CAT->getIndexTypeCVRQualifiers()));
if (IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT))
return CanQualType::CreateUnsafe(
getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
- IAT->getIndexTypeQualifier()));
+ IAT->getIndexTypeCVRQualifiers()));
if (DependentSizedArrayType *DSAT = dyn_cast<DependentSizedArrayType>(AT))
return CanQualType::CreateUnsafe(
@@ -2191,7 +2182,7 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
DSAT->getSizeExpr() ?
DSAT->getSizeExpr()->Retain() : 0,
DSAT->getSizeModifier(),
- DSAT->getIndexTypeQualifier(),
+ DSAT->getIndexTypeCVRQualifiers(),
DSAT->getBracketsRange()));
VariableArrayType *VAT = cast<VariableArrayType>(AT);
@@ -2199,7 +2190,7 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
VAT->getSizeExpr() ?
VAT->getSizeExpr()->Retain() : 0,
VAT->getSizeModifier(),
- VAT->getIndexTypeQualifier(),
+ VAT->getIndexTypeCVRQualifiers(),
VAT->getBracketsRange()));
}
@@ -2316,68 +2307,47 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) {
const ArrayType *ASTContext::getAsArrayType(QualType T) {
// Handle the non-qualified case efficiently.
- if (T.getCVRQualifiers() == 0) {
+ if (!T.hasQualifiers()) {
// Handle the common positive case fast.
if (const ArrayType *AT = dyn_cast<ArrayType>(T))
return AT;
}
- // Handle the common negative case fast, ignoring CVR qualifiers.
+ // Handle the common negative case fast.
QualType CType = T->getCanonicalTypeInternal();
-
- // Make sure to look through type qualifiers (like ExtQuals) for the negative
- // test.
- if (!isa<ArrayType>(CType) &&
- !isa<ArrayType>(CType.getUnqualifiedType()))
+ if (!isa<ArrayType>(CType))
return 0;
- // Apply any CVR qualifiers from the array type to the element type. This
+ // Apply any qualifiers from the array type to the element type. This
// implements C99 6.7.3p8: "If the specification of an array type includes
// any type qualifiers, the element type is so qualified, not the array type."
// If we get here, we either have type qualifiers on the type, or we have
// sugar such as a typedef in the way. If we have type qualifiers on the type
// we must propagate them down into the element type.
- unsigned CVRQuals = T.getCVRQualifiers();
- unsigned AddrSpace = 0;
- Type *Ty = T.getTypePtr();
-
- // Rip through ExtQualType's and typedefs to get to a concrete type.
- while (1) {
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(Ty)) {
- AddrSpace = EXTQT->getAddressSpace();
- Ty = EXTQT->getBaseType();
- } else {
- T = Ty->getDesugaredType();
- if (T.getTypePtr() == Ty && T.getCVRQualifiers() == 0)
- break;
- CVRQuals |= T.getCVRQualifiers();
- Ty = T.getTypePtr();
- }
- }
+
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T.getDesugaredType());
// If we have a simple case, just return now.
const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
- if (ATy == 0 || (AddrSpace == 0 && CVRQuals == 0))
+ if (ATy == 0 || Qs.empty())
return ATy;
// Otherwise, we have an array and we have qualifiers on it. Push the
// qualifiers into the array element type and return a new array type.
// Get the canonical version of the element with the extra qualifiers on it.
// This can recursively sink qualifiers through multiple levels of arrays.
- QualType NewEltTy = ATy->getElementType();
- if (AddrSpace)
- NewEltTy = getAddrSpaceQualType(NewEltTy, AddrSpace);
- NewEltTy = NewEltTy.getWithAdditionalQualifiers(CVRQuals);
+ QualType NewEltTy = getQualifiedType(ATy->getElementType(), Qs);
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
CAT->getSizeModifier(),
- CAT->getIndexTypeQualifier()));
+ CAT->getIndexTypeCVRQualifiers()));
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
IAT->getSizeModifier(),
- IAT->getIndexTypeQualifier()));
+ IAT->getIndexTypeCVRQualifiers()));
if (const DependentSizedArrayType *DSAT
= dyn_cast<DependentSizedArrayType>(ATy))
@@ -2386,15 +2356,15 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) {
DSAT->getSizeExpr() ?
DSAT->getSizeExpr()->Retain() : 0,
DSAT->getSizeModifier(),
- DSAT->getIndexTypeQualifier(),
+ DSAT->getIndexTypeCVRQualifiers(),
DSAT->getBracketsRange()));
const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
return cast<ArrayType>(getVariableArrayType(NewEltTy,
VAT->getSizeExpr() ?
- VAT->getSizeExpr()->Retain() : 0,
+ VAT->getSizeExpr()->Retain() : 0,
VAT->getSizeModifier(),
- VAT->getIndexTypeQualifier(),
+ VAT->getIndexTypeCVRQualifiers(),
VAT->getBracketsRange()));
}
@@ -2416,17 +2386,17 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) {
QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
// int x[restrict 4] -> int *restrict
- return PtrTy.getQualifiedType(PrettyArrayType->getIndexTypeQualifier());
+ return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers());
}
QualType ASTContext::getBaseElementType(QualType QT) {
- QualifierSet qualifiers;
+ QualifierCollector Qs;
while (true) {
- const Type *UT = qualifiers.strip(QT);
+ const Type *UT = Qs.strip(QT);
if (const ArrayType *AT = getAsArrayType(QualType(UT,0))) {
QT = AT->getElementType();
} else {
- return qualifiers.apply(QT, *this);
+ return Qs.apply(QT);
}
}
}
@@ -2651,11 +2621,11 @@ QualType ASTContext::getCFConstantStringType() {
QualType FieldTypes[4];
// const int *isa;
- FieldTypes[0] = getPointerType(IntTy.getQualifiedType(QualType::Const));
+ FieldTypes[0] = getPointerType(IntTy.withConst());
// int flags;
FieldTypes[1] = IntTy;
// const char *str;
- FieldTypes[2] = getPointerType(CharTy.getQualifiedType(QualType::Const));
+ FieldTypes[2] = getPointerType(CharTy.withConst());
// long length;
FieldTypes[3] = LongTy;
@@ -3139,9 +3109,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
- if (T->isObjCInterfaceType()) {
+ if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) {
// @encode(class_name)
- ObjCInterfaceDecl *OI = T->getAs<ObjCInterfaceType>()->getDecl();
+ ObjCInterfaceDecl *OI = OIT->getDecl();
S += '{';
const IdentifierInfo *II = OI->getIdentifier();
S += II->getName();
@@ -3388,24 +3358,24 @@ bool ASTContext::isObjCNSObjectType(QualType Ty) const {
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
/// garbage collection attribute.
///
-QualType::GCAttrTypes ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
- QualType::GCAttrTypes GCAttrs = QualType::GCNone;
+Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
+ Qualifiers::GC GCAttrs = Qualifiers::GCNone;
if (getLangOptions().ObjC1 &&
getLangOptions().getGCMode() != LangOptions::NonGC) {
GCAttrs = Ty.getObjCGCAttr();
// Default behavious under objective-c's gc is for objective-c pointers
// (or pointers to them) be treated as though they were declared
// as __strong.
- if (GCAttrs == QualType::GCNone) {
+ if (GCAttrs == Qualifiers::GCNone) {
if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
- GCAttrs = QualType::Strong;
+ GCAttrs = Qualifiers::Strong;
else if (Ty->isPointerType())
return getObjCGCAttrKind(Ty->getAs<PointerType>()->getPointeeType());
}
// Non-pointers have none gc'able attribute regardless of the attribute
// set on them.
else if (!Ty->isAnyPointerType() && !Ty->isBlockPointerType())
- return QualType::GCNone;
+ return Qualifiers::GCNone;
}
return GCAttrs;
}
@@ -3766,11 +3736,38 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
if (LHSCan == RHSCan)
return LHS;
- // If the qualifiers are different, the types aren't compatible
- // Note that we handle extended qualifiers later, in the
- // case for ExtQualType.
- if (LHSCan.getCVRQualifiers() != RHSCan.getCVRQualifiers())
+ // If the qualifiers are different, the types aren't compatible... mostly.
+ Qualifiers LQuals = LHSCan.getQualifiers();
+ Qualifiers RQuals = RHSCan.getQualifiers();
+ if (LQuals != RQuals) {
+ // If any of these qualifiers are different, we have a type
+ // mismatch.
+ if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
+ LQuals.getAddressSpace() != RQuals.getAddressSpace())
+ return QualType();
+
+ // Exactly one GC qualifier difference is allowed: __strong is
+ // okay if the other type has no GC qualifier but is an Objective
+ // C object pointer (i.e. implicitly strong by default). We fix
+ // this by pretending that the unqualified type was actually
+ // qualified __strong.
+ Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
+ Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
+ assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
+
+ if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
+ return QualType();
+
+ if (GC_L == Qualifiers::Strong && RHSCan->isObjCObjectPointerType()) {
+ return mergeTypes(LHS, getObjCGCQualType(RHS, Qualifiers::Strong));
+ }
+ if (GC_R == Qualifiers::Strong && LHSCan->isObjCObjectPointerType()) {
+ return mergeTypes(getObjCGCQualType(LHS, Qualifiers::Strong), RHS);
+ }
return QualType();
+ }
+
+ // Okay, qualifiers are equal.
Type::TypeClass LHSClass = LHSCan->getTypeClass();
Type::TypeClass RHSClass = RHSCan->getTypeClass();
@@ -3780,59 +3777,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
if (LHSClass == Type::FunctionProto) LHSClass = Type::FunctionNoProto;
if (RHSClass == Type::FunctionProto) RHSClass = Type::FunctionNoProto;
- // Strip off objc_gc attributes off the top level so they can be merged.
- // This is a complete mess, but the attribute itself doesn't make much sense.
- if (RHSClass == Type::ExtQual) {
- QualType::GCAttrTypes GCAttr = RHSCan.getObjCGCAttr();
- if (GCAttr != QualType::GCNone) {
- QualType::GCAttrTypes GCLHSAttr = LHSCan.getObjCGCAttr();
- // __weak attribute must appear on both declarations.
- // __strong attribue is redundant if other decl is an objective-c
- // object pointer (or decorated with __strong attribute); otherwise
- // issue error.
- if ((GCAttr == QualType::Weak && GCLHSAttr != GCAttr) ||
- (GCAttr == QualType::Strong && GCLHSAttr != GCAttr &&
- !LHSCan->isObjCObjectPointerType()))
- return QualType();
-
- RHS = QualType(cast<ExtQualType>(RHS.getDesugaredType())->getBaseType(),
- RHS.getCVRQualifiers());
- QualType Result = mergeTypes(LHS, RHS);
- if (!Result.isNull()) {
- if (Result.getObjCGCAttr() == QualType::GCNone)
- Result = getObjCGCQualType(Result, GCAttr);
- else if (Result.getObjCGCAttr() != GCAttr)
- Result = QualType();
- }
- return Result;
- }
- }
- if (LHSClass == Type::ExtQual) {
- QualType::GCAttrTypes GCAttr = LHSCan.getObjCGCAttr();
- if (GCAttr != QualType::GCNone) {
- QualType::GCAttrTypes GCRHSAttr = RHSCan.getObjCGCAttr();
- // __weak attribute must appear on both declarations. __strong
- // __strong attribue is redundant if other decl is an objective-c
- // object pointer (or decorated with __strong attribute); otherwise
- // issue error.
- if ((GCAttr == QualType::Weak && GCRHSAttr != GCAttr) ||
- (GCAttr == QualType::Strong && GCRHSAttr != GCAttr &&
- !RHSCan->isObjCObjectPointerType()))
- return QualType();
-
- LHS = QualType(cast<ExtQualType>(LHS.getDesugaredType())->getBaseType(),
- LHS.getCVRQualifiers());
- QualType Result = mergeTypes(LHS, RHS);
- if (!Result.isNull()) {
- if (Result.getObjCGCAttr() == QualType::GCNone)
- Result = getObjCGCQualType(Result, GCAttr);
- else if (Result.getObjCGCAttr() != GCAttr)
- Result = QualType();
- }
- return Result;
- }
- }
-
// Same as above for arrays
if (LHSClass == Type::VariableArray || LHSClass == Type::IncompleteArray)
LHSClass = Type::ConstantArray;
@@ -3988,34 +3932,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
case Type::FixedWidthInt:
// Distinct fixed-width integers are not compatible.
return QualType();
- case Type::ExtQual:
- // FIXME: ExtQual types can be compatible even if they're not
- // identical!
- return QualType();
- // First attempt at an implementation, but I'm not really sure it's
- // right...
-#if 0
- ExtQualType* LQual = cast<ExtQualType>(LHSCan);
- ExtQualType* RQual = cast<ExtQualType>(RHSCan);
- if (LQual->getAddressSpace() != RQual->getAddressSpace() ||
- LQual->getObjCGCAttr() != RQual->getObjCGCAttr())
- return QualType();
- QualType LHSBase, RHSBase, ResultType, ResCanUnqual;
- LHSBase = QualType(LQual->getBaseType(), 0);
- RHSBase = QualType(RQual->getBaseType(), 0);
- ResultType = mergeTypes(LHSBase, RHSBase);
- if (ResultType.isNull()) return QualType();
- ResCanUnqual = getCanonicalType(ResultType).getUnqualifiedType();
- if (LHSCan.getUnqualifiedType() == ResCanUnqual)
- return LHS;
- if (RHSCan.getUnqualifiedType() == ResCanUnqual)
- return RHS;
- ResultType = getAddrSpaceQualType(ResultType, LQual->getAddressSpace());
- ResultType = getObjCGCQualType(ResultType, LQual->getObjCGCAttr());
- ResultType.setCVRQualifiers(LHSCan.getCVRQualifiers());
- return ResultType;
-#endif
-
case Type::TemplateSpecialization:
assert(false && "Dependent types have no size");
break;
@@ -4231,7 +4147,7 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context,
break;
// FIXME: There's no way to have a built-in with an rvalue ref arg.
case 'C':
- Type = Type.getQualifiedType(QualType::Const);
+ Type = Type.withConst();
break;
}
}
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index f3ea04305bb..fc04ed401bf 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -146,7 +146,7 @@ CXXRecordDecl::setBases(ASTContext &C,
}
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
- return getCopyConstructor(Context, QualType::Const) != 0;
+ return getCopyConstructor(Context, Qualifiers::Const) != 0;
}
CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
@@ -167,8 +167,8 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
FoundTQs)) {
- if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) ||
- (!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const)))
+ if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) ||
+ (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const)))
return cast<CXXConstructorDecl>(*Con);
}
@@ -508,7 +508,8 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
ClassTy = TD->getInjectedClassNameType(C);
else
ClassTy = C.getTagDeclType(getParent());
- ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
+ ClassTy = C.getQualifiedType(ClassTy,
+ Qualifiers::fromCVRMask(getTypeQualifiers()));
return C.getPointerType(ClassTy);
}
@@ -600,6 +601,8 @@ CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
if (PointeeType.getUnqualifiedType() != ClassTy)
return false;
+ // FIXME: other qualifiers?
+
// We have a copy constructor.
TypeQuals = PointeeType.getCVRQualifiers();
return true;
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp
index a01a89201ae..101ddd25093 100644
--- a/clang/lib/AST/DeclarationName.cpp
+++ b/clang/lib/AST/DeclarationName.cpp
@@ -309,11 +309,11 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
switch (Kind) {
case DeclarationName::CXXConstructorName:
EKind = DeclarationNameExtra::CXXConstructor;
- assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified");
+ assert(!Ty.hasQualifiers() &&"Constructor type must be unqualified");
break;
case DeclarationName::CXXDestructorName:
EKind = DeclarationNameExtra::CXXDestructor;
- assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified");
+ assert(!Ty.hasQualifiers() && "Destructor type must be unqualified");
break;
case DeclarationName::CXXConversionFunctionName:
EKind = DeclarationNameExtra::CXXConversionFunction;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9d2d46fa0c1..dc9cee13a9c 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -825,7 +825,7 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
return LV_NotObjectType;
// Allow qualified void which is an incomplete type other than void (yuck).
- if (TR->isVoidType() && !Ctx.getCanonicalType(TR).getCVRQualifiers())
+ if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
return LV_IncompleteVoidType;
return LV_Valid;
@@ -1120,7 +1120,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
// dereferencing to a pointer is always a gc'able candidate,
// unless it is __weak.
return T->isPointerType() &&
- (Ctx.getObjCGCAttrKind(T) != QualType::Weak);
+ (Ctx.getObjCGCAttrKind(T) != Qualifiers::Weak);
}
return false;
}
@@ -1397,7 +1397,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
return NoDiag();
if (Ctx.getLangOptions().CPlusPlus &&
- E->getType().getCVRQualifiers() == QualType::Const) {
+ E->getType().getCVRQualifiers() == Qualifiers::Const) {
// C++ 7.1.5.1p2
// A variable of non-volatile const-qualified integral or enumeration
// type initialized by an ICE can be used in ICEs.
@@ -1635,7 +1635,7 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const {
// Check that it is a cast to void*.
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
- if (Pointee.getCVRQualifiers() == 0 &&
+ if (!Pointee.hasQualifiers() &&
Pointee->isVoidType() && // to void*
CE->getSubExpr()->getType()->isIntegerType()) // from int.
return CE->getSubExpr()->isNullPointerConstant(Ctx);
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5123aaa7ca7..2aefae6fd74 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -783,7 +783,7 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
// In C++, const, non-volatile integers initialized with ICEs are ICEs.
// In C, they can also be folded, although they are not ICEs.
- if (E->getType().getCVRQualifiers() == QualType::Const) {
+ if (E->getType().getCVRQualifiers() == Qualifiers::Const) {
if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
if (APValue *V = D->getEvaluatedValue())
return Success(V->getInt(), E);
diff --git a/clang/lib/AST/StmtDumper.cpp b/clang/lib/AST/StmtDumper.cpp
index ed92da375f3..0465999a94c 100644
--- a/clang/lib/AST/StmtDumper.cpp
+++ b/clang/lib/AST/StmtDumper.cpp
@@ -87,13 +87,10 @@ namespace {
fprintf(F, "'%s'", T.getAsString().c_str());
if (!T.isNull()) {
- // If the type is directly a typedef, strip off typedefness to give at
- // least one level of concreteness.
- if (TypedefType *TDT = dyn_cast<TypedefType>(T)) {
- QualType Simplified =
- TDT->LookThroughTypedefs().getQualifiedType(T.getCVRQualifiers());
+ // If the type is sugared, also dump a (shallow) desugared type.
+ QualType Simplified = T.getDesugaredType();
+ if (Simplified != T)
fprintf(F, ":'%s'", Simplified.getAsString().c_str());
- }
}
}
void DumpStmt(const Stmt *Node) {
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 27832116616..bda06ace1bc 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -101,12 +101,8 @@ const Type *Type::getArrayElementTypeNoTypeQual() const {
return ATy->getElementType().getTypePtr();
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ArrayType>(CanonicalType)) {
- // Look through type qualifiers
- if (ArrayType *AT = dyn_cast<ArrayType>(CanonicalType.getUnqualifiedType()))
- return AT->getElementType().getTypePtr();
+ if (!isa<ArrayType>(CanonicalType))
return 0;
- }
// If this is a typedef for an array type, strip the typedef off without
// losing all typedef information.
@@ -125,8 +121,8 @@ const Type *Type::getArrayElementTypeNoTypeQual() const {
/// decide whether it is worth providing a desugared form of the type
/// or not.
QualType QualType::getDesugaredType(bool ForDisplay) const {
- return getTypePtr()->getDesugaredType(ForDisplay)
- .getWithAdditionalQualifiers(getCVRQualifiers());
+ QualifierCollector Qs;
+ return Qs.apply(Qs.strip(*this)->getDesugaredType(ForDisplay));
}
/// getDesugaredType - Return the specified type with any "sugar" removed from
@@ -181,8 +177,6 @@ QualType Type::getDesugaredType(bool ForDisplay) const {
bool Type::isVoidType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Void;
- if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
- return AS->getBaseType()->isVoidType();
return false;
}
@@ -190,15 +184,11 @@ bool Type::isObjectType() const {
if (isa<FunctionType>(CanonicalType) || isa<ReferenceType>(CanonicalType) ||
isa<IncompleteArrayType>(CanonicalType) || isVoidType())
return false;
- if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
- return AS->getBaseType()->isObjectType();
return true;
}
bool Type::isDerivedType() const {
switch (CanonicalType->getTypeClass()) {
- case ExtQual:
- return cast<ExtQualType>(CanonicalType)->getBaseType()->isDerivedType();
case Pointer:
case VariableArray:
case ConstantArray:
@@ -241,39 +231,19 @@ bool Type::isUnionType() const {
bool Type::isComplexType() const {
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
- if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
- return AS->getBaseType()->isComplexType();
return false;
}
bool Type::isComplexIntegerType() const {
// Check for GCC complex integer extension.
- if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
- return CT->getElementType()->isIntegerType();
- if (const ExtQualType *AS = dyn_cast<ExtQualType>(CanonicalType))
- return AS->getBaseType()->isComplexIntegerType();
- return false;
+ return getAsComplexIntegerType();
}
const ComplexType *Type::getAsComplexIntegerType() const {
- // Are we directly a complex type?
- if (const ComplexType *CTy = dyn_cast<ComplexType>(this)) {
- if (CTy->getElementType()->isIntegerType())
- return CTy;
- return 0;
- }
-
- // If the canonical form of this type isn't what we want, reject it.
- if (!isa<ComplexType>(CanonicalType)) {
- // Look through type qualifiers (e.g. ExtQualType's).
- if (isa<ComplexType>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAsComplexIntegerType();
- return 0;
- }
-
- // If this is a typedef for a complex type, strip the typedef off without
- // losing all typedef information.
- return cast<ComplexType>(getDesugaredType());
+ if (const ComplexType *Complex = getAs<ComplexType>())
+ if (Complex->getElementType()->isIntegerType())
+ return Complex;
+ return 0;
}
QualType Type::getPointeeType() const {
@@ -335,9 +305,6 @@ const RecordType *Type::getAsStructureType() const {
// losing all typedef information.
return cast<RecordType>(getDesugaredType());
}
- // Look through type qualifiers
- if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAsStructureType();
return 0;
}
@@ -358,9 +325,6 @@ const RecordType *Type::getAsUnionType() const {
return cast<RecordType>(getDesugaredType());
}
- // Look through type qualifiers
- if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAsUnionType();
return 0;
}
@@ -416,8 +380,6 @@ bool Type::isIntegerType() const {
return true;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isIntegerType();
return false;
}
@@ -431,24 +393,18 @@ bool Type::isIntegralType() const {
// FIXME: In C++, enum types are never integral.
if (isa<FixedWidthIntType>(CanonicalType))
return true;
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isIntegralType();
return false;
}
bool Type::isEnumeralType() const {
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
return TT->getDecl()->isEnum();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isEnumeralType();
return false;
}
bool Type::isBooleanType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Bool;
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isBooleanType();
return false;
}
@@ -458,16 +414,12 @@ bool Type::isCharType() const {
BT->getKind() == BuiltinType::UChar ||
BT->getKind() == BuiltinType::Char_S ||
BT->getKind() == BuiltinType::SChar;
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isCharType();
return false;
}
bool Type::isWideCharType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::WChar;
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isWideCharType();
return false;
}
@@ -490,8 +442,6 @@ bool Type::isSignedIntegerType() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isSignedIntegerType();
return false;
}
@@ -514,8 +464,6 @@ bool Type::isUnsignedIntegerType() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isUnsignedIntegerType();
return false;
}
@@ -527,8 +475,6 @@ bool Type::isFloatingType() const {
return CT->getElementType()->isFloatingType();
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isFloatingType();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isFloatingType();
return false;
}
@@ -538,8 +484,6 @@ bool Type::isRealFloatingType() const {
BT->getKind() <= BuiltinType::LongDouble;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealFloatingType();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isRealFloatingType();
return false;
}
@@ -553,8 +497,6 @@ bool Type::isRealType() const {
return true;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealType();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isRealType();
return false;
}
@@ -568,8 +510,6 @@ bool Type::isArithmeticType() const {
return ET->getDecl()->isDefinition();
if (isa<FixedWidthIntType>(CanonicalType))
return true;
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isArithmeticType();
return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
}
@@ -583,8 +523,6 @@ bool Type::isScalarType() const {
return true;
return false;
}
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isScalarType();
if (isa<FixedWidthIntType>(CanonicalType))
return true;
return isa<PointerType>(CanonicalType) ||
@@ -611,8 +549,6 @@ bool Type::isAggregateType() const {
return true;
}
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isAggregateType();
return isa<ArrayType>(CanonicalType);
}
@@ -620,8 +556,6 @@ bool Type::isAggregateType() const {
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types or dependent types.
bool Type::isConstantSizeType() const {
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isConstantSizeType();
assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
assert(!isDependentType() && "This doesn't make sense for dependent types");
// The VAT must have a size, as it is known to be complete.
@@ -634,8 +568,6 @@ bool Type::isConstantSizeType() const {
bool Type::isIncompleteType() const {
switch (CanonicalType->getTypeClass()) {
default: return false;
- case ExtQual:
- return cast<ExtQualType>(CanonicalType)->getBaseType()->isIncompleteType();
case Builtin:
// Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never
// be completed.
@@ -664,8 +596,6 @@ bool Type::isPODType() const {
switch (CanonicalType->getTypeClass()) {
// Everything not explicitly mentioned is not POD.
default: return false;
- case ExtQual:
- return cast<ExtQualType>(CanonicalType)->getBaseType()->isPODType();
case VariableArray:
case ConstantArray:
// IncompleteArray is caught by isIncompleteType() above.
@@ -827,21 +757,16 @@ QualType TypedefType::LookThroughTypedefs() const {
return FirstType;
// Otherwise, do the fully general loop.
- unsigned TypeQuals = 0;
- const TypedefType *TDT = this;
- while (1) {
- QualType CurType = TDT->getDecl()->getUnderlyingType();
+ QualifierCollector Qs;
+ QualType CurType;
+ const TypedefType *TDT = this;
+ do {
+ CurType = TDT->getDecl()->getUnderlyingType();
+ TDT = dyn_cast<TypedefType>(Qs.strip(CurType));
+ } while (TDT);
- /// FIXME:
- /// FIXME: This is incorrect for ExtQuals!
- /// FIXME:
- TypeQuals |= CurType.getCVRQualifiers();
-
- TDT = dyn_cast<TypedefType>(CurType);
- if (TDT == 0)
- return QualType(CurType.getTypePtr(), TypeQuals);
- }
+ return Qs.apply(CurType);
}
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
@@ -961,27 +886,20 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
Args[Idx].Profile(ID, Context);
}
-const Type *QualifierSet::strip(const Type* T) {
- QualType DT = T->getDesugaredType();
- addCVR(DT.getCVRQualifiers());
+QualType QualifierCollector::apply(QualType QT) const {
+ if (!hasNonFastQualifiers())
+ return QT.withFastQualifiers(getFastQualifiers());
- if (const ExtQualType* EQT = dyn_cast<ExtQualType>(DT)) {
- if (EQT->getAddressSpace())
- addAddressSpace(EQT->getAddressSpace());
- if (EQT->getObjCGCAttr())
- addObjCGCAttrType(EQT->getObjCGCAttr());
- return EQT->getBaseType();
- } else {
- // Use the sugared type unless desugaring found extra qualifiers.
- return (DT.getCVRQualifiers() ? DT.getTypePtr() : T);
- }
+ assert(Context && "extended qualifiers but no context!");
+ return Context->getQualifiedType(QT, *this);
}
-QualType QualifierSet::apply(QualType QT, ASTContext& C) {
- QT = QT.getWithAdditionalQualifiers(getCVRMask());
- if (hasObjCGCAttrType()) QT = C.getObjCGCQualType(QT, getObjCGCAttrType());
- if (hasAddressSpace()) QT = C.getAddrSpaceQualType(QT, getAddressSpace());
- return QT;
+QualType QualifierCollector::apply(const Type *T) const {
+ if (!hasNonFastQualifiers())
+ return QualType(T, getFastQualifiers());
+
+ assert(Context && "extended qualifiers but no context!");
+ return Context->getQualifiedType(T, *this);
}
@@ -1012,14 +930,46 @@ void Type::dump() const {
static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
- // Note: funkiness to ensure we get a space only between quals.
- bool NonePrinted = true;
- if (TypeQuals & QualType::Const)
- S += "const", NonePrinted = false;
- if (TypeQuals & QualType::Volatile)
- S += (NonePrinted+" volatile"), NonePrinted = false;
- if (TypeQuals & QualType::Restrict)
- S += (NonePrinted+" restrict"), NonePrinted = false;
+ if (TypeQuals & Qualifiers::Const) {
+ if (!S.empty()) S += ' ';
+ S += "const";
+ }
+ if (TypeQuals & Qualifiers::Volatile) {
+ if (!S.empty()) S += ' ';
+ S += "volatile";
+ }
+ if (TypeQuals & Qualifiers::Restrict) {
+ if (!S.empty()) S += ' ';
+ S += "restrict";
+ }
+}
+
+std::string Qualifiers::getAsString() const {
+ LangOptions LO;
+ return getAsString(PrintingPolicy(LO));
+}
+
+// Appends qualifiers to the given string, separated by spaces. Will
+// prefix a space if the string is non-empty. Will not append a final
+// space.
+void Qualifiers::getAsStringInternal(std::string &S,
+ const PrintingPolicy&) const {
+ AppendTypeQualList(S, getCVRQualifiers());
+ if (unsigned AddressSpace = getAddressSpace()) {
+ if (!S.empty()) S += ' ';
+ S += "__attribute__((address_space(";
+ S += llvm::utostr_32(AddressSpace);
+ S += ")))";
+ }
+ if (Qualifiers::GC GCAttrType = getObjCGCAttr()) {
+ if (!S.empty()) S += ' ';
+ S += "__attribute__((objc_gc(";
+ if (GCAttrType == Qualifiers::Weak)
+ S += "weak";
+ else
+ S += "strong";
+ S += ")))";
+ }
}
std::string QualType::getAsString() const {
@@ -1041,13 +991,16 @@ QualType::getAsStringInternal(std::string &S,
return;
// Print qualifiers as appropriate.
- if (unsigned Tq = getCVRQualifiers()) {
+ Qualifiers Quals = getQualifiers();
+ if (!Quals.empty()) {
std::string TQS;
- AppendTypeQualList(TQS, Tq);
- if (!S.empty())
- S = TQS + ' ' + S;
- else
- S = TQS;
+ Quals.getAsStringInternal(TQS, Policy);
+
+ if (!S.empty()) {
+ TQS += ' ';
+ TQS += S;
+ }
+ std::swap(S, TQS);
}
getTypePtr()->getAsStringInternal(S, Policy);
@@ -1084,25 +1037,6 @@ void ComplexType::getAsStringInternal(std::string &S, const PrintingPolicy &Poli
S = "_Complex " + S;
}
-void ExtQualType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- bool NeedsSpace = false;
- if (AddressSpace) {
- S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S;
- NeedsSpace = true;
- }
- if (GCAttrType != QualType::GCNone) {
- if (NeedsSpace)
- S += ' ';
- S += "__attribute__((objc_gc(";
- if (GCAttrType == QualType::Weak)
- S += "weak";
- else
- S += "strong";
- S += ")))";
- }
- BaseType->getAsStringInternal(S, Policy);
-}
-
void PointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
S = '*' + S;
@@ -1195,8 +1129,8 @@ void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPoli
void VariableArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
S += '[';
- if (getIndexTypeQualifier()) {
- AppendTypeQualList(S, getIndexTypeQualifier());
+ if (getIndexTypeQualifiers().hasQualifiers()) {
+ AppendTypeQualList(S, getIndexTypeCVRQualifiers());
S += ' ';
}
@@ -1219,8 +1153,8 @@ void VariableArrayType::getAsStringInternal(std::string &S, const PrintingPolicy
void DependentSizedArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
S += '[';
- if (getIndexTypeQualifier()) {
- AppendTypeQualList(S, getIndexTypeQualifier());
+ if (getIndexTypeQualifiers().hasQualifiers()) {
+ AppendTypeQualList(S, getIndexTypeCVRQualifiers());
S += ' ';
}
@@ -1536,6 +1470,9 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
}
ObjCQIString += '>';
}
+
+ PointeeType.getQualifiers().getAsStringInternal(ObjCQIString, Policy);
+
if (!isObjCIdType() && !isObjCQualifiedIdType())
ObjCQIString += " *"; // Don't forget the implicit pointer.
else if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 0a0d29169f1..8934a676144 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -1686,8 +1686,8 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
// FIXME: This is really ugly; should be refactored somehow
unsigned idx = CGM.getTypes().getLLVMFieldNo(Field);
llvm::Value *V = Builder.CreateStructGEP(LoadOfThis, idx, "tmp");
- LHS = LValue::MakeAddr(V, FieldType.getCVRQualifiers(),
- QualType::GCNone, FieldType.getAddressSpace());
+ assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
+ LHS = LValue::MakeAddr(V, MakeQualifiers(FieldType));
} else {
LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
}
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 1dbb6e67f26..0b9b3fc2708 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -629,7 +629,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
(Name + ".addr").c_str());
// FIXME: What are the right qualifiers here?
llvm::Function::arg_iterator End =
- ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp,0), AI);
+ ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
EmitParmDecl(*Arg, Temp);
// Name the arguments used in expansion and increment AI.
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 0074316b4c2..197fcac150f 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -788,7 +788,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
case Type::RValueReference:
case Type::Vector:
case Type::ExtVector:
- case Type::ExtQual:
case Type::FixedWidthInt:
case Type::MemberPointer:
case Type::TemplateSpecialization:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index a7eebbf1fd1..309f38e080a 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -166,9 +166,7 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
ErrorUnsupported(E, Name);
llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
return LValue::MakeAddr(llvm::UndefValue::get(Ty),
- E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ MakeQualifiers(E->getType()));
}
/// EmitLValue - Emit code to compute a designator that specifies the location
@@ -746,17 +744,16 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
- LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
} else {
llvm::Value *V = LocalDeclMap[VD];
assert(V && "DeclRefExpr not entered in LocalDeclMap?");
+
+ Qualifiers Quals = MakeQualifiers(E->getType());
// local variables do not get their gc attribute set.
- QualType::GCAttrTypes attr = QualType::GCNone;
// local static?
- if (!NonGCable)
- attr = getContext().getObjCGCAttrKind(E->getType());
+ if (NonGCable) Quals.removeObjCGCAttr();
+
if (VD->hasAttr<BlocksAttr>()) {
V = Builder.CreateStructGEP(V, 1, "forwarding");
V = Builder.CreateLoad(V, false);
@@ -765,8 +762,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
- LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), attr,
- E->getType().getAddressSpace());
+ LV = LValue::MakeAddr(V, Quals);
}
LValue::SetObjCNonGC(LV, NonGCable);
setObjCGCLValueClass(getContext(), E, LV);
@@ -775,9 +771,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
- LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
setObjCGCLValueClass(getContext(), E, LV);
return LV;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
@@ -794,16 +788,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
V = Builder.CreateBitCast(V, ConvertType(NoProtoType), "tmp");
}
}
- return LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
} else if (const ImplicitParamDecl *IPD =
dyn_cast<ImplicitParamDecl>(E->getDecl())) {
llvm::Value *V = LocalDeclMap[IPD];
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
- return LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
}
assert(0 && "Unimp declref");
//an invalid LValue, but the assert will
@@ -812,10 +802,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) {
- return LValue::MakeAddr(GetAddrOfBlockDecl(E),
- E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(GetAddrOfBlockDecl(E), MakeQualifiers(E->getType()));
}
LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
@@ -831,10 +818,10 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
QualType T = E->getSubExpr()->getType()->getPointeeType();
assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
- LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()),
- T.getCVRQualifiers(),
- getContext().getObjCGCAttrKind(T),
- ExprTy.getAddressSpace());
+ Qualifiers Quals = MakeQualifiers(T);
+ Quals.setAddressSpace(ExprTy.getAddressSpace());
+
+ LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals);
// We should not generate __weak write barrier on indirect reference
// of a pointer to object; as in void foo (__weak id *param); *param = 0;
// But, we continue to generate __strong write barrier on indirect write
@@ -851,18 +838,18 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
unsigned Idx = E->getOpcode() == UnaryOperator::Imag;
return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(),
Idx, "idx"),
- ExprTy.getCVRQualifiers(),
- QualType::GCNone,
- ExprTy.getAddressSpace());
+ MakeQualifiers(ExprTy));
}
}
LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
- return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), 0);
+ return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E),
+ Qualifiers());
}
LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
- return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E), 0);
+ return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E),
+ Qualifiers());
}
@@ -894,7 +881,7 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
llvm::Constant *C =
CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str());
- return LValue::MakeAddr(C, 0);
+ return LValue::MakeAddr(C, Qualifiers());
}
LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
@@ -923,7 +910,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
Idx = Builder.CreateIntCast(Idx,
llvm::Type::getInt32Ty(VMContext), IdxSigned, "vidx");
return LValue::MakeVectorElt(LHS.getAddress(), Idx,
- E->getBase()->getType().getCVRQualifiers());
+ E->getBase()->getType().getCVRQualifiers());
}
// The base must be a pointer, which is not an aggregate. Emit it.
@@ -973,10 +960,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
assert(!T.isNull() &&
"CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type");
- LValue LV = LValue::MakeAddr(Address,
- T.getCVRQualifiers(),
- getContext().getObjCGCAttrKind(T),
- E->getBase()->getType().getAddressSpace());
+ Qualifiers Quals = MakeQualifiers(T);
+ Quals.setAddressSpace(E->getBase()->getType().getAddressSpace());
+
+ LValue LV = LValue::MakeAddr(Address, Quals);
if (getContext().getLangOptions().ObjC1 &&
getContext().getLangOptions().getGCMode() != LangOptions::NonGC) {
LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
@@ -1009,9 +996,9 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
} else {
const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
llvm::Value *Ptr = EmitScalarExpr(E->getBase());
- Base = LValue::MakeAddr(Ptr, PT->getPointeeType().getCVRQualifiers(),
- QualType::GCNone,
- PT->getPointeeType().getAddressSpace());
+ Qualifiers Quals = MakeQualifiers(PT->getPointeeType());
+ Quals.removeObjCGCAttr();
+ Base = LValue::MakeAddr(Ptr, Quals);
}
// Encode the element access list into a vector of unsigned indices.
@@ -1021,7 +1008,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
if (Base.isSimple()) {
llvm::Constant *CV = GenerateConstantVector(VMContext, Indices);
return LValue::MakeExtVectorElt(Base.getAddress(), CV,
- Base.getQualifiers());
+ Base.getVRQualifiers());
}
assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
@@ -1037,7 +1024,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
}
llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size());
return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV,
- Base.getQualifiers());
+ Base.getVRQualifiers());
}
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
@@ -1045,7 +1032,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
bool isNonGC = false;
Expr *BaseExpr = E->getBase();
llvm::Value *BaseValue = NULL;
- unsigned CVRQualifiers=0;
+ Qualifiers BaseQuals;
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
if (E->isArrow()) {
@@ -1054,7 +1041,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
BaseExpr->getType()->getAs<PointerType>();
if (PTy->getPointeeType()->isUnionType())
isUnion = true;
- CVRQualifiers = PTy->getPointeeType().getCVRQualifiers();
+ BaseQuals = PTy->getPointeeType().getQualifiers();
} else if (isa<ObjCPropertyRefExpr>(BaseExpr->IgnoreParens()) ||
isa<ObjCImplicitSetterGetterRefExpr>(
BaseExpr->IgnoreParens())) {
@@ -1062,7 +1049,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
BaseValue = RV.getAggregateAddr();
if (BaseExpr->getType()->isUnionType())
isUnion = true;
- CVRQualifiers = BaseExpr->getType().getCVRQualifiers();
+ BaseQuals = BaseExpr->getType().getQualifiers();
} else {
LValue BaseLV = EmitLValue(BaseExpr);
if (BaseLV.isNonGC())
@@ -1072,14 +1059,14 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
QualType BaseTy = BaseExpr->getType();
if (BaseTy->isUnionType())
isUnion = true;
- CVRQualifiers = BaseTy.getCVRQualifiers();
+ BaseQuals = BaseTy.getQualifiers();
}
FieldDecl *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
// FIXME: Handle non-field member expressions
assert(Field && "No code generation for non-field member references");
LValue MemExpLV = EmitLValueForField(BaseValue, Field, isUnion,
- CVRQualifiers);
+ BaseQuals.getCVRQualifiers());
LValue::SetObjCNonGC(MemExpLV, isNonGC);
setObjCGCLValueClass(getContext(), E, MemExpLV);
return MemExpLV;
@@ -1133,17 +1120,14 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
}
if (Field->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
- QualType::GCAttrTypes attr = getContext().getObjCGCAttrKind(Field->getType());
+
+ Qualifiers Quals = MakeQualifiers(Field->getType());
+ Quals.addCVRQualifiers(CVRQualifiers);
// __weak attribute on a field is ignored.
- if (attr == QualType::Weak)
- attr = QualType::GCNone;
+ if (Quals.getObjCGCAttr() == Qualifiers::Weak)
+ Quals.removeObjCGCAttr();
- LValue LV =
- LValue::MakeAddr(V,
- Field->getType().getCVRQualifiers()|CVRQualifiers,
- attr,
- Field->getType().getAddressSpace());
- return LV;
+ return LValue::MakeAddr(V, Quals);
}
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
@@ -1151,9 +1135,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral");
const Expr* InitExpr = E->getInitializer();
- LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers(),
- QualType::GCNone,
- E->getType().getAddressSpace());
+ LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType()));
if (E->getType()->isComplexType()) {
EmitComplexExprIntoAddr(InitExpr, DeclPtr, false);
@@ -1199,9 +1181,7 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
EmitBlock(ContBlock);
Temp = Builder.CreateLoad(Temp, "lv");
- return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
}
// ?: here should be an aggregate.
@@ -1212,9 +1192,7 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAggExpr(E, Temp, false);
- return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
}
/// EmitCastLValue - Casts are never lvalues. If a cast is needed by the code
@@ -1254,18 +1232,14 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
GetAddressCXXOfBaseClass(LV.getAddress(), DerivedClassDecl,
BaseClassDecl, /*NullCheckValue=*/false);
- return LValue::MakeAddr(Base, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(Base, MakeQualifiers(E->getType()));
}
case CastExpr::CK_ToUnion: {
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAnyExpr(E->getSubExpr(), Temp, false);
- return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
}
}
}
@@ -1327,9 +1301,7 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAggExpr(E, Temp, false);
// FIXME: Are these qualifiers correct?
- return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
}
LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
@@ -1340,23 +1312,17 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
"Can't have a scalar return unless the return type is a "
"reference type!");
- return LValue::MakeAddr(RV.getScalarVal(), E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
}
- return LValue::MakeAddr(RV.getAggregateAddr(),
- E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
}
LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
// FIXME: This shouldn't require another copy.
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAggExpr(E, Temp, false);
- return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
- QualType::GCNone, E->getType().getAddressSpace());
+ return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
}
LValue
@@ -1368,8 +1334,7 @@ CodeGenFunction::EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E) {
LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "tmp");
EmitCXXConstructExpr(Temp, E);
- return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(),
- QualType::GCNone, E->getType().getAddressSpace());
+ return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
}
LValue
@@ -1385,10 +1350,7 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
// Can only get l-value for message expression returning aggregate type
RValue RV = EmitObjCMessageExpr(E);
// FIXME: can this be volatile?
- return LValue::MakeAddr(RV.getAggregateAddr(),
- E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
}
llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
@@ -1408,22 +1370,23 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
// FIXME: A lot of the code below could be shared with EmitMemberExpr.
llvm::Value *BaseValue = 0;
const Expr *BaseExpr = E->getBase();
- unsigned CVRQualifiers = 0;
+ Qualifiers BaseQuals;
QualType ObjectTy;
if (E->isArrow()) {
BaseValue = EmitScalarExpr(BaseExpr);
ObjectTy = BaseExpr->getType()->getPointeeType();
- CVRQualifiers = ObjectTy.getCVRQualifiers();
+ BaseQuals = ObjectTy.getQualifiers();
} else {
LValue BaseLV = EmitLValue(BaseExpr);
// FIXME: this isn't right for bitfields.
BaseValue = BaseLV.getAddress();
ObjectTy = BaseExpr->getType();
- CVRQualifiers = ObjectTy.getCVRQualifiers();
+ BaseQuals = ObjectTy.getQualifiers();
}
LValue LV =
- EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), CVRQualifiers);
+ EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(),
+ BaseQuals.getCVRQualifiers());
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
@@ -1453,10 +1416,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
// Can only get l-value for message expression returning aggregate type
RValue RV = EmitAnyExprToTemp(E);
// FIXME: can this be volatile?
- return LValue::MakeAddr(RV.getAggregateAddr(),
- E->getType().getCVRQualifiers(),
- getContext().getObjCGCAttrKind(E->getType()),
- E->getType().getAddressSpace());
+ return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 2e7e8686169..e19fb0065fc 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -181,7 +181,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
llvm::Value *CastPtr = Builder.CreateBitCast(DestPtr,
CGF.ConvertType(PtrTy));
EmitInitializationToLValue(E->getSubExpr(),
- LValue::MakeAddr(CastPtr, 0));
+ LValue::MakeAddr(CastPtr, Qualifiers()));
return;
}
@@ -316,7 +316,7 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
return;
}
- EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, 0));
+ EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, Qualifiers()));
}
void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
@@ -429,15 +429,16 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType();
- unsigned CVRqualifier = ElementType.getCVRQualifiers();
+ // FIXME: were we intentionally ignoring address spaces and GC attributes?
+ Qualifiers Quals = CGF.MakeQualifiers(ElementType);
for (uint64_t i = 0; i != NumArrayElements; ++i) {
llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
if (i < NumInitElements)
EmitInitializationToLValue(E->getInit(i),
- LValue::MakeAddr(NextVal, CVRqualifier));
+ LValue::MakeAddr(NextVal, Quals));
else
- EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, CVRqualifier),
+ EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, Quals),
ElementType);
}
return;
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index b9569f589b3..21b45583e5a 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -791,8 +791,7 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr");
llvm::Value *lhs = LV.getAddress();
lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty));
- LV = LValue::MakeAddr(lhs, ValTy.getCVRQualifiers(),
- CGF.getContext().getObjCGCAttrKind(ValTy));
+ LV = LValue::MakeAddr(lhs, CGF.MakeQualifiers(ValTy));
} else
NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec");
} else {
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index df6058303a1..b9f4f3471c9 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -112,6 +112,9 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
+ Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
+ Quals.addCVRQualifiers(CVRQualifiers);
+
if (Ivar->isBitField()) {
// We need to compute the bit offset for the bit-field, the offset
// is to the byte. Note, there is a subtle invariant here: we can
@@ -124,11 +127,11 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
return LValue::MakeBitfield(V, BitOffset, BitFieldSize,
IvarTy->isSignedIntegerType(),
- IvarTy.getCVRQualifiers()|CVRQualifiers);
+ Quals.getCVRQualifiers());
}
- LValue LV = LValue::MakeAddr(V, IvarTy.getCVRQualifiers()|CVRQualifiers,
- CGF.CGM.getContext().getObjCGCAttrKind(IvarTy));
+
+ LValue LV = LValue::MakeAddr(V, Quals);
return LV;
}
@@ -2992,21 +2995,20 @@ llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
}
-static QualType::GCAttrTypes GetGCAttrTypeForType(ASTContext &Ctx,
- QualType FQT) {
+static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
if (FQT.isObjCGCStrong())
- return QualType::Strong;
+ return Qualifiers::Strong;
if (FQT.isObjCGCWeak())
- return QualType::Weak;
+ return Qualifiers::Weak;
if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
- return QualType::Strong;
+ return Qualifiers::Strong;
if (const PointerType *PT = FQT->getAs<PointerType>())
return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
- return QualType::GCNone;
+ return Qualifiers::GCNone;
}
void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
@@ -3123,11 +3125,11 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
}
// At this point, we are done with Record/Union and array there of.
// For other arrays we are down to its element type.
- QualType::GCAttrTypes GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
+ Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
- if ((ForStrongLayout && GCAttr == QualType::Strong)
- || (!ForStrongLayout && GCAttr == QualType::Weak)) {
+ if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
+ || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
if (IsUnion) {
uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
if (UnionIvarSize > MaxUnionIvarSize) {
@@ -3140,8 +3142,8 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
FieldSize / WordSizeInBits));
}
} else if ((ForStrongLayout &&
- (GCAttr == QualType::GCNone || GCAttr == QualType::Weak))
- || (!ForStrongLayout && GCAttr != QualType::Weak)) {
+ (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
+ || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
if (IsUnion) {
// FIXME: Why the asymmetry? We divide by word size in bits on other
// side.
diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h
index d9dd94d4a63..ee9dc524c6e 100644
--- a/clang/lib/CodeGen/CGValue.h
+++ b/clang/lib/CodeGen/CGValue.h
@@ -118,12 +118,6 @@ class LValue {
// use getKVCRefExpr
} LVType;
- enum ObjCType {
- None = 0, // object with no gc attribute.
- Weak, // __weak object expression
- Strong // __strong object expression
- };
-
llvm::Value *V;
union {
@@ -146,9 +140,8 @@ class LValue {
const ObjCImplicitSetterGetterRefExpr *KVCRefExpr;
};
- bool Volatile:1;
- // FIXME: set but never used, what effect should it have?
- bool Restrict:1;
+ // 'const' is unused here
+ Qualifiers Quals;
// objective-c's ivar
bool Ivar:1;
@@ -163,20 +156,13 @@ class LValue {
// Lvalue is a global reference of an objective-c object
bool GlobalObjCRef : 1;
- // objective-c's gc attributes
- unsigned ObjCType : 2;
-
- // address space
- unsigned AddressSpace;
-
private:
- static void SetQualifiers(unsigned Qualifiers, LValue& R) {
- R.Volatile = (Qualifiers&QualType::Volatile)!=0;
- R.Restrict = (Qualifiers&QualType::Restrict)!=0;
+ void SetQualifiers(Qualifiers Quals) {
+ this->Quals = Quals;
+
// FIXME: Convenient place to set objc flags to 0. This should really be
// done in a user-defined constructor instead.
- R.ObjCType = None;
- R.Ivar = R.ObjIsArray = R.NonGC = R.GlobalObjCRef = false;
+ this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
}
public:
@@ -187,21 +173,20 @@ public:
bool isPropertyRef() const { return LVType == PropertyRef; }
bool isKVCRef() const { return LVType == KVCRef; }
- bool isVolatileQualified() const { return Volatile; }
- bool isRestrictQualified() const { return Restrict; }
- unsigned getQualifiers() const {
- return (Volatile ? QualType::Volatile : 0) |
- (Restrict ? QualType::Restrict : 0);
+ bool isVolatileQualified() const { return Quals.hasVolatile(); }
+ bool isRestrictQualified() const { return Quals.hasRestrict(); }
+ unsigned getVRQualifiers() const {
+ return Quals.getCVRQualifiers() & ~Qualifiers::Const;
}
bool isObjCIvar() const { return Ivar; }
bool isObjCArray() const { return ObjIsArray; }
bool isNonGC () const { return NonGC; }
bool isGlobalObjCRef() const { return GlobalObjCRef; }
- bool isObjCWeak() const { return ObjCType == Weak; }
- bool isObjCStrong() const { return ObjCType == Strong; }
+ bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; }
+ bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; }
- unsigned getAddressSpace() const { return AddressSpace; }
+ unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
static void SetObjCIvar(LValue& R, bool iValue) {
R.Ivar = iValue;
@@ -216,14 +201,6 @@ public:
static void SetObjCNonGC(LValue& R, bool iValue) {
R.NonGC = iValue;
}
- static void SetObjCType(QualType::GCAttrTypes GCAttrs, LValue& R) {
- if (GCAttrs == QualType::Weak)
- R.ObjCType = Weak;
- else if (GCAttrs == QualType::Strong)
- R.ObjCType = Strong;
- else
- R.ObjCType = None;
- }
// simple lvalue
llvm::Value *getAddress() const { assert(isSimple()); return V; }
@@ -262,48 +239,44 @@ public:
return KVCRefExpr;
}
- static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers,
- QualType::GCAttrTypes GCAttrs = QualType::GCNone,
- unsigned AddressSpace = 0) {
+ static LValue MakeAddr(llvm::Value *V, Qualifiers Quals) {
LValue R;
R.LVType = Simple;
R.V = V;
- SetQualifiers(Qualifiers,R);
- R.AddressSpace = AddressSpace;
- SetObjCType(GCAttrs, R);
+ R.SetQualifiers(Quals);
return R;
}
static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx,
- unsigned Qualifiers) {
+ unsigned CVR) {
LValue R;
R.LVType = VectorElt;
R.V = Vec;
R.VectorIdx = Idx;
- SetQualifiers(Qualifiers,R);
+ R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
return R;
}
static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts,
- unsigned Qualifiers) {
+ unsigned CVR) {
LValue R;
R.LVType = ExtVectorElt;
R.V = Vec;
R.VectorElts = Elts;
- SetQualifiers(Qualifiers,R);
+ R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
return R;
}
static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit,
unsigned short Size, bool IsSigned,
- unsigned Qualifiers) {
+ unsigned CVR) {
LValue R;
R.LVType = BitField;
R.V = V;
R.BitfieldData.StartBit = StartBit;
R.BitfieldData.Size = Size;
R.BitfieldData.IsSigned = IsSigned;
- SetQualifiers(Qualifiers,R);
+ R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
return R;
}
@@ -311,20 +284,20 @@ public:
// the lvalue. However, this complicates the code a bit, and I haven't figured
// out how to make it go wrong yet.
static LValue MakePropertyRef(const ObjCPropertyRefExpr *E,
- unsigned Qualifiers) {
+ unsigned CVR) {
LValue R;
R.LVType = PropertyRef;
R.PropertyRefExpr = E;
- SetQualifiers(Qualifiers,R);
+ R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
return R;
}
static LValue MakeKVCRef(const ObjCImplicitSetterGetterRefExpr *E,
- unsigned Qualifiers) {
+ unsigned CVR) {
LValue R;
R.LVType = KVCRef;
R.KVCRefExpr = E;
- SetQualifiers(Qualifiers,R);
+ R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
return R;
}
};
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 651dc951774..6b6b1494e49 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -496,6 +496,12 @@ public:
// Helpers
//===--------------------------------------------------------------------===//
+ Qualifiers MakeQualifiers(QualType T) {
+ Qualifiers Quals = T.getQualifiers();
+ Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T));
+ return Quals;
+ }
+
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 6826122ad98..87b3d1144f4 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -267,7 +267,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
case Type::VariableArray: {
const VariableArrayType &A = cast<VariableArrayType>(Ty);
- assert(A.getIndexTypeQualifier() == 0 &&
+ assert(A.getIndexTypeCVRQualifiers() == 0 &&
"FIXME: We only handle trivial array types so far!");
// VLAs resolve to the innermost element type; this matches
// the return of alloca, and there isn't any obviously better choice.
@@ -275,7 +275,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
}
case Type::IncompleteArray: {
const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty);
- assert(A.getIndexTypeQualifier() == 0 &&
+ assert(A.getIndexTypeCVRQualifiers() == 0 &&
"FIXME: We only handle trivial array types so far!");
// int X[] -> [0 x int]
return llvm::ArrayType::get(ConvertTypeForMemRecursive(A.getElementType()), 0);
@@ -312,10 +312,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
return GetFunctionType(getFunctionInfo(FNPT), true);
}
- case Type::ExtQual:
- return
- ConvertTypeRecursive(QualType(cast<ExtQualType>(Ty).getBaseType(), 0));
-
case Type::ObjCInterface: {
// Objective-C interfaces are always opaque (outside of the
// runtime, which can do whatever it likes); we never refine
diff --git a/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp
index 878f13d516d..83dc0e64dcf 100644
--- a/clang/lib/CodeGen/Mangle.cpp
+++ b/clang/lib/CodeGen/Mangle.cpp
@@ -84,7 +84,7 @@ namespace {
void manglePrefix(const DeclContext *DC);
void mangleTemplatePrefix(const NamedDecl *ND);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
- void mangleCVQualifiers(unsigned Quals);
+ void mangleQualifiers(Qualifiers Quals);
void mangleType(QualType T);
// Declare manglers for every type class.
@@ -459,7 +459,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND) {
// FIXME: no class template support
Out << 'N';
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND))
- mangleCVQualifiers(Method->getTypeQualifiers());
+ mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = 0;
@@ -637,14 +637,16 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
}
}
-void CXXNameMangler::mangleCVQualifiers(unsigned Quals) {
+void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
// <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
- if (Quals & QualType::Restrict)
+ if (Quals.hasRestrict())
Out << 'r';
- if (Quals & QualType::Volatile)
+ if (Quals.hasVolatile())
Out << 'V';
- if (Quals & QualType::Const)
+ if (Quals.hasConst())
Out << 'K';
+
+ // FIXME: For now, just drop all extension qualifiers on the floor.
}
void CXXNameMangler::mangleType(QualType T) {
@@ -655,10 +657,10 @@ void CXXNameMangler::mangleType(QualType T) {
if (IsSubstitutable && mangleSubstitution(T))
return;
- if (unsigned CVRQualifiers = T.getCVRQualifiers()) {
- // <type> ::= <CV-qualifiers> <type>
- mangleCVQualifiers(CVRQualifiers);
-
+ if (Qualifiers Quals = T.getQualifiers()) {
+ mangleQualifiers(Quals);
+ // Recurse: even if the qualified type isn't yet substitutable,
+ // the unqualified type might be.
mangleType(T.getUnqualifiedType());
} else {
switch (T->getTypeClass()) {
@@ -669,7 +671,7 @@ void CXXNameMangler::mangleType(QualType T) {
return;
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
- mangleType(static_cast<CLASS##Type*>(T.getTypePtr())); \
+ mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \
break;
#include "clang/AST/TypeNodes.def"
}
@@ -830,7 +832,7 @@ void CXXNameMangler::mangleType(const MemberPointerType *T) {
mangleType(QualType(T->getClass(), 0));
QualType PointeeType = T->getPointeeType();
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
- mangleCVQualifiers(FPT->getTypeQuals());
+ mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals()));
mangleType(FPT);
} else
mangleType(PointeeType);
@@ -912,11 +914,6 @@ void CXXNameMangler::mangleType(const TypenameType *T) {
assert(false && "can't mangle dependent typenames yet");
}
-// FIXME: For now, just drop all extension qualifiers on the floor.
-void CXXNameMangler::mangleType(const ExtQualType *T) {
- mangleType(QualType(T->getBaseType(), 0));
-}
-
void CXXNameMangler::mangleExpression(const Expr *E) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
diff --git a/clang/lib/Frontend/DocumentXML.cpp b/clang/lib/Frontend/DocumentXML.cpp
index a6af2f8ecfa..d92d4cb7b8d 100644
--- a/clang/lib/Frontend/DocumentXML.cpp
+++ b/clang/lib/Frontend/DocumentXML.cpp
@@ -135,7 +135,7 @@ void DocumentXML::finalize() {
for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
i != e; ++i) {
- if (i->first.getCVRQualifiers() != 0) {
+ if (i->first.hasQualifiers()) {
writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
@@ -205,7 +205,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
{
addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
- if (pType.getCVRQualifiers() == 0)
+ if (!pType.hasQualifiers())
{
Types[pType] = BasicTypes[pType.getTypePtr()];
}
diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp
index c493e39776b..73c0b8d9911 100644
--- a/clang/lib/Frontend/PCHReader.cpp
+++ b/clang/lib/Frontend/PCHReader.cpp
@@ -1764,18 +1764,11 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
unsigned Code = Stream.ReadCode();
switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
case pch::TYPE_EXT_QUAL: {
- assert(Record.size() == 3 &&
+ assert(Record.size() == 2 &&
"Incorrect encoding of extended qualifier type");
QualType Base = GetType(Record[0]);
- QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1];
- unsigned AddressSpace = Record[2];
-
- QualType T = Base;
- if (GCAttr != QualType::GCNone)
- T = Context->getObjCGCQualType(T, GCAttr);
- if (AddressSpace)
- T = Context->getAddrSpaceQualType(T, AddressSpace);
- return T;
+ Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
+ return Context->getQualifiedType(Base, Quals);
}
case pch::TYPE_FIXED_WIDTH_INT: {
@@ -1984,8 +1977,8 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
QualType PCHReader::GetType(pch::TypeID ID) {
- unsigned Quals = ID & 0x07;
- unsigned Index = ID >> 3;
+ unsigned FastQuals = ID & Qualifiers::FastMask;
+ unsigned Index = ID >> Qualifiers::FastWidth;
if (Index < pch::NUM_PREDEF_TYPE_IDS) {
QualType T;
@@ -2026,15 +2019,15 @@ QualType PCHReader::GetType(pch::TypeID ID) {
}
assert(!T.isNull() && "Unknown predefined type");
- return T.getQualifiedType(Quals);
+ return T.withFastQualifiers(FastQuals);
}
Index -= pch::NUM_PREDEF_TYPE_IDS;
//assert(Index < TypesLoaded.size() && "Type index out-of-range");
- if (!TypesLoaded[Index])
- TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
+ if (TypesLoaded[Index].isNull())
+ TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]);
- return QualType(TypesLoaded[Index], Quals);
+ return TypesLoaded[Index].withFastQualifiers(FastQuals);
}
Decl *PCHReader::GetDecl(pch::DeclID ID) {
@@ -2155,7 +2148,7 @@ void PCHReader::PrintStats() {
unsigned NumTypesLoaded
= TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
- (Type *)0);
+ QualType());
unsigned NumDeclsLoaded
= DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
(Decl *)0);
diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp
index 531c6f78184..8ef846f7672 100644
--- a/clang/lib/Frontend/PCHWriter.cpp
+++ b/clang/lib/Frontend/PCHWriter.cpp
@@ -64,13 +64,6 @@ namespace {
};
}
-void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) {
- Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record);
- Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values
- Record.push_back(T->getAddressSpace());
- Code = pch::TYPE_EXT_QUAL;
-}
-
void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
assert(false && "Built-in types are never serialized");
}
@@ -115,7 +108,7 @@ void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
Writer.AddTypeRef(T->getElementType(), Record);
Record.push_back(T->getSizeModifier()); // FIXME: stable values
- Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values
+ Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
}
void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
@@ -1087,7 +1080,7 @@ void PCHWriter::WriteComments(ASTContext &Context) {
//===----------------------------------------------------------------------===//
/// \brief Write the representation of a type to the PCH stream.
-void PCHWriter::WriteType(const Type *T) {
+void PCHWriter::WriteType(QualType T) {
pch::TypeID &ID = TypeIDs[T];
if (ID == 0) // we haven't seen this type before.
ID = NextTypeID++;
@@ -1104,22 +1097,30 @@ void PCHWriter::WriteType(const Type *T) {
// Emit the type's representation.
PCHTypeWriter W(*this, Record);
- switch (T->getTypeClass()) {
- // For all of the concrete, non-dependent types, call the
- // appropriate visitor function.
+
+ if (T.hasNonFastQualifiers()) {
+ Qualifiers Qs = T.getQualifiers();
+ AddTypeRef(T.getUnqualifiedType(), Record);
+ Record.push_back(Qs.getAsOpaqueValue());
+ W.Code = pch::TYPE_EXT_QUAL;
+ } else {
+ switch (T->getTypeClass()) {
+ // For all of the concrete, non-dependent types, call the
+ // appropriate visitor function.
#define TYPE(Class, Base) \
- case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
+ case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break;
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
- // For all of the dependent type nodes (which only occur in C++
- // templates), produce an error.
+ // For all of the dependent type nodes (which only occur in C++
+ // templates), produce an error.
#define TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
- assert(false && "Cannot serialize dependent type nodes");
- break;
+ assert(false && "Cannot serialize dependent type nodes");
+ break;
+ }
}
// Emit the serialized record.
@@ -1136,9 +1137,8 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) {
// Emit all of the types that need to be emitted (so far).
while (!TypesToEmit.empty()) {
- const Type *T = TypesToEmit.front();
+ QualType T = TypesToEmit.front();
TypesToEmit.pop();
- assert(!isa<BuiltinType>(T) && "Built-in types are not serialized");
WriteType(T);
}
@@ -1975,6 +1975,26 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
return;
}
+ unsigned FastQuals = T.getFastQualifiers();
+ T.removeFastQualifiers();
+
+ if (T.hasNonFastQualifiers()) {
+ pch::TypeID &ID = TypeIDs[T];
+ if (ID == 0) {
+ // We haven't seen these qualifiers applied to this type before.
+ // Assign it a new ID. This is the only time we enqueue a
+ // qualified type, and it has no CV qualifiers.
+ ID = NextTypeID++;
+ TypesToEmit.push(T);
+ }
+
+ // Encode the type qualifiers in the type reference.
+ Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
+ return;
+ }
+
+ assert(!T.hasQualifiers());
+
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
pch::TypeID ID = 0;
switch (BT->getKind()) {
@@ -2010,20 +2030,20 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
break;
}
- Record.push_back((ID << 3) | T.getCVRQualifiers());
+ Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
return;
}
- pch::TypeID &ID = TypeIDs[T.getTypePtr()];
+ pch::TypeID &ID = TypeIDs[T];
if (ID == 0) {
// We haven't seen this type before. Assign it a new ID and put it
- // into the queu of types to emit.
+ // into the queue of types to emit.
ID = NextTypeID++;
- TypesToEmit.push(T.getTypePtr());
+ TypesToEmit.push(T);
}
// Encode the type qualifiers in the type reference.
- Record.push_back((ID << 3) | T.getCVRQualifiers());
+ Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
}
void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
diff --git a/clang/lib/Frontend/RewriteObjC.cpp b/clang/lib/Frontend/RewriteObjC.cpp
index 57b1fc31a84..55ab78e638b 100644
--- a/clang/lib/Frontend/RewriteObjC.cpp
+++ b/clang/lib/Frontend/RewriteObjC.cpp
@@ -1937,8 +1937,7 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
void RewriteObjC::SynthSelGetUidFunctionDecl() {
IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
llvm::SmallVector<QualType, 16> ArgTys;
- ArgTys.push_back(Context->getPointerType(
- Context->CharTy.getQualifiedType(QualType::Const)));
+ ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(),
&ArgTys[0], ArgTys.size(),
false /*isVariadic*/, 0);
@@ -2084,8 +2083,7 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
void RewriteObjC::SynthGetClassFunctionDecl() {
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
llvm::SmallVector<QualType, 16> ArgTys;
- ArgTys.push_back(Context->getPointerType(
- Context->CharTy.getQualifiedType(QualType::Const)));
+ ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
&ArgTys[0], ArgTys.size(),
false /*isVariadic*/, 0);
@@ -2099,8 +2097,7 @@ void RewriteObjC::SynthGetClassFunctionDecl() {
void RewriteObjC::SynthGetMetaClassFunctionDecl() {
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
llvm::SmallVector<QualType, 16> ArgTys;
- ArgTys.push_back(Context->getPointerType(
- Context->CharTy.getQualifiedType(QualType::Const)));
+ ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
&ArgTys[0], ArgTys.size(),
false /*isVariadic*/, 0);
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 63b252a536a..81f7283e23f 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -44,9 +44,7 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
// If this is a sugared type (like a typedef, typeof, etc), then unwrap one
// level of the sugar so that the type is more obvious to the user.
- QualType DesugaredTy = Ty->getDesugaredType(true);
- DesugaredTy.setCVRQualifiers(DesugaredTy.getCVRQualifiers() |
- Ty.getCVRQualifiers());
+ QualType DesugaredTy = Ty.getDesugaredType(true);
if (Ty != DesugaredTy &&
// If the desugared type is a vector type, we don't want to expand it,
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp
index d1a8b6dedfe..ab085fb8ee7 100644
--- a/clang/lib/Sema/SemaCXXCast.cpp
+++ b/clang/lib/Sema/SemaCXXCast.cpp
@@ -186,12 +186,12 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
"Destination type is not pointer or pointer to member.");
QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType;
- llvm::SmallVector<unsigned, 8> cv1, cv2;
+ llvm::SmallVector<Qualifiers, 8> cv1, cv2;
// Find the qualifications.
while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
- cv1.push_back(UnwrappedSrcType.getCVRQualifiers());
- cv2.push_back(UnwrappedDestType.getCVRQualifiers());
+ cv1.push_back(UnwrappedSrcType.getQualifiers());
+ cv2.push_back(UnwrappedDestType.getQualifiers());
}
assert(cv1.size() > 0 && "Must have at least one pointer level.");
@@ -199,13 +199,14 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
// unwrapping, of course).
QualType SrcConstruct = Self.Context.VoidTy;
QualType DestConstruct = Self.Context.VoidTy;
- for (llvm::SmallVector<unsigned, 8>::reverse_iterator i1 = cv1.rbegin(),
- i2 = cv2.rbegin();
+ ASTContext &Context = Self.Context;
+ for (llvm::SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
+ i2 = cv2.rbegin();
i1 != cv1.rend(); ++i1, ++i2) {
- SrcConstruct = Self.Context.getPointerType(
- SrcConstruct.getQualifiedType(*i1));
- DestConstruct = Self.Context.getPointerType(
- DestConstruct.getQualifiedType(*i2));
+ SrcConstruct
+ = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
+ DestConstruct
+ = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
}
// Test if they're compatible.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 084b2efcf36..ec27814870c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1814,14 +1814,16 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
// constant expression folding, like struct {char x[(int)(char*)2];}
SizeIsNegative = false;
- if (const PointerType* PTy = dyn_cast<PointerType>(T)) {
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T);
+
+ if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
QualType Pointee = PTy->getPointeeType();
QualType FixedType =
TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative);
if (FixedType.isNull()) return FixedType;
FixedType = Context.getPointerType(FixedType);
- FixedType.setCVRQualifiers(T.getCVRQualifiers());
- return FixedType;
+ return Qs.apply(FixedType);
}
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
@@ -2968,7 +2970,7 @@ void Sema::CheckMain(FunctionDecl* FD) {
// char const * const *
// char * const *
- QualifierSet qs;
+ QualifierCollector qs;
const PointerType* PT;
if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
(PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 5cced5a92e9..390a8048db2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2046,13 +2046,13 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
if (FTI.TypeQuals != 0) {
- if (FTI.TypeQuals & QualType::Const)
+ if (FTI.TypeQuals & Qualifiers::Const)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
<< "const" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Volatile)
+ if (FTI.TypeQuals & Qualifiers::Volatile)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
<< "volatile" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Restrict)
+ if (FTI.TypeQuals & Qualifiers::Restrict)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
<< "restrict" << SourceRange(D.getIdentifierLoc());
}
@@ -2159,13 +2159,13 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D,
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
- if (FTI.TypeQuals & QualType::Const)
+ if (FTI.TypeQuals & Qualifiers::Const)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
<< "const" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Volatile)
+ if (FTI.TypeQuals & Qualifiers::Volatile)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
<< "volatile" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Restrict)
+ if (FTI.TypeQuals & Qualifiers::Restrict)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
<< "restrict" << SourceRange(D.getIdentifierLoc());
D.setInvalidType();
@@ -2844,10 +2844,8 @@ Sema::getAssignOperatorMethod(ParmVarDecl *ParmDecl,
// If class's assignment operator argument is const/volatile qualified,
// look for operator = (const/volatile B&). Otherwise, look for
// operator = (B&).
- if (ParmDecl->getType().isConstQualified())
- RHSType.addConst();
- if (ParmDecl->getType().isVolatileQualified())
- RHSType.addVolatile();
+ RHSType = Context.getCVRQualifiedType(RHSType,
+ ParmDecl->getType().getCVRQualifiers());
ExprOwningPtr<Expr> LHS(this, new (Context) DeclRefExpr(ParmDecl,
LHSType,
SourceLocation()));
@@ -3575,7 +3573,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// -- Otherwise, the reference shall be to a non-volatile const
// type (i.e., cv1 shall be const), or the reference shall be an
// rvalue reference and the initializer expression shall be an rvalue.
- if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) {
+ if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
if (!ICS)
Diag(DeclLoc, diag::err_not_reference_to_const_init)
<< T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value")
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9695814860c..5bc8818dbad 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -566,7 +566,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
// of the anonymous union objects and, eventually, the field we
// found via name lookup.
bool BaseObjectIsPointer = false;
- unsigned ExtraQuals = 0;
+ Qualifiers BaseQuals;
if (BaseObject) {
// BaseObject is an anonymous struct/union variable (and is,
// therefore, not part of another non-anonymous record).
@@ -574,8 +574,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
MarkDeclarationReferenced(Loc, BaseObject);
BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
SourceLocation());
- ExtraQuals
- = Context.getCanonicalType(BaseObject->getType()).getCVRQualifiers();
+ BaseQuals
+ = Context.getCanonicalType(BaseObject->getType()).getQualifiers();
} else if (BaseObjectExpr) {
// The caller provided the base object expression. Determine
// whether its a pointer and whether it adds any qualifiers to the
@@ -585,7 +585,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
BaseObjectIsPointer = true;
ObjectType = ObjectPtr->getPointeeType();
}
- ExtraQuals = Context.getCanonicalType(ObjectType).getCVRQualifiers();
+ BaseQuals
+ = Context.getCanonicalType(ObjectType).getQualifiers();
} else {
// We've found a member of an anonymous struct/union that is
// inside a non-anonymous struct/union, so in a well-formed
@@ -608,7 +609,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method)
<< Field->getDeclName());
}
- ExtraQuals = MD->getTypeQualifiers();
+ BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
}
if (!BaseObjectExpr)
@@ -619,24 +620,35 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
// Build the implicit member references to the field of the
// anonymous struct/union.
Expr *Result = BaseObjectExpr;
- unsigned BaseAddrSpace = BaseObjectExpr->getType().getAddressSpace();
+ Qualifiers ResultQuals = BaseQuals;
for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
FI = AnonFields.rbegin(), FIEnd = AnonFields.rend();
FI != FIEnd; ++FI) {
QualType MemberType = (*FI)->getType();
- if (!(*FI)->isMutable()) {
- unsigned combinedQualifiers
- = MemberType.getCVRQualifiers() | ExtraQuals;
- MemberType = MemberType.getQualifiedType(combinedQualifiers);
- }
- if (BaseAddrSpace != MemberType.getAddressSpace())
- MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
+ Qualifiers MemberTypeQuals =
+ Context.getCanonicalType(MemberType).getQualifiers();
+
+ // CVR attributes from the base are picked up by members,
+ // except that 'mutable' members don't pick up 'const'.
+ if ((*FI)->isMutable())
+ ResultQuals.removeConst();
+
+ // GC attributes are never picked up by members.
+ ResultQuals.removeObjCGCAttr();
+
+ // TR 18037 does not allow fields to be declared with address spaces.
+ assert(!MemberTypeQuals.hasAddressSpace());
+
+ Qualifiers NewQuals = ResultQuals + MemberTypeQuals;
+ if (NewQuals != MemberTypeQuals)
+ MemberType = Context.getQualifiedType(MemberType, NewQuals);
+
MarkDeclarationReferenced(Loc, *FI);
// FIXME: Might this end up being a qualified name?
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
OpLoc, MemberType);
BaseObjectIsPointer = false;
- ExtraQuals = Context.getCanonicalType(MemberType).getCVRQualifiers();
+ ResultQuals = NewQuals;
}
return Owned(Result);
@@ -948,11 +960,10 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
MemberType = RefType->getPointeeType();
- else if (!FD->isMutable()) {
- unsigned combinedQualifiers
- = MemberType.getCVRQualifiers() | MD->getTypeQualifiers();
- MemberType = MemberType.getQualifiedType(combinedQualifiers);
- }
+ else if (!FD->isMutable())
+ MemberType
+ = Context.getQualifiedType(MemberType,
+ Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (!Method->isStatic()) {
Ctx = Method->getParent();
@@ -1135,7 +1146,7 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
// - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent
else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) {
- if (Dcl->getType().getCVRQualifiers() == QualType::Const &&
+ if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const &&
Dcl->getInit()) {
ValueDependent = Dcl->getInit()->isValueDependent();
}
@@ -1174,7 +1185,7 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
PredefinedExpr::ComputeName(Context, IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
- ResTy = Context.CharTy.getQualifiedType(QualType::Const);
+ ResTy = Context.CharTy.withConst();
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
}
return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
@@ -2235,14 +2246,16 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
MemberType = Ref->getPointeeType();
else {
- unsigned BaseAddrSpace = BaseType.getAddressSpace();
- unsigned combinedQualifiers =
- MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
- if (FD->isMutable())
- combinedQualifiers &= ~QualType::Const;
- MemberType = MemberType.getQualifiedType(combinedQualifiers);
- if (BaseAddrSpace != MemberType.getAddressSpace())
- MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
+ Qualifiers BaseQuals = BaseType.getQualifiers();
+ BaseQuals.removeObjCGCAttr();
+ if (FD->isMutable()) BaseQuals.removeConst();
+
+ Qualifiers MemberQuals
+ = Context.getCanonicalType(MemberType).getQualifiers();
+
+ Qualifiers Combined = BaseQuals + MemberQuals;
+ if (Combined != MemberQuals)
+ MemberType = Context.getQualifiedType(MemberType, Combined);
}
MarkDeclarationReferenced(MemberLoc, FD);
@@ -3510,7 +3523,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
- QualType destPointee = lhptee.getQualifiedType(rhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(LHS, destType); // add qualifiers if necessary
ImpCastExprToType(RHS, destType); // promote to void*
@@ -3519,7 +3533,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
- QualType destPointee = rhptee.getQualifiedType(lhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(RHS, destType); // add qualifiers if necessary
ImpCastExprToType(LHS, destType); // promote to void*
@@ -3534,14 +3549,16 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// ignore qualifiers on void (C99 6.5.15p3, clause 6)
if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
// Figure out necessary qualifiers (C99 6.5.15p6)
- QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(LHS, destType); // add qualifiers if necessary
ImpCastExprToType(RHS, destType); // promote to void*
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
- QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(LHS, destType); // add qualifiers if necessary
ImpCastExprToType(RHS, destType); // promote to void*
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index ff6ae50533a..e93929e94b9 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -972,7 +972,7 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
= ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
// This conversion is considered only when there is an
// explicit appropriate pointer target type (C++ 4.2p2).
- if (ToPtrType->getPointeeType().getCVRQualifiers() == 0 &&
+ if (!ToPtrType->getPointeeType().hasQualifiers() &&
((StrLit->isWide() && ToPointeeType->isWideCharType()) ||
(!StrLit->isWide() &&
(ToPointeeType->getKind() == BuiltinType::Char_U ||
@@ -1316,10 +1316,7 @@ QualType Sema::CheckPointerToMemberOperands(
// argument.
// We probably need a "MemberFunctionClosureType" or something like that.
QualType Result = MemPtr->getPointeeType();
- if (LType.isConstQualified())
- Result.addConst();
- if (LType.isVolatileQualified())
- Result.addVolatile();
+ Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
return Result;
}
@@ -1662,14 +1659,33 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (LMemPtr && RMemPtr) {
QualType LPointee = LMemPtr->getPointeeType();
QualType RPointee = RMemPtr->getPointeeType();
+
+ QualifierCollector LPQuals, RPQuals;
+ const Type *LPCan = LPQuals.strip(Context.getCanonicalType(LPointee));
+ const Type *RPCan = RPQuals.strip(Context.getCanonicalType(RPointee));
+
// First, we check that the unqualified pointee type is the same. If it's
// not, there's no conversion that will unify the two pointers.
- if (Context.getCanonicalType(LPointee).getUnqualifiedType() ==
- Context.getCanonicalType(RPointee).getUnqualifiedType()) {
- // Second, we take the greater of the two cv qualifications. If neither
+ if (LPCan == RPCan) {
+
+ // Second, we take the greater of the two qualifications. If neither
// is greater than the other, the conversion is not possible.
- unsigned Q = LPointee.getCVRQualifiers() | RPointee.getCVRQualifiers();
- if (Q == LPointee.getCVRQualifiers() || Q == RPointee.getCVRQualifiers()){
+
+ Qualifiers MergedQuals = LPQuals + RPQuals;
+
+ bool CompatibleQuals = true;
+ if (MergedQuals.getCVRQualifiers() != LPQuals.getCVRQualifiers() &&
+ MergedQuals.getCVRQualifiers() != RPQuals.getCVRQualifiers())
+ CompatibleQuals = false;
+ else if (LPQuals.getAddressSpace() != RPQuals.getAddressSpace())
+ // FIXME:
+ // C99 6.5.15 as modified by TR 18037:
+ // If the second and third operands are pointers into different
+ // address spaces, the address spaces must overlap.
+ CompatibleQuals = false;
+ // FIXME: GC qualifiers?
+
+ if (CompatibleQuals) {
// Third, we check if either of the container classes is derived from
// the other.
QualType LContainer(LMemPtr->getClass(), 0);
@@ -1687,8 +1703,9 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// The type 'Q Pointee (MoreDerived::*)' is the common type.
// We don't use ImpCastExprToType here because this could still fail
// for ambiguous or inaccessible conversions.
- QualType Common = Context.getMemberPointerType(
- LPointee.getQualifiedType(Q), MoreDerived.getTypePtr());
+ LPointee = Context.getQualifiedType(LPointee, MergedQuals);
+ QualType Common
+ = Context.getMemberPointerType(LPointee, MoreDerived.getTypePtr());
if (PerformImplicitConversion(LHS, Common, "converting"))
return QualType();
if (PerformImplicitConversion(RHS, Common, "converting"))
@@ -1750,6 +1767,7 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
// What we do here is, we build the two possible composite types, and try the
// conversions in both directions. If only one works, or if the two composite
// types are the same, we have succeeded.
+ // FIXME: extended qualifiers?
llvm::SmallVector<unsigned, 4> QualifierUnion;
llvm::SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass;
QualType Composite1 = T1, Composite2 = T2;
@@ -1790,16 +1808,21 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
I = QualifierUnion.begin(),
E = QualifierUnion.end();
I != E; (void)++I, ++MOC) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(*I);
if (MOC->first && MOC->second) {
// Rebuild member pointer type
- Composite1 = Context.getMemberPointerType(Composite1.getQualifiedType(*I),
- MOC->first);
- Composite2 = Context.getMemberPointerType(Composite2.getQualifiedType(*I),
- MOC->second);
+ Composite1 = Context.getMemberPointerType(
+ Context.getQualifiedType(Composite1, Quals),
+ MOC->first);
+ Composite2 = Context.getMemberPointerType(
+ Context.getQualifiedType(Composite2, Quals),
+ MOC->second);
} else {
// Rebuild pointer type
- Composite1 = Context.getPointerType(Composite1.getQualifiedType(*I));
- Composite2 = Context.getPointerType(Composite2.getQualifiedType(*I));
+ Composite1
+ = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
+ Composite2
+ = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
}
}
diff --git a/clang/lib/Sema/SemaInherit.cpp b/clang/lib/Sema/SemaInherit.cpp
index 01e856c1d6d..8f932ac7d15 100644
--- a/clang/lib/Sema/SemaInherit.cpp
+++ b/clang/lib/Sema/SemaInherit.cpp
@@ -59,7 +59,7 @@ BasePaths::decl_iterator BasePaths::found_decls_end() {
/// an unqualified, canonical class type.
bool BasePaths::isAmbiguous(QualType BaseType) {
assert(BaseType->isCanonical() && "Base type must be the canonical type");
- assert(BaseType.getCVRQualifiers() == 0 && "Base type must be unqualified");
+ assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified");
std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4232d54f4b6..edb854ccdd4 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -856,12 +856,12 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
ASTContext &Context) {
QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType());
QualType CanonToPointee = Context.getCanonicalType(ToPointee);
- unsigned Quals = CanonFromPointee.getCVRQualifiers();
+ Qualifiers Quals = CanonFromPointee.getQualifiers();
// Exact qualifier match -> return the pointer type we're converting to.
- if (CanonToPointee.getCVRQualifiers() == Quals) {
+ if (CanonToPointee.getQualifiers() == Quals) {
// ToType is exactly what we need. Return it.
- if (ToType.getTypePtr())
+ if (!ToType.isNull())
return ToType;
// Build a pointer to ToPointee. It has the right qualifiers
@@ -870,7 +870,8 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
}
// Just build a canonical type that has the right qualifiers.
- return Context.getPointerType(CanonToPointee.getQualifiedType(Quals));
+ return Context.getPointerType(
+ Context.getQualifiedType(CanonToPointee.getUnqualifiedType(), Quals));
}
static bool isNullPointerConstantForConversion(Expr *Expr,
@@ -2022,8 +2023,8 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType,
ImplicitConversionSequence
Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
QualType ClassType = Context.getTypeDeclType(Method->getParent());
- unsigned MethodQuals = Method->getTypeQualifiers();
- QualType ImplicitParamType = ClassType.getQualifiedType(MethodQuals);
+ QualType ImplicitParamType
+ = Context.getCVRQualifiedType(ClassType, Method->getTypeQualifiers());
// Set up the conversion sequence as a "bad" conversion, to allow us
// to exit early.
@@ -2831,27 +2832,27 @@ public:
/// restrict *", and "int const volatile restrict *" to the set of
/// pointer types. Returns true if the add of @p Ty itself succeeded,
/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
bool
BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) {
+
// Insert this type.
if (!PointerTypes.insert(Ty))
return false;
- if (const PointerType *PointerTy = Ty->getAs<PointerType>()) {
- QualType PointeeTy = PointerTy->getPointeeType();
- // FIXME: Optimize this so that we don't keep trying to add the same types.
-
- // FIXME: Do we have to add CVR qualifiers at *all* levels to deal with all
- // pointer conversions that don't cast away constness?
- if (!PointeeTy.isConstQualified())
- AddPointerWithMoreQualifiedTypeVariants
- (Context.getPointerType(PointeeTy.withConst()));
- if (!PointeeTy.isVolatileQualified())
- AddPointerWithMoreQualifiedTypeVariants
- (Context.getPointerType(PointeeTy.withVolatile()));
- if (!PointeeTy.isRestrictQualified())
- AddPointerWithMoreQualifiedTypeVariants
- (Context.getPointerType(PointeeTy.withRestrict()));
+ const PointerType *PointerTy = Ty->getAs<PointerType>();
+ assert(PointerTy && "type was not a pointer type!");
+
+ QualType PointeeTy = PointerTy->getPointeeType();
+ unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+
+ // Iterate through all strict supersets of BaseCVR.
+ for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+ if ((CVR | BaseCVR) != CVR) continue;
+
+ QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+ PointerTypes.insert(Context.getPointerType(QPointeeTy));
}
return true;
@@ -2864,6 +2865,8 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) {
/// restrict *", and "int const volatile restrict *" to the set of
/// pointer types. Returns true if the add of @p Ty itself succeeded,
/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
bool
BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
QualType Ty) {
@@ -2871,20 +2874,20 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
if (!MemberPointerTypes.insert(Ty))
return false;
- if (const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>()) {
- QualType PointeeTy = PointerTy->getPointeeType();
- const Type *ClassTy = PointerTy->getClass();
- // FIXME: Optimize this so that we don't keep trying to add the same types.
-
- if (!PointeeTy.isConstQualified())
- AddMemberPointerWithMoreQualifiedTypeVariants
- (Context.getMemberPointerType(PointeeTy.withConst(), ClassTy));
- if (!PointeeTy.isVolatileQualified())
- AddMemberPointerWithMoreQualifiedTypeVariants
- (Context.getMemberPointerType(PointeeTy.withVolatile(), ClassTy));
- if (!PointeeTy.isRestrictQualified())
- AddMemberPointerWithMoreQualifiedTypeVariants
- (Context.getMemberPointerType(PointeeTy.withRestrict(), ClassTy));
+ const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
+ assert(PointerTy && "type was not a member pointer type!");
+
+ QualType PointeeTy = PointerTy->getPointeeType();
+ const Type *ClassTy = PointerTy->getClass();
+
+ // Iterate through all strict supersets of the pointee type's CVR
+ // qualifiers.
+ unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+ for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+ if ((CVR | BaseCVR) != CVR) continue;
+
+ QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+ MemberPointerTypes.insert(Context.getMemberPointerType(QPointeeTy, ClassTy));
}
return true;
@@ -2924,7 +2927,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
// Add 'cv void*' to our set of types.
if (!Ty->isVoidType()) {
QualType QualVoid
- = Context.VoidTy.getQualifiedType(PointeeTy.getCVRQualifiers());
+ = Context.getCVRQualifiedType(Context.VoidTy,
+ PointeeTy.getCVRQualifiers());
AddPointerWithMoreQualifiedTypeVariants(Context.getPointerType(QualVoid));
}
@@ -2936,7 +2940,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
Base != ClassDecl->bases_end(); ++Base) {
QualType BaseTy = Context.getCanonicalType(Base->getType());
- BaseTy = BaseTy.getQualifiedType(PointeeTy.getCVRQualifiers());
+ BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(),
+ PointeeTy.getCVRQualifiers());
// Add the pointer type, recursively, so that we get all of
// the indirect base classes, too.
@@ -2997,7 +3002,8 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
// volatile T& operator=(volatile T&, T)
- ParamTypes[0] = S.Context.getLValueReferenceType(T.withVolatile());
+ ParamTypes[0]
+ = S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
ParamTypes[1] = T;
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssignmentOperator=*/true);
@@ -3119,7 +3125,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
// Volatile version
- ParamTypes[0] = Context.getLValueReferenceType(ArithTy.withVolatile());
+ ParamTypes[0]
+ = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
if (NumArgs == 1)
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
@@ -3154,7 +3161,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
// With volatile
- ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
+ ParamTypes[0]
+ = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
if (NumArgs == 1)
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
@@ -3465,7 +3473,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
// volatile version
- ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
+ ParamTypes[0]
+ = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
}
@@ -3498,7 +3507,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
/*IsAssigmentOperator=*/Op == OO_Equal);
// Add this built-in operator as a candidate (VQ is 'volatile').
- ParamTypes[0] = ArithmeticTypes[Left].withVolatile();
+ ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]);
ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
@@ -3536,7 +3545,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
// Add this built-in operator as a candidate (VQ is 'volatile').
ParamTypes[0] = ArithmeticTypes[Left];
- ParamTypes[0].addVolatile();
+ ParamTypes[0] = Context.getVolatileType(ParamTypes[0]);
ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 4ffca8c8f5c..a73c261d97f 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -1295,22 +1295,19 @@ public:
TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
: t(type), stmt(statement) {}
+ // An arbitrary order is fine as long as it places identical
+ // types next to each other.
bool operator<(const TypeWithHandler &y) const {
- if (t.getTypePtr() < y.t.getTypePtr())
+ if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
return true;
- else if (t.getTypePtr() > y.t.getTypePtr())
- return false;
- else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
- return true;
- else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
+ if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
return false;
else
return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
}
bool operator==(const TypeWithHandler& other) const {
- return t.getTypePtr() == other.t.getTypePtr()
- && t.getCVRQualifiers() == other.t.getCVRQualifiers();
+ return t == other.t;
}
QualType getQualType() const { return t; }
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 8d4999bf6d6..2ad1a61b504 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -300,28 +300,30 @@ DeduceTemplateArguments(ASTContext &Context,
}
/// \brief Returns a completely-unqualified array type, capturing the
-/// qualifiers in CVRQuals.
+/// qualifiers in Quals.
///
/// \param Context the AST context in which the array type was built.
///
/// \param T a canonical type that may be an array type.
///
-/// \param CVRQuals will receive the set of const/volatile/restrict qualifiers
-/// that were applied to the element type of the array.
+/// \param Quals will receive the full set of qualifiers that were
+/// applied to the element type of the array.
///
/// \returns if \p T is an array type, the completely unqualified array type
/// that corresponds to T. Otherwise, returns T.
static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
- unsigned &CVRQuals) {
+ Qualifiers &Quals) {
assert(T->isCanonical() && "Only operates on canonical types");
if (!isa<ArrayType>(T)) {
- CVRQuals = T.getCVRQualifiers();
+ Quals = T.getQualifiers();
return T.getUnqualifiedType();
}
+ assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
+
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(),
- CVRQuals);
+ Quals);
if (Elt == CAT->getElementType())
return T;
@@ -331,7 +333,7 @@ static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(),
- CVRQuals);
+ Quals);
if (Elt == IAT->getElementType())
return T;
@@ -340,7 +342,7 @@ static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(),
- CVRQuals);
+ Quals);
if (Elt == DSAT->getElementType())
return T;
@@ -387,9 +389,9 @@ DeduceTemplateArguments(ASTContext &Context,
// referred to by the reference) can be more cv-qualified than the
// transformed A.
if (TDF & TDF_ParamWithReferenceType) {
- unsigned ExtraQualsOnParam
- = Param.getCVRQualifiers() & ~Arg.getCVRQualifiers();
- Param.setCVRQualifiers(Param.getCVRQualifiers() & ~ExtraQualsOnParam);
+ Qualifiers Quals = Param.getQualifiers();
+ Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiers());
+ Param = Context.getQualifiedType(Param.getUnqualifiedType(), Quals);
}
// If the parameter type is not dependent, there is nothing to deduce.
@@ -418,10 +420,10 @@ DeduceTemplateArguments(ASTContext &Context,
// top level, so they can be matched with the qualifiers on the parameter.
// FIXME: address spaces, ObjC GC qualifiers
if (isa<ArrayType>(Arg)) {
- unsigned CVRQuals = 0;
- Arg = getUnqualifiedArrayType(Context, Arg, CVRQuals);
- if (CVRQuals) {
- Arg = Arg.getWithAdditionalQualifiers(CVRQuals);
+ Qualifiers Quals;
+ Arg = getUnqualifiedArrayType(Context, Arg, Quals);
+ if (Quals) {
+ Arg = Context.getQualifiedType(Arg, Quals);
RecanonicalizeArg = true;
}
}
@@ -437,8 +439,8 @@ DeduceTemplateArguments(ASTContext &Context,
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
- unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers();
- QualType DeducedType = Arg.getQualifiedType(Quals);
+ QualType DeducedType = Arg;
+ DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
if (RecanonicalizeArg)
DeducedType = Context.getCanonicalType(DeducedType);
@@ -2022,13 +2024,6 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
T = SemaRef.Context.getCanonicalType(T);
switch (T->getTypeClass()) {
- case Type::ExtQual:
- MarkUsedTemplateParameters(SemaRef,
- QualType(cast<ExtQualType>(T)->getBaseType(), 0),
- OnlyDeduced,
- Used);
- break;
-
case Type::Pointer:
MarkUsedTemplateParameters(SemaRef,
cast<PointerType>(T)->getPointeeType(),
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 86b49d4f320..90a03972cc1 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -496,7 +496,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
PredefinedExpr::ComputeName(getSema().Context, IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
- QualType ResTy = getSema().Context.CharTy.getQualifiedType(QualType::Const);
+ QualType ResTy = getSema().Context.CharTy.withConst();
ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI,
ArrayType::Normal, 0);
PredefinedExpr *PE =
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 6fee787a74e..c297694b9ff 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -312,7 +312,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
// Enforce C99 6.7.3p2: "Types other than pointer types derived from object
// or incomplete types shall not be restrict-qualified." C++ also allows
// restrict-qualified references.
- if (TypeQuals & QualType::Restrict) {
+ if (TypeQuals & DeclSpec::TQ_restrict) {
if (Result->isPointerType() || Result->isReferenceType()) {
QualType EltTy = Result->isPointerType() ?
Result->getAs<PointerType>()->getPointeeType() :
@@ -324,13 +324,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_invalid_pointee)
<< EltTy << DS.getSourceRange();
- TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
+ TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
}
} else {
Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_not_pointer)
<< Result << DS.getSourceRange();
- TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
+ TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
}
}
@@ -340,12 +340,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
if (Result->isFunctionType() && TypeQuals) {
// Get some location to point at, either the C or V location.
SourceLocation Loc;
- if (TypeQuals & QualType::Const)
+ if (TypeQuals & DeclSpec::TQ_const)
Loc = DS.getConstSpecLoc();
- else {
- assert((TypeQuals & QualType::Volatile) &&
- "Has CV quals but not C or V?");
+ else if (TypeQuals & DeclSpec::TQ_volatile)
Loc = DS.getVolatileSpecLoc();
+ else {
+ assert((TypeQuals & DeclSpec::TQ_restrict) &&
+ "Has CVR quals but not C, V, or R?");
+ Loc = DS.getRestrictSpecLoc();
}
Diag(Loc, diag::warn_typecheck_function_qualifiers)
<< Result << DS.getSourceRange();
@@ -359,12 +361,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
// FIXME: Shouldn't we be checking SCS_typedef here?
if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
TypeQuals && Result->isReferenceType()) {
- TypeQuals &= ~QualType::Const;
- TypeQuals &= ~QualType::Volatile;
+ TypeQuals &= ~DeclSpec::TQ_const;
+ TypeQuals &= ~DeclSpec::TQ_volatile;
}
- Result = Result.getQualifiedType(TypeQuals);
+ Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
+ Result = Context.getQualifiedType(Result, Quals);
}
+
return Result;
}
@@ -399,23 +403,25 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
return QualType();
}
+ Qualifiers Qs = Qualifiers::fromCVRMask(Quals);
+
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
- if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+ if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) {
Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
- Quals &= ~QualType::Restrict;
+ Qs.removeRestrict();
}
// Build the pointer type.
- return Context.getPointerType(T).getQualifiedType(Quals);
+ return Context.getQualifiedType(Context.getPointerType(T), Qs);
}
/// \brief Build a reference type.
///
/// \param T The type to which we'll be building a reference.
///
-/// \param Quals The cvr-qualifiers to be applied to the reference type.
+/// \param CVR The cvr-qualifiers to be applied to the reference type.
///
/// \param Loc The location of the entity whose type involves this
/// reference type or, if there is no such entity, the location of the
@@ -426,8 +432,9 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
///
/// \returns A suitable reference type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
+QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR,
SourceLocation Loc, DeclarationName Entity) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
if (LValueRef) {
if (const RValueReferenceType *R = T->getAs<RValueReferenceType>()) {
// C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
@@ -435,8 +442,8 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
// reference to cv TD" creates the type "lvalue reference to T".
// We use the qualifiers (restrict or none) of the original reference,
// not the new ones. This is consistent with GCC.
- return Context.getLValueReferenceType(R->getPointeeType()).
- getQualifiedType(T.getCVRQualifiers());
+ QualType LVRT = Context.getLValueReferenceType(R->getPointeeType());
+ return Context.getQualifiedType(LVRT, T.getQualifiers());
}
}
if (T->isReferenceType()) {
@@ -449,7 +456,7 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
// typedef int& intref;
// typedef intref& intref2;
//
- // Parser::ParserDeclaratorInternal diagnoses the case where
+ // Parser::ParseDeclaratorInternal diagnoses the case where
// references are written directly; here, we handle the
// collapsing of references-to-references as described in C++
// DR 106 and amended by C++ DR 540.
@@ -466,10 +473,10 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
- if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+ if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
- Quals &= ~QualType::Restrict;
+ Quals.removeRestrict();
}
// C++ [dcl.ref]p1:
@@ -481,13 +488,13 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
// We diagnose extraneous cv-qualifiers for the non-typedef,
// non-template type argument case within the parser. Here, we just
// ignore any extraneous cv-qualifiers.
- Quals &= ~QualType::Const;
- Quals &= ~QualType::Volatile;
+ Quals.removeConst();
+ Quals.removeVolatile();
// Handle restrict on references.
if (LValueRef)
- return Context.getLValueReferenceType(T).getQualifiedType(Quals);
- return Context.getRValueReferenceType(T).getQualifiedType(Quals);
+ return Context.getQualifiedType(Context.getLValueReferenceType(T), Quals);
+ return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);
}
/// \brief Build an array type.
@@ -513,6 +520,7 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceRange Brackets, DeclarationName Entity) {
+
SourceLocation Loc = Brackets.getBegin();
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
@@ -706,15 +714,17 @@ QualType Sema::BuildFunctionType(QualType T,
///
/// \param T the type to which the member pointer refers.
/// \param Class the class type into which the member pointer points.
-/// \param Quals Qualifiers applied to the member pointer type
+/// \param CVR Qualifiers applied to the member pointer type
/// \param Loc the location where this type begins
/// \param Entity the name of the entity that will have this member pointer type
///
/// \returns a member pointer type, if successful, or a NULL type if there was
/// an error.
QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
- unsigned Quals, SourceLocation Loc,
+ unsigned CVR, SourceLocation Loc,
DeclarationName Entity) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (CheckDistantExceptionSpec(T)) {
@@ -744,13 +754,13 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
- if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+ if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
// FIXME: If we're doing this as part of template instantiation,
// we should return immediately.
- Quals &= ~QualType::Restrict;
+ Quals.removeRestrict();
}
if (!Class->isDependentType() && !Class->isRecordType()) {
@@ -758,15 +768,15 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return QualType();
}
- return Context.getMemberPointerType(T, Class.getTypePtr())
- .getQualifiedType(Quals);
+ return Context.getQualifiedType(
+ Context.getMemberPointerType(T, Class.getTypePtr()), Quals);
}
/// \brief Build a block pointer type.
///
/// \param T The type to which we'll be building a block pointer.
///
-/// \param Quals The cvr-qualifiers to be applied to the block pointer type.
+/// \param CVR The cvr-qualifiers to be applied to the block pointer type.
///
/// \param Loc The location of the entity whose type involves this
/// block pointer type or, if there is no such entity, the location of the
@@ -777,15 +787,16 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
///
/// \returns A suitable block pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildBlockPointerType(QualType T, unsigned Quals,
+QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR,
SourceLocation Loc,
DeclarationName Entity) {
- if (!T.getTypePtr()->isFunctionType()) {
+ if (!T->isFunctionType()) {
Diag(Loc, diag::err_nonfunction_block_type);
return QualType();
}
- return Context.getBlockPointerType(T).getQualifiedType(Quals);
+ Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+ return Context.getQualifiedType(Context.getBlockPointerType(T), Quals);
}
QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) {
@@ -921,8 +932,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case DeclaratorChunk::BlockPointer:
if (ShouldBuildInfo) {
if (SourceTy->isFunctionType())
- SourceTy = Context.getBlockPointerType(SourceTy)
- .getQualifiedType(DeclType.Cls.TypeQuals);
+ SourceTy
+ = Context.getQualifiedType(Context.getBlockPointerType(SourceTy),
+ Qualifiers::fromCVRMask(DeclType.Cls.TypeQuals));
else
// If not function type Context::getBlockPointerType asserts,
// so just give up.
@@ -939,8 +951,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case DeclaratorChunk::Pointer:
//FIXME: Use ObjCObjectPointer for info when appropriate.
if (ShouldBuildInfo)
- SourceTy = Context.getPointerType(SourceTy)
- .getQualifiedType(DeclType.Ptr.TypeQuals);
+ SourceTy = Context.getQualifiedType(Context.getPointerType(SourceTy),
+ Qualifiers::fromCVRMask(DeclType.Ptr.TypeQuals));
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
@@ -957,14 +969,16 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
break;
- case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Reference: {
+ Qualifiers Quals;
+ if (DeclType.Ref.HasRestrict) Quals.addRestrict();
+
if (ShouldBuildInfo) {
if (DeclType.Ref.LValueRef)
SourceTy = Context.getLValueReferenceType(SourceTy);
else
SourceTy = Context.getRValueReferenceType(SourceTy);
- unsigned Quals = DeclType.Ref.HasRestrict ? QualType::Restrict : 0;
- SourceTy = SourceTy.getQualifiedType(Quals);
+ SourceTy = Context.getQualifiedType(SourceTy, Quals);
}
// Verify that we're not building a reference to pointer to function with
@@ -974,15 +988,15 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
D.setInvalidType(true);
// Build the type anyway.
}
- T = BuildReferenceType(T, DeclType.Ref.LValueRef,
- DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
+ T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals,
DeclType.Loc, Name);
break;
+ }
case DeclaratorChunk::Array: {
if (ShouldBuildInfo)
// We just need to get an array type, the exact type doesn't matter.
SourceTy = Context.getIncompleteArrayType(SourceTy, ArrayType::Normal,
- DeclType.Arr.TypeQuals);
+ DeclType.Arr.TypeQuals);
// Verify that we're not building an array of pointers to function with
// exception specification.
@@ -1009,7 +1023,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
ASM = ArrayType::Normal;
D.setInvalidType(true);
}
- T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
+ T = BuildArrayType(T, ASM, ArraySize,
+ Qualifiers::fromCVRMask(ATI.TypeQuals),
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
break;
}
@@ -1028,7 +1043,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
SourceTy = Context.getFunctionType(SourceTy, ArgTys.data(),
ArgTys.size(),
- FTI.isVariadic, FTI.TypeQuals);
+ FTI.isVariadic,
+ FTI.TypeQuals);
}
// If the function declarator has a prototype (i.e. it is not () and
@@ -1132,7 +1148,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
Param->setType(ArgTy);
} else {
// Reject, but continue to parse 'float(const void)'.
- if (ArgTy.getCVRQualifiers())
+ if (ArgTy.hasQualifiers())
Diag(DeclType.Loc, diag::err_void_param_qualified);
// Do not add 'void' to the ArgTys list.
@@ -1198,8 +1214,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (ShouldBuildInfo) {
QualType cls = !ClsType.isNull() ? ClsType : Context.IntTy;
- SourceTy = Context.getMemberPointerType(SourceTy, cls.getTypePtr())
- .getQualifiedType(DeclType.Mem.TypeQuals);
+ SourceTy = Context.getQualifiedType(
+ Context.getMemberPointerType(SourceTy, cls.getTypePtr()),
+ Qualifiers::fromCVRMask(DeclType.Mem.TypeQuals));
}
if (!ClsType.isNull())
@@ -1479,7 +1496,7 @@ bool Sema::CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID,
SubIsPointer = true;
}
bool SubIsClass = CanonicalSubT->isRecordType();
- CanonicalSubT.setCVRQualifiers(0);
+ CanonicalSubT = CanonicalSubT.getUnqualifiedType();
BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
@@ -1501,7 +1518,7 @@ bool Sema::CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID,
continue;
}
}
- CanonicalSuperT.setCVRQualifiers(0);
+ CanonicalSuperT = CanonicalSuperT.getUnqualifiedType();
// If the types are the same, move on to the next type in the subset.
if (CanonicalSubT == CanonicalSuperT) {
Contained = true;
@@ -1633,6 +1650,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
/// space for the type.
static void HandleAddressSpaceTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S){
+
// If this type is already address space qualified, reject it.
// Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
// for two or more different address spaces."
@@ -1664,10 +1682,10 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
addrSpace.setIsSigned(false);
}
llvm::APSInt max(addrSpace.getBitWidth());
- max = QualType::MaxAddressSpace;
+ max = Qualifiers::MaxAddressSpace;
if (addrSpace > max) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << QualType::MaxAddressSpace << ASArgExpr->getSourceRange();
+ << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
return;
}
@@ -1679,7 +1697,7 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
/// specified type. The attribute contains 1 argument, weak or strong.
static void HandleObjCGCTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S) {
- if (Type.getObjCGCAttr() != QualType::GCNone) {
+ if (Type.getObjCGCAttr() != Qualifiers::GCNone) {
S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc);
return;
}
@@ -1690,15 +1708,15 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
<< "objc_gc" << 1;
return;
}
- QualType::GCAttrTypes GCAttr;
+ Qualifiers::GC GCAttr;
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
return;
}
if (Attr.getParameterName()->isStr("weak"))
- GCAttr = QualType::Weak;
+ GCAttr = Qualifiers::Weak;
else if (Attr.getParameterName()->isStr("strong"))
- GCAttr = QualType::Strong;
+ GCAttr = Qualifiers::Strong;
else {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
<< "objc_gc" << Attr.getParameterName();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index bd7fb4f2f89..ffbf69b51aa 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -188,7 +188,7 @@ public:
/// not permitted (e.g., qualifiers on reference or function types). This
/// is the right thing for template instantiation, but probably not for
/// other clients.
- QualType AddTypeQualifiers(QualType T, unsigned CVRQualifiers);
+ QualType AddTypeQualifiers(QualType T, Qualifiers Qs);
/// \brief Transform the given statement.
///
@@ -1935,13 +1935,16 @@ QualType TreeTransform<Derived>::TransformType(QualType T) {
if (getDerived().AlreadyTransformed(T))
return T;
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T);
+
QualType Result;
- switch (T->getTypeClass()) {
+ switch (Ty->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
Result = getDerived().Transform##CLASS##Type( \
- static_cast<CLASS##Type*>(T.getTypePtr())); \
+ static_cast<const CLASS##Type*>(Ty)); \
break;
#include "clang/AST/TypeNodes.def"
}
@@ -1949,25 +1952,19 @@ QualType TreeTransform<Derived>::TransformType(QualType T) {
if (Result.isNull() || T == Result)
return Result;
- return getDerived().AddTypeQualifiers(Result, T.getCVRQualifiers());
+ return getDerived().AddTypeQualifiers(Result, Qs);
}
template<typename Derived>
QualType
-TreeTransform<Derived>::AddTypeQualifiers(QualType T, unsigned CVRQualifiers) {
- if (CVRQualifiers && !T->isFunctionType() && !T->isReferenceType())
- return T.getWithAdditionalQualifiers(CVRQualifiers);
+TreeTransform<Derived>::AddTypeQualifiers(QualType T, Qualifiers Quals) {
+ if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType())
+ return SemaRef.Context.getQualifiedType(T, Quals);
return T;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformExtQualType(const ExtQualType *T) {
- // FIXME: Implement
- return QualType(T, 0);
-}
-
-template<typename Derived>
QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) {
// Nothing to do
return QualType(T, 0);
@@ -2076,7 +2073,7 @@ TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) {
return getDerived().RebuildConstantArrayType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2103,7 +2100,7 @@ TreeTransform<Derived>::TransformConstantArrayWithExprType(
T->getSizeModifier(),
T->getSize(),
Size.takeAs<Expr>(),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -2122,7 +2119,7 @@ TreeTransform<Derived>::TransformConstantArrayWithoutExprType(
return getDerived().RebuildConstantArrayWithoutExprType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2138,7 +2135,7 @@ QualType TreeTransform<Derived>::TransformIncompleteArrayType(
return getDerived().RebuildIncompleteArrayType(ElementType,
T->getSizeModifier(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2165,7 +2162,7 @@ QualType TreeTransform<Derived>::TransformVariableArrayType(
return getDerived().RebuildVariableArrayType(ElementType,
T->getSizeModifier(),
move(Size),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -2193,7 +2190,7 @@ QualType TreeTransform<Derived>::TransformDependentSizedArrayType(
return getDerived().RebuildDependentSizedArrayType(ElementType,
T->getSizeModifier(),
move(Size),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -4462,14 +4459,14 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
template<typename Derived>
QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
- return SemaRef.BuildPointerType(PointeeType, 0,
+ return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
template<typename Derived>
QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
- return SemaRef.BuildBlockPointerType(PointeeType, 0,
+ return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4477,7 +4474,7 @@ QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
template<typename Derived>
QualType
TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, true, 0,
+ return SemaRef.BuildReferenceType(ReferentType, true, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4485,7 +4482,7 @@ TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
template<typename Derived>
QualType
TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, false, 0,
+ return SemaRef.BuildReferenceType(ReferentType, false, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4493,7 +4490,7 @@ TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
template<typename Derived>
QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
QualType ClassType) {
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0,
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4700,7 +4697,7 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
QualType T) {
if (T->isDependentType() || T->isRecordType() ||
(SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
- assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here");
+ assert(!T.hasQualifiers() && "Can't get cv-qualifiers here");
return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
T.getTypePtr());
}
OpenPOWER on IntegriCloud