[cfe-commits] r82705 - in /cfe/trunk: include/clang/AST/ include/clang/Frontend/ include/clang/Parse/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Sema/ test/Sema/
John McCall
rjmccall at apple.com
Thu Sep 24 12:53:01 PDT 2009
Author: rjmccall
Date: Thu Sep 24 14:53:00 2009
New Revision: 82705
URL: http://llvm.org/viewvc/llvm-project?rev=82705&view=rev
Log:
Refactor the representation of qualifiers to bring ExtQualType out of the
Type hierarchy. Demote 'volatile' to extended-qualifier status. Audit our
use of qualifiers and fix a few places that weren't dealing with qualifiers
quite right; many more remain.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/CanonicalType.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/AST/TypeNodes.def
cfe/trunk/include/clang/Frontend/DocumentXML.h
cfe/trunk/include/clang/Frontend/PCHReader.h
cfe/trunk/include/clang/Frontend/PCHWriter.h
cfe/trunk/include/clang/Frontend/TypeXML.def
cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/AST/DeclarationName.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/StmtDumper.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/lib/CodeGen/CGCall.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/lib/CodeGen/CGValue.h
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/CodeGen/Mangle.cpp
cfe/trunk/lib/Frontend/DocumentXML.cpp
cfe/trunk/lib/Frontend/PCHReader.cpp
cfe/trunk/lib/Frontend/PCHWriter.cpp
cfe/trunk/lib/Frontend/RewriteObjC.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaCXXCast.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaInherit.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/Sema/address_spaces.c
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Sep 24 14:53:00 2009
@@ -63,7 +63,7 @@
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
std::vector<Type*> Types;
- llvm::FoldingSet<ExtQualType> ExtQualTypes;
+ llvm::FoldingSet<ExtQuals> ExtQualNodes;
llvm::FoldingSet<ComplexType> ComplexTypes;
llvm::FoldingSet<PointerType> PointerTypes;
llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
@@ -332,6 +332,11 @@
// Type Constructors
//===--------------------------------------------------------------------===//
+private:
+ /// getExtQualType - Return a type with extended qualifiers.
+ QualType getExtQualType(const Type *Base, Qualifiers Quals);
+
+public:
/// getAddSpaceQualType - Return the uniqued reference to the type for an
/// address space qualified type with the specified type and address space.
/// The resulting type has a union of the qualifiers from T and the address
@@ -342,7 +347,27 @@
/// getObjCGCQualType - Returns the uniqued reference to the type for an
/// objc gc qualified type. The retulting type has a union of the qualifiers
/// from T and the gc attribute.
- QualType getObjCGCQualType(QualType T, QualType::GCAttrTypes gcAttr);
+ QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr);
+
+ /// getRestrictType - Returns the uniqued reference to the type for a
+ /// 'restrict' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'restrict'.
+ QualType getRestrictType(QualType T) {
+ return T.withFastQualifiers(Qualifiers::Restrict);
+ }
+
+ /// getVolatileType - Returns the uniqued reference to the type for a
+ /// 'volatile' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'volatile'.
+ QualType getVolatileType(QualType T);
+
+ /// getConstType - Returns the uniqued reference to the type for a
+ /// 'const' qualified type. The resulting type has a union of the
+ /// qualifiers from T and 'const'.
+ ///
+ /// It can be reasonably expected that this will always be
+ /// equivalent to calling T.withConst().
+ QualType getConstType(QualType T) { return T.withConst(); }
/// getNoReturnType - Add the noreturn attribute to the given type which must
/// be a FunctionType or a pointer to an allowable type or a BlockPointer.
@@ -636,6 +661,28 @@
QualType getFixedWidthIntType(unsigned Width, bool Signed);
+ /// getCVRQualifiedType - Returns a type with additional const,
+ /// volatile, or restrict qualifiers.
+ QualType getCVRQualifiedType(QualType T, unsigned CVR) {
+ return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
+ }
+
+ /// getQualifiedType - Returns a type with additional qualifiers.
+ QualType getQualifiedType(QualType T, Qualifiers Qs) {
+ if (!Qs.hasNonFastQualifiers())
+ return T.withFastQualifiers(Qs.getFastQualifiers());
+ QualifierCollector Qc(Qs);
+ const Type *Ptr = Qc.strip(T);
+ return getExtQualType(Ptr, Qc);
+ }
+
+ /// getQualifiedType - Returns a type with additional qualifiers.
+ QualType getQualifiedType(const Type *T, Qualifiers Qs) {
+ if (!Qs.hasNonFastQualifiers())
+ return QualType(T, Qs.getFastQualifiers());
+ return getExtQualType(T, Qs);
+ }
+
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
TemplateDecl *Template);
@@ -666,7 +713,7 @@
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
/// garbage collection attribute.
///
- QualType::GCAttrTypes getObjCGCAttrKind(const QualType &Ty) const;
+ Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
/// isObjCNSObjectType - Return true if this is an NSObject object with
/// its NSObject attribute set.
Modified: cfe/trunk/include/clang/AST/CanonicalType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CanonicalType.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/CanonicalType.h (original)
+++ cfe/trunk/include/clang/AST/CanonicalType.h Thu Sep 24 14:53:00 2009
@@ -103,20 +103,23 @@
/// proxy.
CanProxy<T> operator->() const;
+ /// \brief Retrieve all qualifiers.
+ Qualifiers getQualifiers() const { return Stored.getQualifiers(); }
+
/// \brief Retrieve the const/volatile/restrict qualifiers.
unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); }
- /// \brief Set the const/volatile/restrict qualifiers
- void setCVRQualifiers(unsigned Quals) { Stored.setCVRQualifiers(Quals); }
+ /// \brief Determines whether this type has any qualifiers
+ bool hasQualifiers() const { return Stored.hasQualifiers(); }
bool isConstQualified() const {
- return (getCVRQualifiers() & QualType::Const) ? true : false;
+ return Stored.isConstQualified();
}
bool isVolatileQualified() const {
- return (getCVRQualifiers() & QualType::Volatile) ? true : false;
+ return Stored.isVolatileQualified();
}
bool isRestrictQualified() const {
- return (getCVRQualifiers() & QualType::Restrict) ? true : false;
+ return Stored.isRestrictQualified();
}
/// \brief Retrieve the unqualified form of this type.
@@ -322,7 +325,7 @@
static inline clang::CanQual<T> getFromVoidPointer(void *P) {
return clang::CanQual<T>::getFromOpaquePtr(P);
}
- // CVR qualifiers go in low bits.
+ // qualifier information is encoded in the low bits.
enum { NumLowBitsAvailable = 0 };
};
@@ -426,13 +429,6 @@
};
template<>
-struct CanProxyAdaptor<ExtQualType> : public CanProxyBase<ExtQualType> {
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type*, getBaseType)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(QualType::GCAttrTypes, getObjCGCAttr)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getAddressSpace)
-};
-
-template<>
struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
};
@@ -477,7 +473,7 @@
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
getSizeModifier)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
};
template<>
@@ -486,7 +482,7 @@
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
getSizeModifier)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
};
@@ -496,7 +492,7 @@
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
getSizeModifier)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
@@ -510,7 +506,7 @@
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
getSizeModifier)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize)
};
@@ -520,7 +516,7 @@
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
getSizeModifier)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
};
template<>
@@ -529,7 +525,7 @@
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier,
getSizeModifier)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndexTypeQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc)
@@ -666,9 +662,7 @@
//----------------------------------------------------------------------------//
template<typename T>
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
- if (CanQual<ExtQualType> EQ = getAs<ExtQualType>())
- return CanQual<T>::CreateUnsafe(QualType(EQ->getBaseType(), 0));
- return CanQual<T>::CreateUnsafe(QualType(Stored.getTypePtr(), 0));
+ return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType());
}
template<typename T>
@@ -707,10 +701,6 @@
if (isa<U>(Stored.getTypePtr()))
return CanQual<U>::CreateUnsafe(Stored);
- if (const ExtQualType *EQ = Stored->getAs<ExtQualType>())
- return CanQual<T>::CreateUnsafe(QualType(EQ->getBaseType(), 0))
- .template getAs<U>();
-
return CanProxy<U>();
}
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Sep 24 14:53:00 2009
@@ -30,7 +30,7 @@
using llvm::cast_or_null;
using llvm::dyn_cast;
using llvm::dyn_cast_or_null;
-namespace clang { class Type; }
+namespace clang { class Type; class ExtQuals; }
namespace llvm {
template <typename T>
@@ -44,6 +44,15 @@
}
enum { NumLowBitsAvailable = 3 };
};
+ template<>
+ class PointerLikeTypeTraits< ::clang::ExtQuals*> {
+ public:
+ static inline void *getAsVoidPointer(::clang::ExtQuals *P) { return P; }
+ static inline ::clang::ExtQuals *getFromVoidPointer(void *P) {
+ return static_cast< ::clang::ExtQuals*>(P);
+ }
+ enum { NumLowBitsAvailable = 3 };
+ };
}
namespace clang {
@@ -73,43 +82,345 @@
#define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.def"
-/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
-/// their own: instead each reference to a type stores the qualifiers. This
-/// greatly reduces the number of nodes we need to allocate for types (for
-/// example we only need one for 'int', 'const int', 'volatile int',
-/// 'const volatile int', etc).
-///
-/// As an added efficiency bonus, instead of making this a pair, we just store
-/// the three bits we care about in the low bits of the pointer. To handle the
-/// packing/unpacking, we make QualType be a simple wrapper class that acts like
-/// a smart pointer.
-class QualType {
- llvm::PointerIntPair<Type*, 3> Value;
+/// Qualifiers - The collection of all-type qualifiers we support.
+/// Clang supports five independent qualifiers:
+/// * C99: const, volatile, and restrict
+/// * Embedded C (TR18037): address spaces
+/// * Objective C: the GC attributes (none, weak, or strong)
+class Qualifiers {
public:
- enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
+ enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
Const = 0x1,
Restrict = 0x2,
Volatile = 0x4,
- CVRFlags = Const|Restrict|Volatile
+ CVRMask = Const | Volatile | Restrict
};
- enum GCAttrTypes {
+ enum GC {
GCNone = 0,
Weak,
Strong
};
- // 24 bits should be enough for anyone.
- static const unsigned MaxAddressSpace = 0xffffffu;
+ enum {
+ /// The maximum supported address space number.
+ /// 24 bits should be enough for anyone.
+ MaxAddressSpace = 0xffffffu,
+
+ /// The width of the "fast" qualifier mask.
+ FastWidth = 2,
+
+ /// The fast qualifier mask.
+ FastMask = (1 << FastWidth) - 1
+ };
+
+ Qualifiers() : Mask(0) {}
+
+ static Qualifiers fromFastMask(unsigned Mask) {
+ Qualifiers Qs;
+ Qs.addFastQualifiers(Mask);
+ return Qs;
+ }
+
+ static Qualifiers fromCVRMask(unsigned CVR) {
+ Qualifiers Qs;
+ Qs.addCVRQualifiers(CVR);
+ return Qs;
+ }
+
+ // Deserialize qualifiers from an opaque representation.
+ static Qualifiers fromOpaqueValue(unsigned opaque) {
+ Qualifiers Qs;
+ Qs.Mask = opaque;
+ return Qs;
+ }
+
+ // Serialize these qualifiers into an opaque representation.
+ unsigned getAsOpaqueValue() const {
+ return Mask;
+ }
+
+ bool hasConst() const { return Mask & Const; }
+ void setConst(bool flag) {
+ Mask = (Mask & ~Const) | (flag ? Const : 0);
+ }
+ void removeConst() { Mask &= ~Const; }
+ void addConst() { Mask |= Const; }
+
+ bool hasVolatile() const { return Mask & Volatile; }
+ void setVolatile(bool flag) {
+ Mask = (Mask & ~Volatile) | (flag ? Volatile : 0);
+ }
+ void removeVolatile() { Mask &= ~Volatile; }
+ void addVolatile() { Mask |= Volatile; }
+
+ bool hasRestrict() const { return Mask & Restrict; }
+ void setRestrict(bool flag) {
+ Mask = (Mask & ~Restrict) | (flag ? Restrict : 0);
+ }
+ void removeRestrict() { Mask &= ~Restrict; }
+ void addRestrict() { Mask |= Restrict; }
+
+ bool hasCVRQualifiers() const { return getCVRQualifiers(); }
+ unsigned getCVRQualifiers() const { return Mask & CVRMask; }
+ void setCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask = (Mask & ~CVRMask) | mask;
+ }
+ void removeCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask &= ~mask;
+ }
+ void removeCVRQualifiers() {
+ removeCVRQualifiers(CVRMask);
+ }
+ void addCVRQualifiers(unsigned mask) {
+ assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
+ Mask |= mask;
+ }
+
+ bool hasObjCGCAttr() const { return Mask & GCAttrMask; }
+ GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); }
+ void setObjCGCAttr(GC type) {
+ Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift);
+ }
+ void removeObjCGCAttr() { setObjCGCAttr(GCNone); }
+ void addObjCGCAttr(GC type) {
+ assert(type);
+ setObjCGCAttr(type);
+ }
+
+ bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
+ unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
+ void setAddressSpace(unsigned space) {
+ assert(space <= MaxAddressSpace);
+ Mask = (Mask & ~AddressSpaceMask)
+ | (((uint32_t) space) << AddressSpaceShift);
+ }
+ void removeAddressSpace() { setAddressSpace(0); }
+ void addAddressSpace(unsigned space) {
+ assert(space);
+ setAddressSpace(space);
+ }
+
+ // Fast qualifiers are those that can be allocated directly
+ // on a QualType object.
+ bool hasFastQualifiers() const { return getFastQualifiers(); }
+ unsigned getFastQualifiers() const { return Mask & FastMask; }
+ void setFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask = (Mask & ~FastMask) | mask;
+ }
+ void removeFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask &= ~mask;
+ }
+ void removeFastQualifiers() {
+ removeFastQualifiers(FastMask);
+ }
+ void addFastQualifiers(unsigned mask) {
+ assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
+ Mask |= mask;
+ }
+
+ /// hasNonFastQualifiers - Return true if the set contains any
+ /// qualifiers which require an ExtQuals node to be allocated.
+ bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
+ Qualifiers getNonFastQualifiers() const {
+ Qualifiers Quals = *this;
+ Quals.setFastQualifiers(0);
+ return Quals;
+ }
+
+ /// hasQualifiers - Return true if the set contains any qualifiers.
+ bool hasQualifiers() const { return Mask; }
+ bool empty() const { return !Mask; }
+
+ /// \brief Add the qualifiers from the given set to this set.
+ void addQualifiers(Qualifiers Q) {
+ // If the other set doesn't have any non-boolean qualifiers, just
+ // bit-or it in.
+ if (!(Q.Mask & ~CVRMask))
+ Mask |= Q.Mask;
+ else {
+ Mask |= (Q.Mask & CVRMask);
+ if (Q.hasAddressSpace())
+ addAddressSpace(Q.getAddressSpace());
+ if (Q.hasObjCGCAttr())
+ addObjCGCAttr(Q.getObjCGCAttr());
+ }
+ }
+
+ bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
+ bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
+
+ operator bool() const { return hasQualifiers(); }
+
+ Qualifiers &operator+=(Qualifiers R) {
+ addQualifiers(R);
+ return *this;
+ }
+
+ // Union two qualifier sets. If an enumerated qualifier appears
+ // in both sets, use the one from the right.
+ friend Qualifiers operator+(Qualifiers L, Qualifiers R) {
+ L += R;
+ return L;
+ }
+
+ std::string getAsString() const;
+ std::string getAsString(const PrintingPolicy &Policy) const {
+ std::string Buffer;
+ getAsStringInternal(Buffer, Policy);
+ return Buffer;
+ }
+ void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Mask);
+ }
+
+private:
+
+ // bits: |0 1 2|3 .. 4|5 .. 31|
+ // |C R V|GCAttr|AddrSpace|
+ uint32_t Mask;
+
+ static const uint32_t GCAttrMask = 0x18;
+ static const uint32_t GCAttrShift = 3;
+ static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask);
+ static const uint32_t AddressSpaceShift = 5;
+};
+
+
+/// ExtQuals - We can encode up to three bits in the low bits of a
+/// type pointer, but there are many more type qualifiers that we want
+/// to be able to apply to an arbitrary type. Therefore we have this
+/// struct, intended to be heap-allocated and used by QualType to
+/// store qualifiers.
+///
+/// The current design tags the 'const' and 'restrict' qualifiers in
+/// two low bits on the QualType pointer; a third bit records whether
+/// the pointer is an ExtQuals node. 'const' was chosen because it is
+/// orders of magnitude more common than the other two qualifiers, in
+/// both library and user code. It's relatively rare to see
+/// 'restrict' in user code, but many standard C headers are saturated
+/// with 'restrict' declarations, so that representing them efficiently
+/// is a critical goal of this representation.
+class ExtQuals : public llvm::FoldingSetNode {
+ // NOTE: changing the fast qualifiers should be straightforward as
+ // long as you don't make 'const' non-fast.
+ // 1. Qualifiers:
+ // a) Modify the bitmasks (Qualifiers::TQ and DeclSpec::TQ).
+ // Fast qualifiers must occupy the low-order bits.
+ // b) Update Qualifiers::FastWidth and FastMask.
+ // 2. QualType:
+ // a) Update is{Volatile,Restrict}Qualified(), defined inline.
+ // b) Update remove{Volatile,Restrict}, defined near the end of
+ // this header.
+ // 3. ASTContext:
+ // a) Update get{Volatile,Restrict}Type.
+
+ /// Context - the context to which this set belongs. We save this
+ /// here so that QualifierCollector can use it to reapply extended
+ /// qualifiers to an arbitrary type without requiring a context to
+ /// be pushed through every single API dealing with qualifiers.
+ ASTContext& Context;
+
+ /// BaseType - the underlying type that this qualifies
+ const Type *BaseType;
+
+ /// Quals - the immutable set of qualifiers applied by this
+ /// node; always contains extended qualifiers.
+ Qualifiers Quals;
+
+public:
+ ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals)
+ : Context(Context), BaseType(Base), Quals(Quals)
+ {
+ assert(Quals.hasNonFastQualifiers()
+ && "ExtQuals created with no fast qualifiers");
+ assert(!Quals.hasFastQualifiers()
+ && "ExtQuals created with fast qualifiers");
+ }
+
+ Qualifiers getQualifiers() const { return Quals; }
+
+ bool hasVolatile() const { return Quals.hasVolatile(); }
+
+ bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); }
+ Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); }
+
+ bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
+ unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+
+ const Type *getBaseType() const { return BaseType; }
+
+ ASTContext &getContext() const { return Context; }
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, getBaseType(), Quals);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const Type *BaseType,
+ Qualifiers Quals) {
+ assert(!Quals.hasFastQualifiers() && "fast qualifiers in ExtQuals hash!");
+ ID.AddPointer(BaseType);
+ Quals.Profile(ID);
+ }
+};
+
+
+/// QualType - For efficiency, we don't store CV-qualified types as nodes on
+/// their own: instead each reference to a type stores the qualifiers. This
+/// greatly reduces the number of nodes we need to allocate for types (for
+/// example we only need one for 'int', 'const int', 'volatile int',
+/// 'const volatile int', etc).
+///
+/// As an added efficiency bonus, instead of making this a pair, we
+/// just store the two bits we care about in the low bits of the
+/// pointer. To handle the packing/unpacking, we make QualType be a
+/// simple wrapper class that acts like a smart pointer. A third bit
+/// indicates whether there are extended qualifiers present, in which
+/// case the pointer points to a special structure.
+class QualType {
+ // Thankfully, these are efficiently composable.
+ llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>,
+ Qualifiers::FastWidth> Value;
+
+ bool hasExtQuals() const {
+ return Value.getPointer().is<const ExtQuals*>();
+ }
+
+ const ExtQuals *getExtQualsUnsafe() const {
+ return Value.getPointer().get<const ExtQuals*>();
+ }
+ const Type *getTypePtrUnsafe() const {
+ return Value.getPointer().get<const Type*>();
+ }
+
+ friend class QualifierCollector;
+public:
QualType() {}
QualType(const Type *Ptr, unsigned Quals)
- : Value(const_cast<Type*>(Ptr), Quals) {}
-
- unsigned getCVRQualifiers() const { return Value.getInt(); }
- void setCVRQualifiers(unsigned Quals) { Value.setInt(Quals); }
- Type *getTypePtr() const { return Value.getPointer(); }
+ : Value(Ptr, Quals) {}
+ QualType(const ExtQuals *Ptr, unsigned Quals)
+ : Value(Ptr, Quals) {}
+
+ unsigned getFastQualifiers() const { return Value.getInt(); }
+ void setFastQualifiers(unsigned Quals) { Value.setInt(Quals); }
+
+ /// Retrieves a pointer to the underlying (unqualified) type.
+ /// This should really return a const Type, but it's not worth
+ /// changing all the users right now.
+ Type *getTypePtr() const {
+ if (hasNonFastQualifiers())
+ return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
+ return const_cast<Type*>(getTypePtrUnsafe());
+ }
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
static QualType getFromOpaquePtr(void *Ptr) {
@@ -128,43 +439,97 @@
/// isNull - Return true if this QualType doesn't point to a type yet.
bool isNull() const {
- return getTypePtr() == 0;
+ return Value.getPointer().isNull();
}
bool isConstQualified() const {
- return (getCVRQualifiers() & Const) ? true : false;
+ return (getFastQualifiers() & Qualifiers::Const);
+ }
+ bool isRestrictQualified() const {
+ return (getFastQualifiers() & Qualifiers::Restrict);
}
bool isVolatileQualified() const {
- return (getCVRQualifiers() & Volatile) ? true : false;
+ return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile());
}
- bool isRestrictQualified() const {
- return (getCVRQualifiers() & Restrict) ? true : false;
+
+ // Determines whether this type has any direct qualifiers.
+ bool hasQualifiers() const {
+ return getFastQualifiers() || hasNonFastQualifiers();
+ }
+
+ bool hasNonFastQualifiers() const {
+ return hasExtQuals();
+ }
+
+ // Retrieves the set of qualifiers belonging to this type.
+ Qualifiers getQualifiers() const {
+ Qualifiers Quals;
+ if (hasNonFastQualifiers())
+ Quals = getExtQualsUnsafe()->getQualifiers();
+ Quals.addFastQualifiers(getFastQualifiers());
+ return Quals;
+ }
+
+ // Retrieves the CVR qualifiers of this type.
+ unsigned getCVRQualifiers() const {
+ unsigned CVR = getFastQualifiers();
+ if (isVolatileQualified()) CVR |= Qualifiers::Volatile;
+ return CVR;
}
bool isConstant(ASTContext& Ctx) const;
- /// addConst/addVolatile/addRestrict - add the specified type qual to this
- /// QualType.
- void addConst() { Value.setInt(Value.getInt() | Const); }
- void addVolatile() { Value.setInt(Value.getInt() | Volatile); }
- void addRestrict() { Value.setInt(Value.getInt() | Restrict); }
+ // Don't promise in the API that anything besides 'const' can be
+ // easily added.
- void removeConst() { Value.setInt(Value.getInt() & ~Const); }
- void removeVolatile() { Value.setInt(Value.getInt() & ~Volatile); }
- void removeRestrict() { Value.setInt(Value.getInt() & ~Restrict); }
+ /// addConst - add the specified type qualifier to this QualType.
+ void addConst() {
+ addFastQualifiers(Qualifiers::Const);
+ }
+ QualType withConst() const {
+ return withFastQualifiers(Qualifiers::Const);
+ }
+
+ void addFastQualifiers(unsigned TQs) {
+ assert(!(TQs & ~Qualifiers::FastMask)
+ && "non-fast qualifier bits set in mask!");
+ Value.setInt(Value.getInt() | TQs);
+ }
+
+ void removeConst();
+ void removeVolatile();
+ void removeRestrict();
+ void removeCVRQualifiers(unsigned Mask);
+
+ void removeFastQualifiers() { Value.setInt(0); }
+ void removeFastQualifiers(unsigned Mask) {
+ assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers");
+ Value.setInt(Value.getInt() & ~Mask);
+ }
+
+ // Creates a type with the given qualifiers in addition to any
+ // qualifiers already on this type.
+ QualType withFastQualifiers(unsigned TQs) const {
+ QualType T = *this;
+ T.addFastQualifiers(TQs);
+ return T;
+ }
- QualType getQualifiedType(unsigned TQs) const {
- return QualType(getTypePtr(), TQs);
+ // Creates a type with exactly the given fast qualifiers, removing
+ // any existing fast qualifiers.
+ QualType withExactFastQualifiers(unsigned TQs) const {
+ return withoutFastQualifiers().withFastQualifiers(TQs);
}
- QualType getWithAdditionalQualifiers(unsigned TQs) const {
- return QualType(getTypePtr(), TQs|getCVRQualifiers());
+
+ // Removes fast qualifiers, but leaves any extended qualifiers in place.
+ QualType withoutFastQualifiers() const {
+ QualType T = *this;
+ T.removeFastQualifiers();
+ return T;
}
- QualType withConst() const { return getWithAdditionalQualifiers(Const); }
- QualType withVolatile() const { return getWithAdditionalQualifiers(Volatile);}
- QualType withRestrict() const { return getWithAdditionalQualifiers(Restrict);}
+ QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); }
- QualType getUnqualifiedType() const;
bool isMoreQualifiedThan(QualType Other) const;
bool isAtLeastAsQualifiedAs(QualType Other) const;
QualType getNonReferenceType() const;
@@ -175,6 +540,8 @@
/// to getting the canonical type, but it doesn't remove *all* typedefs. For
/// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
/// concrete.
+ ///
+ /// Qualifiers are left in place.
QualType getDesugaredType(bool ForDisplay = false) const;
/// operator==/!= - Indicate whether the specified types and qualifiers are
@@ -202,22 +569,20 @@
ID.AddPointer(getAsOpaquePtr());
}
-public:
-
/// getAddressSpace - Return the address space of this type.
inline unsigned getAddressSpace() const;
/// GCAttrTypesAttr - Returns gc attribute of this type.
- inline QualType::GCAttrTypes getObjCGCAttr() const;
+ inline Qualifiers::GC getObjCGCAttr() const;
/// isObjCGCWeak true when Type is objc's weak.
bool isObjCGCWeak() const {
- return getObjCGCAttr() == Weak;
+ return getObjCGCAttr() == Qualifiers::Weak;
}
/// isObjCGCStrong true when Type is objc's strong.
bool isObjCGCStrong() const {
- return getObjCGCAttr() == Strong;
+ return getObjCGCAttr() == Qualifiers::Strong;
}
/// getNoReturnAttr - Returns true if the type has the noreturn attribute,
@@ -249,7 +614,7 @@
static inline clang::QualType getFromVoidPointer(void *P) {
return clang::QualType::getFromOpaquePtr(P);
}
- // CVR qualifiers go in low bits.
+ // Various qualifiers go in low bits.
enum { NumLowBitsAvailable = 0 };
};
@@ -519,151 +884,11 @@
#define TYPE(Class, Base)
#define LEAF_TYPE(Class) \
template <> inline const Class##Type *Type::getAs() const { \
- return dyn_cast<Class##Type>(CanonicalType.getUnqualifiedType()); \
+ return dyn_cast<Class##Type>(CanonicalType); \
}
#include "clang/AST/TypeNodes.def"
-/// ExtQualType - TR18037 (C embedded extensions) 6.2.5p26
-/// This supports all kinds of type attributes; including,
-/// address space qualified types, objective-c's __weak and
-/// __strong attributes.
-///
-class ExtQualType : public Type, public llvm::FoldingSetNode {
- /// BaseType - This is the underlying type that this qualifies. All CVR
- /// qualifiers are stored on the QualType that references this type, so we
- /// can't have any here.
- Type *BaseType;
-
- /// Address Space ID - The address space ID this type is qualified with.
- unsigned AddressSpace;
- /// GC __weak/__strong attributes
- QualType::GCAttrTypes GCAttrType;
-
- ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace,
- QualType::GCAttrTypes gcAttr) :
- Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base),
- AddressSpace(AddrSpace), GCAttrType(gcAttr) {
- assert(!isa<ExtQualType>(BaseType) &&
- "Cannot have ExtQualType of ExtQualType");
- }
- friend class ASTContext; // ASTContext creates these.
-public:
- Type *getBaseType() const { return BaseType; }
- QualType::GCAttrTypes getObjCGCAttr() const { return GCAttrType; }
- unsigned getAddressSpace() const { return AddressSpace; }
-
- virtual void getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const;
-
- void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getBaseType(), AddressSpace, GCAttrType);
- }
- static void Profile(llvm::FoldingSetNodeID &ID, Type *Base,
- unsigned AddrSpace, QualType::GCAttrTypes gcAttr) {
- ID.AddPointer(Base);
- ID.AddInteger(AddrSpace);
- ID.AddInteger(gcAttr);
- }
-
- static bool classof(const Type *T) { return T->getTypeClass() == ExtQual; }
- static bool classof(const ExtQualType *) { return true; }
-};
-
-
-/// QualifierSet - This class is used to collect qualifiers.
-/// Clang supports five independent qualifiers:
-/// * C99: const, volatile, and restrict
-/// * Embedded C (TR18037): address spaces
-/// * Objective C: the GC attributes (none, weak, or strong)
-class QualifierSet {
-public:
- QualifierSet() : Mask(0) {}
-
- void removeConst() { removeCVR(QualType::Const); }
- void removeVolatile() { removeCVR(QualType::Volatile); }
- void removeRestrict() { removeCVR(QualType::Restrict); }
- void removeCVR(unsigned mask) { Mask &= ~mask; }
- void removeAddressSpace() { setAddressSpace(0); }
- void removeObjCGCAttrType() { setGCAttrType(QualType::GCNone); }
-
- void addConst() { addCVR(QualType::Const); }
- void addVolatile() { addCVR(QualType::Volatile); }
- void addRestrict() { addCVR(QualType::Restrict); }
- void addCVR(unsigned mask) { Mask |= mask; }
- void addAddressSpace(unsigned space) {
- assert(space);
- setAddressSpace(space);
- }
- void addObjCGCAttrType(QualType::GCAttrTypes type) {
- assert(type);
- setGCAttrType(type);
- }
-
- bool hasConst() const { return Mask & QualType::Const; }
- bool hasVolatile() const { return Mask & QualType::Volatile; }
- bool hasRestrict() const { return Mask & QualType::Restrict; }
- unsigned getCVRMask() const { return Mask & CVRMask; }
-
- bool hasObjCGCAttrType() const { return Mask & GCAttrMask; }
- QualType::GCAttrTypes getObjCGCAttrType() const {
- return QualType::GCAttrTypes((Mask & GCAttrMask) >> GCAttrShift);
- }
-
- bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
- unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
-
- /// empty() - Return true if there are no qualifiers collected
- /// in this set.
- bool empty() {
- return (Mask == 0);
- }
-
- /// Collect any qualifiers on the given type and return an
- /// unqualified type.
- const Type *strip(QualType QT) {
- Mask |= QT.getCVRQualifiers();
- return strip(QT.getTypePtr());
- }
-
- /// Collect any qualifiers on the given type and return an
- /// unqualified type.
- const Type *strip(const Type* T);
-
- /// Apply the collected qualifiers to the given type.
- QualType apply(QualType QT, ASTContext& C);
-
- /// Apply the collected qualifiers to the given type.
- QualType apply(const Type* T, ASTContext& C) {
- return apply(QualType(T, 0), C);
- }
-
- bool operator==(QualifierSet& Other) { return Mask == Other.Mask; }
-
-private:
- void setAddressSpace(unsigned space) {
- assert(space <= MaxAddressSpace);
- Mask = (Mask & ~AddressSpaceMask)
- | (((uint32_t) space) << AddressSpaceShift);
- }
-
- void setGCAttrType(QualType::GCAttrTypes type) {
- Mask = (Mask & ~GCAttrMask) | (type << GCAttrShift);
- }
-
- // bits: |0 1 2|3 .. 4|5 .. 31|
- // |C R V|GCAttr|AddrSpace|
- uint32_t Mask;
-
- static const uint32_t CVRMask = 0x07;
- static const uint32_t GCAttrMask = 0x18;
- static const uint32_t GCAttrShift = 3;
- static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask);
- static const uint32_t AddressSpaceShift = 5;
- static const unsigned MaxAddressSpace = QualType::MaxAddressSpace;
-};
-
-
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
@@ -967,7 +1192,10 @@
ArraySizeModifier getSizeModifier() const {
return ArraySizeModifier(SizeModifier);
}
- unsigned getIndexTypeQualifier() const { return IndexTypeQuals; }
+ Qualifiers getIndexTypeQualifiers() const {
+ return Qualifiers::fromCVRMask(IndexTypeQuals);
+ }
+ unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray ||
@@ -1003,7 +1231,7 @@
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getSize(),
- getSizeModifier(), getIndexTypeQualifier());
+ getSizeModifier(), getIndexTypeCVRQualifiers());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
@@ -1109,7 +1337,8 @@
friend class StmtIteratorBase;
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getElementType(), getSizeModifier(), getIndexTypeQualifier());
+ Profile(ID, getElementType(), getSizeModifier(),
+ getIndexTypeCVRQualifiers());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
@@ -1226,7 +1455,7 @@
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, getElementType(),
- getSizeModifier(), getIndexTypeQualifier(), getSizeExpr());
+ getSizeModifier(), getIndexTypeCVRQualifiers(), getSizeExpr());
}
static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
@@ -1709,7 +1938,7 @@
/// @brief Determines whether this type is in the process of being
/// defined.
bool isBeingDefined() const { return decl.getInt(); }
- void setBeingDefined(bool Def) { decl.setInt(Def? 1 : 0); }
+ void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -2206,41 +2435,119 @@
static bool classof(const ObjCObjectPointerType *) { return true; }
};
+/// A qualifier set is used to build a set of qualifiers.
+class QualifierCollector : public Qualifiers {
+ ASTContext *Context;
+
+public:
+ QualifierCollector(Qualifiers Qs = Qualifiers())
+ : Qualifiers(Qs), Context(0) {}
+ QualifierCollector(ASTContext &Context, Qualifiers Qs = Qualifiers())
+ : Qualifiers(Qs), Context(&Context) {}
+
+ void setContext(ASTContext &C) { Context = &C; }
+
+ /// Collect any qualifiers on the given type and return an
+ /// unqualified type.
+ const Type *strip(QualType QT) {
+ addFastQualifiers(QT.getFastQualifiers());
+ if (QT.hasNonFastQualifiers()) {
+ const ExtQuals *EQ = QT.getExtQualsUnsafe();
+ Context = &EQ->getContext();
+ addQualifiers(EQ->getQualifiers());
+ return EQ->getBaseType();
+ }
+ return QT.getTypePtrUnsafe();
+ }
+
+ /// Apply the collected qualifiers to the given type.
+ QualType apply(QualType QT) const;
+
+ /// Apply the collected qualifiers to the given type.
+ QualType apply(const Type* T) const;
+
+};
+
+
// Inline function definitions.
-/// getUnqualifiedType - Return the type without any qualifiers.
-inline QualType QualType::getUnqualifiedType() const {
- Type *TP = getTypePtr();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(TP))
- TP = EXTQT->getBaseType();
- return QualType(TP, 0);
+inline void QualType::removeConst() {
+ removeFastQualifiers(Qualifiers::Const);
+}
+
+inline void QualType::removeRestrict() {
+ removeFastQualifiers(Qualifiers::Restrict);
+}
+
+inline void QualType::removeVolatile() {
+ QualifierCollector Qc;
+ const Type *Ty = Qc.strip(*this);
+ if (Qc.hasVolatile()) {
+ Qc.removeVolatile();
+ *this = Qc.apply(Ty);
+ }
+}
+
+inline void QualType::removeCVRQualifiers(unsigned Mask) {
+ assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-fast qualifiers");
+
+ // Fast path: we don't need to touch the slow qualifiers.
+ if (!(Mask & ~Qualifiers::FastMask)) {
+ removeFastQualifiers(Mask);
+ return;
+ }
+
+ QualifierCollector Qc;
+ const Type *Ty = Qc.strip(*this);
+ Qc.removeCVRQualifiers(Mask);
+ *this = Qc.apply(Ty);
}
/// getAddressSpace - Return the address space of this type.
inline unsigned QualType::getAddressSpace() const {
+ if (hasNonFastQualifiers()) {
+ const ExtQuals *EQ = getExtQualsUnsafe();
+ if (EQ->hasAddressSpace())
+ return EQ->getAddressSpace();
+ }
+
QualType CT = getTypePtr()->getCanonicalTypeInternal();
+ if (CT.hasNonFastQualifiers()) {
+ const ExtQuals *EQ = CT.getExtQualsUnsafe();
+ if (EQ->hasAddressSpace())
+ return EQ->getAddressSpace();
+ }
+
if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
return AT->getElementType().getAddressSpace();
if (const RecordType *RT = dyn_cast<RecordType>(CT))
return RT->getAddressSpace();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT))
- return EXTQT->getAddressSpace();
return 0;
}
/// getObjCGCAttr - Return the gc attribute of this type.
-inline QualType::GCAttrTypes QualType::getObjCGCAttr() const {
+inline Qualifiers::GC QualType::getObjCGCAttr() const {
+ if (hasNonFastQualifiers()) {
+ const ExtQuals *EQ = getExtQualsUnsafe();
+ if (EQ->hasObjCGCAttr())
+ return EQ->getObjCGCAttr();
+ }
+
QualType CT = getTypePtr()->getCanonicalTypeInternal();
+ if (CT.hasNonFastQualifiers()) {
+ const ExtQuals *EQ = CT.getExtQualsUnsafe();
+ if (EQ->hasObjCGCAttr())
+ return EQ->getObjCGCAttr();
+ }
+
if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
return AT->getElementType().getObjCGCAttr();
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT))
- return EXTQT->getObjCGCAttr();
if (const ObjCObjectPointerType *PT = CT->getAs<ObjCObjectPointerType>())
return PT->getPointeeType().getObjCGCAttr();
// We most look at all pointer types, not just pointer to interface types.
if (const PointerType *PT = CT->getAs<PointerType>())
return PT->getPointeeType().getObjCGCAttr();
- return GCNone;
+ return Qualifiers::GCNone;
}
/// getNoReturnAttr - Returns true if the type has the noreturn attribute,
@@ -2262,6 +2569,7 @@
/// "int". However, it is not more qualified than "const volatile
/// int".
inline bool QualType::isMoreQualifiedThan(QualType Other) const {
+ // FIXME: work on arbitrary qualifiers
unsigned MyQuals = this->getCVRQualifiers();
unsigned OtherQuals = Other.getCVRQualifiers();
if (getAddressSpace() != Other.getAddressSpace())
@@ -2274,6 +2582,7 @@
/// int" is at least as qualified as "const int", "volatile int",
/// "int", and "const volatile int".
inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const {
+ // FIXME: work on arbitrary qualifiers
unsigned MyQuals = this->getCVRQualifiers();
unsigned OtherQuals = Other.getCVRQualifiers();
if (getAddressSpace() != Other.getAddressSpace())
@@ -2441,14 +2750,10 @@
return Ty;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<T>(CanonicalType)) {
- // Look through type qualifiers
- if (isa<T>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAs<T>();
+ if (!isa<T>(CanonicalType))
return 0;
- }
- // If this is a typedef for a pointer type, strip the typedef off without
+ // If this is a typedef for the type, strip the typedef off without
// losing all typedef information.
return cast<T>(getDesugaredType());
}
Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Thu Sep 24 14:53:00 2009
@@ -51,7 +51,6 @@
# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
#endif
-TYPE(ExtQual, Type)
TYPE(Builtin, Type)
TYPE(FixedWidthInt, Type)
TYPE(Complex, Type)
Modified: cfe/trunk/include/clang/Frontend/DocumentXML.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DocumentXML.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/DocumentXML.h (original)
+++ cfe/trunk/include/clang/Frontend/DocumentXML.h Thu Sep 24 14:53:00 2009
@@ -132,6 +132,7 @@
// for addAttributeOptional:
static bool isDefault(unsigned value) { return value == 0; }
static bool isDefault(bool value) { return !value; }
+ static bool isDefault(Qualifiers::GC value) { return value == Qualifiers::GCNone; }
static bool isDefault(const std::string& value) { return value.empty(); }
};
Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Sep 24 14:53:00 2009
@@ -206,7 +206,7 @@
///
/// When the pointer at index I is non-NULL, the type with
/// ID = (I + 1) << 3 has already been loaded from the PCH file.
- std::vector<Type *> TypesLoaded;
+ std::vector<QualType> TypesLoaded;
/// \brief Offset of each declaration within the bitstream, indexed
/// by the declaration ID (-1).
Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Thu Sep 24 14:53:00 2009
@@ -40,6 +40,24 @@
class SwitchCase;
class TargetInfo;
+/// A structure for putting "fast"-unqualified QualTypes into a
+/// DenseMap. This uses the standard pointer hash function.
+struct UnsafeQualTypeDenseMapInfo {
+ static inline bool isEqual(QualType A, QualType B) { return A == B; }
+ static inline bool isPod() { return true; }
+ static inline QualType getEmptyKey() {
+ return QualType::getFromOpaquePtr((void*) 1);
+ }
+ static inline QualType getTombstoneKey() {
+ return QualType::getFromOpaquePtr((void*) 2);
+ }
+ static inline unsigned getHashValue(QualType T) {
+ assert(!T.getFastQualifiers() && "hash invalid for types with fast quals");
+ uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
+ }
+};
+
/// \brief Writes a precompiled header containing the contents of a
/// translation unit.
///
@@ -76,9 +94,11 @@
///
/// The ID numbers of types are consecutive (in order of discovery)
/// and start at 1. 0 is reserved for NULL. When types are actually
- /// stored in the stream, the ID number is shifted by 3 bits to
- /// allow for the const/volatile/restrict qualifiers.
- llvm::DenseMap<const Type *, pch::TypeID> TypeIDs;
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ llvm::DenseMap<QualType, pch::TypeID, UnsafeQualTypeDenseMapInfo> TypeIDs;
/// \brief Offset of each type in the bitstream, indexed by
/// the type's ID.
@@ -89,7 +109,7 @@
/// \brief Queue containing the types that we still need to
/// emit.
- std::queue<const Type *> TypesToEmit;
+ std::queue<QualType> TypesToEmit;
/// \brief Map that provides the ID numbers of each identifier in
/// the output stream.
@@ -168,7 +188,7 @@
const char* isysroot);
void WritePreprocessor(const Preprocessor &PP);
void WriteComments(ASTContext &Context);
- void WriteType(const Type *T);
+ void WriteType(QualType T);
void WriteTypesBlock(ASTContext &Context);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
Modified: cfe/trunk/include/clang/Frontend/TypeXML.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/TypeXML.def?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/TypeXML.def (original)
+++ cfe/trunk/include/clang/Frontend/TypeXML.def Thu Sep 24 14:53:00 2009
@@ -68,17 +68,8 @@
ATTRIBUTE_OPT_XML(isConstQualified(), "const") // boolean
ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile") // boolean
ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict") // boolean
-END_NODE_XML
-
-NODE_XML(ExtQualType, "ExtQualType")
- ID_ATTRIBUTE_XML
- TYPE_ATTRIBUTE_XML(getBaseType())
- ATTRIBUTE_OPT_XML(getAddressSpace(), "adress_space") // unsigned: Address Space ID - The address space ID this type is qualified with.
- ATTRIBUTE_ENUM_OPT_XML(getObjCGCAttr(), "objc_gc") // GC __weak/__strong attributes
- ENUM_XML(QualType::GCNone, "")
- ENUM_XML(QualType::Weak, "weak")
- ENUM_XML(QualType::Strong, "strong")
- END_ENUM_XML
+ ATTRIBUTE_OPT_XML(getObjCGCAttr(), "objc_gc") // Qualifiers::GC
+ ATTRIBUTE_OPT_XML(getAddressSpace(), "address_space") // unsigned
END_NODE_XML
NODE_XML(BuiltinType, "FundamentalType")
@@ -175,7 +166,7 @@
ENUM_XML(ArrayType::Static, "static")
ENUM_XML(ArrayType::Star, "star")
END_ENUM_XML
- ATTRIBUTE_OPT_XML(getIndexTypeQualifier(), "index_type_qualifier") // unsigned
+ ATTRIBUTE_OPT_XML(getIndexTypeCVRQualifiers(), "index_type_qualifier") // unsigned
END_NODE_XML
NODE_XML(IncompleteArrayType, "IncompleteArrayType")
Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Thu Sep 24 14:53:00 2009
@@ -90,7 +90,7 @@
};
// type-qualifiers
- enum TQ { // NOTE: These flags must be kept in sync with QualType::TQ.
+ enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ.
TQ_unspecified = 0,
TQ_const = 1,
TQ_restrict = 2,
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Sep 24 14:53:00 2009
@@ -59,6 +59,13 @@
}
{
+ 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 @@
/// 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 @@
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 @@
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
-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();
- }
+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;
- ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
+ ExtQuals::Profile(ID, TypeNode, Quals);
void *InsertPos = 0;
- if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(EXTQy, CVRQuals);
+ if (ExtQuals *EQ = ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos)) {
+ assert(EQ->getQualifiers() == Quals);
+ QualType T = QualType(EQ, Fast);
+ return T;
+ }
- // 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);
+ ExtQuals *New = new (*this, 8) ExtQuals(*this, TypeNode, Quals);
+ ExtQualNodes.InsertNode(New, InsertPos);
+ QualType T = QualType(New, Fast);
+ return T;
+}
- // 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);
+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 ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
+
+ // 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);
+
+ 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 @@
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 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 we are composing extended qualifiers together, merge together
+ // into one ExtQuals node.
+ QualifierCollector Quals;
+ const Type *TypeNode = Quals.strip(T);
+
+ // 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 @@
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 @@
/// 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 @@
DSAT->getSizeExpr() ?
DSAT->getSizeExpr()->Retain() : 0,
DSAT->getSizeModifier(),
- DSAT->getIndexTypeQualifier(),
+ DSAT->getIndexTypeCVRQualifiers(),
DSAT->getBracketsRange()));
VariableArrayType *VAT = cast<VariableArrayType>(AT);
@@ -2199,7 +2190,7 @@
VAT->getSizeExpr() ?
VAT->getSizeExpr()->Retain() : 0,
VAT->getSizeModifier(),
- VAT->getIndexTypeQualifier(),
+ VAT->getIndexTypeCVRQualifiers(),
VAT->getBracketsRange()));
}
@@ -2316,68 +2307,47 @@
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 @@
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 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 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 @@
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 @@
/// 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 @@
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 @@
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 @@
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 @@
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;
}
}
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Sep 24 14:53:00 2009
@@ -146,7 +146,7 @@
}
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 @@
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 @@
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 @@
if (PointeeType.getUnqualifiedType() != ClassTy)
return false;
+ // FIXME: other qualifiers?
+
// We have a copy constructor.
TypeQuals = PointeeType.getCVRQualifiers();
return true;
Modified: cfe/trunk/lib/AST/DeclarationName.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclarationName.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclarationName.cpp (original)
+++ cfe/trunk/lib/AST/DeclarationName.cpp Thu Sep 24 14:53:00 2009
@@ -309,11 +309,11 @@
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;
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Sep 24 14:53:00 2009
@@ -825,7 +825,7 @@
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 @@
// 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 @@
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 @@
// 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);
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Sep 24 14:53:00 2009
@@ -783,7 +783,7 @@
// 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);
Modified: cfe/trunk/lib/AST/StmtDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtDumper.cpp (original)
+++ cfe/trunk/lib/AST/StmtDumper.cpp Thu Sep 24 14:53:00 2009
@@ -87,13 +87,10 @@
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) {
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Sep 24 14:53:00 2009
@@ -101,12 +101,8 @@
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 @@
/// 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 @@
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 @@
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::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 @@
// 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 @@
return cast<RecordType>(getDesugaredType());
}
- // Look through type qualifiers
- if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAsUnionType();
return 0;
}
@@ -416,8 +380,6 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
return true;
}
- if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CanonicalType))
- return EXTQT->getBaseType()->isAggregateType();
return isa<ArrayType>(CanonicalType);
}
@@ -620,8 +556,6 @@
/// 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::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 @@
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 @@
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 @@
Args[Idx].Profile(ID, Context);
}
-const Type *QualifierSet::strip(const Type* T) {
- QualType DT = T->getDesugaredType();
- addCVR(DT.getCVRQualifiers());
-
- 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);
- }
+QualType QualifierCollector::apply(QualType QT) const {
+ if (!hasNonFastQualifiers())
+ return QT.withFastQualifiers(getFastQualifiers());
+
+ 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 @@
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 @@
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 @@
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 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 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 @@
}
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'.
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Thu Sep 24 14:53:00 2009
@@ -1686,8 +1686,8 @@
// 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);
}
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Sep 24 14:53:00 2009
@@ -629,7 +629,7 @@
(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.
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Sep 24 14:53:00 2009
@@ -788,7 +788,6 @@
case Type::RValueReference:
case Type::Vector:
case Type::ExtVector:
- case Type::ExtQual:
case Type::FixedWidthInt:
case Type::MemberPointer:
case Type::TemplateSpecialization:
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Sep 24 14:53:00 2009
@@ -166,9 +166,7 @@
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 @@
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 @@
}
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 @@
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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
"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 @@
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 @@
// 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 @@
// 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 @@
// 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()));
}
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Sep 24 14:53:00 2009
@@ -181,7 +181,7 @@
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 @@
return;
}
- EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, 0));
+ EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, Qualifiers()));
}
void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
@@ -429,15 +429,16 @@
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;
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Sep 24 14:53:00 2009
@@ -791,8 +791,7 @@
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 {
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Thu Sep 24 14:53:00 2009
@@ -112,6 +112,9 @@
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 @@
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 @@
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 @@
}
// 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 @@
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.
Modified: cfe/trunk/lib/CodeGen/CGValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGValue.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGValue.h (original)
+++ cfe/trunk/lib/CodeGen/CGValue.h Thu Sep 24 14:53:00 2009
@@ -118,12 +118,6 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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;
}
};
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Sep 24 14:53:00 2009
@@ -496,6 +496,12 @@
// 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,
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Thu Sep 24 14:53:00 2009
@@ -267,7 +267,7 @@
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 @@
}
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 @@
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
Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Thu Sep 24 14:53:00 2009
@@ -84,7 +84,7 @@
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 @@
// 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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
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>
Modified: cfe/trunk/lib/Frontend/DocumentXML.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/DocumentXML.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/DocumentXML.cpp (original)
+++ cfe/trunk/lib/Frontend/DocumentXML.cpp Thu Sep 24 14:53:00 2009
@@ -135,7 +135,7 @@
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 @@
{
addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
- if (pType.getCVRQualifiers() == 0)
+ if (!pType.hasQualifiers())
{
Types[pType] = BasicTypes[pType.getTypePtr()];
}
Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Sep 24 14:53:00 2009
@@ -1764,18 +1764,11 @@
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::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 @@
}
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 @@
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);
Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Sep 24 14:53:00 2009
@@ -64,13 +64,6 @@
};
}
-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::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 @@
//===----------------------------------------------------------------------===//
/// \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 @@
// 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 @@
// 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 @@
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 @@
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) {
Modified: cfe/trunk/lib/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/RewriteObjC.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Frontend/RewriteObjC.cpp Thu Sep 24 14:53:00 2009
@@ -1937,8 +1937,7 @@
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::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::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);
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Sep 24 14:53:00 2009
@@ -44,9 +44,7 @@
// If this is a sugared type (like a typedef, typeof, etc), then unwrap one
// level of the sugar so that the type is more obvious to the user.
- QualType DesugaredTy = Ty->getDesugaredType(true);
- DesugaredTy.setCVRQualifiers(DesugaredTy.getCVRQualifiers() |
- Ty.getCVRQualifiers());
+ QualType DesugaredTy = Ty.getDesugaredType(true);
if (Ty != DesugaredTy &&
// If the desugared type is a vector type, we don't want to expand it,
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Thu Sep 24 14:53:00 2009
@@ -186,12 +186,12 @@
"Destination type is not pointer or pointer to member.");
QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType;
- llvm::SmallVector<unsigned, 8> cv1, cv2;
+ llvm::SmallVector<Qualifiers, 8> cv1, cv2;
// Find the qualifications.
while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
- cv1.push_back(UnwrappedSrcType.getCVRQualifiers());
- cv2.push_back(UnwrappedDestType.getCVRQualifiers());
+ cv1.push_back(UnwrappedSrcType.getQualifiers());
+ cv2.push_back(UnwrappedDestType.getQualifiers());
}
assert(cv1.size() > 0 && "Must have at least one pointer level.");
@@ -199,13 +199,14 @@
// unwrapping, of course).
QualType SrcConstruct = Self.Context.VoidTy;
QualType DestConstruct = Self.Context.VoidTy;
- for (llvm::SmallVector<unsigned, 8>::reverse_iterator i1 = cv1.rbegin(),
- i2 = cv2.rbegin();
+ ASTContext &Context = Self.Context;
+ for (llvm::SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
+ i2 = cv2.rbegin();
i1 != cv1.rend(); ++i1, ++i2) {
- SrcConstruct = Self.Context.getPointerType(
- SrcConstruct.getQualifiedType(*i1));
- DestConstruct = Self.Context.getPointerType(
- DestConstruct.getQualifiedType(*i2));
+ SrcConstruct
+ = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
+ DestConstruct
+ = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
}
// Test if they're compatible.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 24 14:53:00 2009
@@ -1814,14 +1814,16 @@
// constant expression folding, like struct {char x[(int)(char*)2];}
SizeIsNegative = false;
- if (const PointerType* PTy = dyn_cast<PointerType>(T)) {
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T);
+
+ if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
QualType Pointee = PTy->getPointeeType();
QualType FixedType =
TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative);
if (FixedType.isNull()) return FixedType;
FixedType = Context.getPointerType(FixedType);
- FixedType.setCVRQualifiers(T.getCVRQualifiers());
- return FixedType;
+ return Qs.apply(FixedType);
}
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
@@ -2968,7 +2970,7 @@
// char const * const *
// char * const *
- QualifierSet qs;
+ QualifierCollector qs;
const PointerType* PT;
if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
(PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 24 14:53:00 2009
@@ -2046,13 +2046,13 @@
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
if (FTI.TypeQuals != 0) {
- if (FTI.TypeQuals & QualType::Const)
+ if (FTI.TypeQuals & Qualifiers::Const)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
<< "const" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Volatile)
+ if (FTI.TypeQuals & Qualifiers::Volatile)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
<< "volatile" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Restrict)
+ if (FTI.TypeQuals & Qualifiers::Restrict)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
<< "restrict" << SourceRange(D.getIdentifierLoc());
}
@@ -2159,13 +2159,13 @@
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
if (FTI.TypeQuals != 0 && !D.isInvalidType()) {
- if (FTI.TypeQuals & QualType::Const)
+ if (FTI.TypeQuals & Qualifiers::Const)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
<< "const" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Volatile)
+ if (FTI.TypeQuals & Qualifiers::Volatile)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
<< "volatile" << SourceRange(D.getIdentifierLoc());
- if (FTI.TypeQuals & QualType::Restrict)
+ if (FTI.TypeQuals & Qualifiers::Restrict)
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
<< "restrict" << SourceRange(D.getIdentifierLoc());
D.setInvalidType();
@@ -2844,10 +2844,8 @@
// If class's assignment operator argument is const/volatile qualified,
// look for operator = (const/volatile B&). Otherwise, look for
// operator = (B&).
- if (ParmDecl->getType().isConstQualified())
- RHSType.addConst();
- if (ParmDecl->getType().isVolatileQualified())
- RHSType.addVolatile();
+ RHSType = Context.getCVRQualifiedType(RHSType,
+ ParmDecl->getType().getCVRQualifiers());
ExprOwningPtr<Expr> LHS(this, new (Context) DeclRefExpr(ParmDecl,
LHSType,
SourceLocation()));
@@ -3575,7 +3573,7 @@
// -- Otherwise, the reference shall be to a non-volatile const
// type (i.e., cv1 shall be const), or the reference shall be an
// rvalue reference and the initializer expression shall be an rvalue.
- if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) {
+ if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
if (!ICS)
Diag(DeclLoc, diag::err_not_reference_to_const_init)
<< T1 << (InitLvalue != Expr::LV_Valid? "temporary" : "value")
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Sep 24 14:53:00 2009
@@ -566,7 +566,7 @@
// of the anonymous union objects and, eventually, the field we
// found via name lookup.
bool BaseObjectIsPointer = false;
- unsigned ExtraQuals = 0;
+ Qualifiers BaseQuals;
if (BaseObject) {
// BaseObject is an anonymous struct/union variable (and is,
// therefore, not part of another non-anonymous record).
@@ -574,8 +574,8 @@
MarkDeclarationReferenced(Loc, BaseObject);
BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
SourceLocation());
- ExtraQuals
- = Context.getCanonicalType(BaseObject->getType()).getCVRQualifiers();
+ BaseQuals
+ = Context.getCanonicalType(BaseObject->getType()).getQualifiers();
} else if (BaseObjectExpr) {
// The caller provided the base object expression. Determine
// whether its a pointer and whether it adds any qualifiers to the
@@ -585,7 +585,8 @@
BaseObjectIsPointer = true;
ObjectType = ObjectPtr->getPointeeType();
}
- ExtraQuals = Context.getCanonicalType(ObjectType).getCVRQualifiers();
+ BaseQuals
+ = Context.getCanonicalType(ObjectType).getQualifiers();
} else {
// We've found a member of an anonymous struct/union that is
// inside a non-anonymous struct/union, so in a well-formed
@@ -608,7 +609,7 @@
return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method)
<< Field->getDeclName());
}
- ExtraQuals = MD->getTypeQualifiers();
+ BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
}
if (!BaseObjectExpr)
@@ -619,24 +620,35 @@
// Build the implicit member references to the field of the
// anonymous struct/union.
Expr *Result = BaseObjectExpr;
- unsigned BaseAddrSpace = BaseObjectExpr->getType().getAddressSpace();
+ Qualifiers ResultQuals = BaseQuals;
for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
FI = AnonFields.rbegin(), FIEnd = AnonFields.rend();
FI != FIEnd; ++FI) {
QualType MemberType = (*FI)->getType();
- if (!(*FI)->isMutable()) {
- unsigned combinedQualifiers
- = MemberType.getCVRQualifiers() | ExtraQuals;
- MemberType = MemberType.getQualifiedType(combinedQualifiers);
- }
- if (BaseAddrSpace != MemberType.getAddressSpace())
- MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
+ Qualifiers MemberTypeQuals =
+ Context.getCanonicalType(MemberType).getQualifiers();
+
+ // CVR attributes from the base are picked up by members,
+ // except that 'mutable' members don't pick up 'const'.
+ if ((*FI)->isMutable())
+ ResultQuals.removeConst();
+
+ // GC attributes are never picked up by members.
+ ResultQuals.removeObjCGCAttr();
+
+ // TR 18037 does not allow fields to be declared with address spaces.
+ assert(!MemberTypeQuals.hasAddressSpace());
+
+ Qualifiers NewQuals = ResultQuals + MemberTypeQuals;
+ if (NewQuals != MemberTypeQuals)
+ MemberType = Context.getQualifiedType(MemberType, NewQuals);
+
MarkDeclarationReferenced(Loc, *FI);
// FIXME: Might this end up being a qualified name?
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
OpLoc, MemberType);
BaseObjectIsPointer = false;
- ExtraQuals = Context.getCanonicalType(MemberType).getCVRQualifiers();
+ ResultQuals = NewQuals;
}
return Owned(Result);
@@ -948,11 +960,10 @@
if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
MemberType = RefType->getPointeeType();
- else if (!FD->isMutable()) {
- unsigned combinedQualifiers
- = MemberType.getCVRQualifiers() | MD->getTypeQualifiers();
- MemberType = MemberType.getQualifiedType(combinedQualifiers);
- }
+ else if (!FD->isMutable())
+ MemberType
+ = Context.getQualifiedType(MemberType,
+ Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (!Method->isStatic()) {
Ctx = Method->getParent();
@@ -1135,7 +1146,7 @@
// - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent
else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) {
- if (Dcl->getType().getCVRQualifiers() == QualType::Const &&
+ if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const &&
Dcl->getInit()) {
ValueDependent = Dcl->getInit()->isValueDependent();
}
@@ -1174,7 +1185,7 @@
PredefinedExpr::ComputeName(Context, IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
- ResTy = Context.CharTy.getQualifiedType(QualType::Const);
+ ResTy = Context.CharTy.withConst();
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0);
}
return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
@@ -2235,14 +2246,16 @@
if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
MemberType = Ref->getPointeeType();
else {
- unsigned BaseAddrSpace = BaseType.getAddressSpace();
- unsigned combinedQualifiers =
- MemberType.getCVRQualifiers() | BaseType.getCVRQualifiers();
- if (FD->isMutable())
- combinedQualifiers &= ~QualType::Const;
- MemberType = MemberType.getQualifiedType(combinedQualifiers);
- if (BaseAddrSpace != MemberType.getAddressSpace())
- MemberType = Context.getAddrSpaceQualType(MemberType, BaseAddrSpace);
+ Qualifiers BaseQuals = BaseType.getQualifiers();
+ BaseQuals.removeObjCGCAttr();
+ if (FD->isMutable()) BaseQuals.removeConst();
+
+ Qualifiers MemberQuals
+ = Context.getCanonicalType(MemberType).getQualifiers();
+
+ Qualifiers Combined = BaseQuals + MemberQuals;
+ if (Combined != MemberQuals)
+ MemberType = Context.getQualifiedType(MemberType, Combined);
}
MarkDeclarationReferenced(MemberLoc, FD);
@@ -3510,7 +3523,8 @@
if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
- QualType destPointee = lhptee.getQualifiedType(rhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(LHS, destType); // add qualifiers if necessary
ImpCastExprToType(RHS, destType); // promote to void*
@@ -3519,7 +3533,8 @@
if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
- QualType destPointee = rhptee.getQualifiedType(lhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(RHS, destType); // add qualifiers if necessary
ImpCastExprToType(LHS, destType); // promote to void*
@@ -3534,14 +3549,16 @@
// ignore qualifiers on void (C99 6.5.15p3, clause 6)
if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
// Figure out necessary qualifiers (C99 6.5.15p6)
- QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(LHS, destType); // add qualifiers if necessary
ImpCastExprToType(RHS, destType); // promote to void*
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
- QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers());
+ QualType destPointee
+ = Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
ImpCastExprToType(LHS, destType); // add qualifiers if necessary
ImpCastExprToType(RHS, destType); // promote to void*
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Sep 24 14:53:00 2009
@@ -972,7 +972,7 @@
= ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
// This conversion is considered only when there is an
// explicit appropriate pointer target type (C++ 4.2p2).
- if (ToPtrType->getPointeeType().getCVRQualifiers() == 0 &&
+ if (!ToPtrType->getPointeeType().hasQualifiers() &&
((StrLit->isWide() && ToPointeeType->isWideCharType()) ||
(!StrLit->isWide() &&
(ToPointeeType->getKind() == BuiltinType::Char_U ||
@@ -1316,10 +1316,7 @@
// argument.
// We probably need a "MemberFunctionClosureType" or something like that.
QualType Result = MemPtr->getPointeeType();
- if (LType.isConstQualified())
- Result.addConst();
- if (LType.isVolatileQualified())
- Result.addVolatile();
+ Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
return Result;
}
@@ -1662,14 +1659,33 @@
if (LMemPtr && RMemPtr) {
QualType LPointee = LMemPtr->getPointeeType();
QualType RPointee = RMemPtr->getPointeeType();
+
+ QualifierCollector LPQuals, RPQuals;
+ const Type *LPCan = LPQuals.strip(Context.getCanonicalType(LPointee));
+ const Type *RPCan = RPQuals.strip(Context.getCanonicalType(RPointee));
+
// First, we check that the unqualified pointee type is the same. If it's
// not, there's no conversion that will unify the two pointers.
- if (Context.getCanonicalType(LPointee).getUnqualifiedType() ==
- Context.getCanonicalType(RPointee).getUnqualifiedType()) {
- // Second, we take the greater of the two cv qualifications. If neither
+ if (LPCan == RPCan) {
+
+ // Second, we take the greater of the two qualifications. If neither
// is greater than the other, the conversion is not possible.
- unsigned Q = LPointee.getCVRQualifiers() | RPointee.getCVRQualifiers();
- if (Q == LPointee.getCVRQualifiers() || Q == RPointee.getCVRQualifiers()){
+
+ Qualifiers MergedQuals = LPQuals + RPQuals;
+
+ bool CompatibleQuals = true;
+ if (MergedQuals.getCVRQualifiers() != LPQuals.getCVRQualifiers() &&
+ MergedQuals.getCVRQualifiers() != RPQuals.getCVRQualifiers())
+ CompatibleQuals = false;
+ else if (LPQuals.getAddressSpace() != RPQuals.getAddressSpace())
+ // FIXME:
+ // C99 6.5.15 as modified by TR 18037:
+ // If the second and third operands are pointers into different
+ // address spaces, the address spaces must overlap.
+ CompatibleQuals = false;
+ // FIXME: GC qualifiers?
+
+ if (CompatibleQuals) {
// Third, we check if either of the container classes is derived from
// the other.
QualType LContainer(LMemPtr->getClass(), 0);
@@ -1687,8 +1703,9 @@
// The type 'Q Pointee (MoreDerived::*)' is the common type.
// We don't use ImpCastExprToType here because this could still fail
// for ambiguous or inaccessible conversions.
- QualType Common = Context.getMemberPointerType(
- LPointee.getQualifiedType(Q), MoreDerived.getTypePtr());
+ LPointee = Context.getQualifiedType(LPointee, MergedQuals);
+ QualType Common
+ = Context.getMemberPointerType(LPointee, MoreDerived.getTypePtr());
if (PerformImplicitConversion(LHS, Common, "converting"))
return QualType();
if (PerformImplicitConversion(RHS, Common, "converting"))
@@ -1750,6 +1767,7 @@
// What we do here is, we build the two possible composite types, and try the
// conversions in both directions. If only one works, or if the two composite
// types are the same, we have succeeded.
+ // FIXME: extended qualifiers?
llvm::SmallVector<unsigned, 4> QualifierUnion;
llvm::SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass;
QualType Composite1 = T1, Composite2 = T2;
@@ -1790,16 +1808,21 @@
I = QualifierUnion.begin(),
E = QualifierUnion.end();
I != E; (void)++I, ++MOC) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(*I);
if (MOC->first && MOC->second) {
// Rebuild member pointer type
- Composite1 = Context.getMemberPointerType(Composite1.getQualifiedType(*I),
- MOC->first);
- Composite2 = Context.getMemberPointerType(Composite2.getQualifiedType(*I),
- MOC->second);
+ Composite1 = Context.getMemberPointerType(
+ Context.getQualifiedType(Composite1, Quals),
+ MOC->first);
+ Composite2 = Context.getMemberPointerType(
+ Context.getQualifiedType(Composite2, Quals),
+ MOC->second);
} else {
// Rebuild pointer type
- Composite1 = Context.getPointerType(Composite1.getQualifiedType(*I));
- Composite2 = Context.getPointerType(Composite2.getQualifiedType(*I));
+ Composite1
+ = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
+ Composite2
+ = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
}
}
Modified: cfe/trunk/lib/Sema/SemaInherit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInherit.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInherit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInherit.cpp Thu Sep 24 14:53:00 2009
@@ -59,7 +59,7 @@
/// an unqualified, canonical class type.
bool BasePaths::isAmbiguous(QualType BaseType) {
assert(BaseType->isCanonical() && "Base type must be the canonical type");
- assert(BaseType.getCVRQualifiers() == 0 && "Base type must be unqualified");
+ assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified");
std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Sep 24 14:53:00 2009
@@ -856,12 +856,12 @@
ASTContext &Context) {
QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType());
QualType CanonToPointee = Context.getCanonicalType(ToPointee);
- unsigned Quals = CanonFromPointee.getCVRQualifiers();
+ Qualifiers Quals = CanonFromPointee.getQualifiers();
// Exact qualifier match -> return the pointer type we're converting to.
- if (CanonToPointee.getCVRQualifiers() == Quals) {
+ if (CanonToPointee.getQualifiers() == Quals) {
// ToType is exactly what we need. Return it.
- if (ToType.getTypePtr())
+ if (!ToType.isNull())
return ToType;
// Build a pointer to ToPointee. It has the right qualifiers
@@ -870,7 +870,8 @@
}
// Just build a canonical type that has the right qualifiers.
- return Context.getPointerType(CanonToPointee.getQualifiedType(Quals));
+ return Context.getPointerType(
+ Context.getQualifiedType(CanonToPointee.getUnqualifiedType(), Quals));
}
static bool isNullPointerConstantForConversion(Expr *Expr,
@@ -2022,8 +2023,8 @@
ImplicitConversionSequence
Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) {
QualType ClassType = Context.getTypeDeclType(Method->getParent());
- unsigned MethodQuals = Method->getTypeQualifiers();
- QualType ImplicitParamType = ClassType.getQualifiedType(MethodQuals);
+ QualType ImplicitParamType
+ = Context.getCVRQualifiedType(ClassType, Method->getTypeQualifiers());
// Set up the conversion sequence as a "bad" conversion, to allow us
// to exit early.
@@ -2831,27 +2832,27 @@
/// restrict *", and "int const volatile restrict *" to the set of
/// pointer types. Returns true if the add of @p Ty itself succeeded,
/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
bool
BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) {
+
// Insert this type.
if (!PointerTypes.insert(Ty))
return false;
- if (const PointerType *PointerTy = Ty->getAs<PointerType>()) {
- QualType PointeeTy = PointerTy->getPointeeType();
- // FIXME: Optimize this so that we don't keep trying to add the same types.
+ const PointerType *PointerTy = Ty->getAs<PointerType>();
+ assert(PointerTy && "type was not a pointer type!");
- // FIXME: Do we have to add CVR qualifiers at *all* levels to deal with all
- // pointer conversions that don't cast away constness?
- if (!PointeeTy.isConstQualified())
- AddPointerWithMoreQualifiedTypeVariants
- (Context.getPointerType(PointeeTy.withConst()));
- if (!PointeeTy.isVolatileQualified())
- AddPointerWithMoreQualifiedTypeVariants
- (Context.getPointerType(PointeeTy.withVolatile()));
- if (!PointeeTy.isRestrictQualified())
- AddPointerWithMoreQualifiedTypeVariants
- (Context.getPointerType(PointeeTy.withRestrict()));
+ QualType PointeeTy = PointerTy->getPointeeType();
+ unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+
+ // Iterate through all strict supersets of BaseCVR.
+ for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+ if ((CVR | BaseCVR) != CVR) continue;
+
+ QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+ PointerTypes.insert(Context.getPointerType(QPointeeTy));
}
return true;
@@ -2864,6 +2865,8 @@
/// restrict *", and "int const volatile restrict *" to the set of
/// pointer types. Returns true if the add of @p Ty itself succeeded,
/// false otherwise.
+///
+/// FIXME: what to do about extended qualifiers?
bool
BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
QualType Ty) {
@@ -2871,20 +2874,20 @@
if (!MemberPointerTypes.insert(Ty))
return false;
- if (const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>()) {
- QualType PointeeTy = PointerTy->getPointeeType();
- const Type *ClassTy = PointerTy->getClass();
- // FIXME: Optimize this so that we don't keep trying to add the same types.
+ const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
+ assert(PointerTy && "type was not a member pointer type!");
+
+ QualType PointeeTy = PointerTy->getPointeeType();
+ const Type *ClassTy = PointerTy->getClass();
- 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));
+ // Iterate through all strict supersets of the pointee type's CVR
+ // qualifiers.
+ unsigned BaseCVR = PointeeTy.getCVRQualifiers();
+ for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
+ if ((CVR | BaseCVR) != CVR) continue;
+
+ QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
+ MemberPointerTypes.insert(Context.getMemberPointerType(QPointeeTy, ClassTy));
}
return true;
@@ -2924,7 +2927,8 @@
// Add 'cv void*' to our set of types.
if (!Ty->isVoidType()) {
QualType QualVoid
- = Context.VoidTy.getQualifiedType(PointeeTy.getCVRQualifiers());
+ = Context.getCVRQualifiedType(Context.VoidTy,
+ PointeeTy.getCVRQualifiers());
AddPointerWithMoreQualifiedTypeVariants(Context.getPointerType(QualVoid));
}
@@ -2936,7 +2940,8 @@
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
Base != ClassDecl->bases_end(); ++Base) {
QualType BaseTy = Context.getCanonicalType(Base->getType());
- BaseTy = BaseTy.getQualifiedType(PointeeTy.getCVRQualifiers());
+ BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(),
+ PointeeTy.getCVRQualifiers());
// Add the pointer type, recursively, so that we get all of
// the indirect base classes, too.
@@ -2997,7 +3002,8 @@
if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
// volatile T& operator=(volatile T&, T)
- ParamTypes[0] = S.Context.getLValueReferenceType(T.withVolatile());
+ ParamTypes[0]
+ = S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
ParamTypes[1] = T;
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssignmentOperator=*/true);
@@ -3119,7 +3125,8 @@
AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
// Volatile version
- ParamTypes[0] = Context.getLValueReferenceType(ArithTy.withVolatile());
+ ParamTypes[0]
+ = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
if (NumArgs == 1)
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
@@ -3154,7 +3161,8 @@
if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
// With volatile
- ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
+ ParamTypes[0]
+ = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
if (NumArgs == 1)
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
@@ -3465,7 +3473,8 @@
if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
// volatile version
- ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
+ ParamTypes[0]
+ = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
}
@@ -3498,7 +3507,7 @@
/*IsAssigmentOperator=*/Op == OO_Equal);
// Add this built-in operator as a candidate (VQ is 'volatile').
- ParamTypes[0] = ArithmeticTypes[Left].withVolatile();
+ ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]);
ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
@@ -3536,7 +3545,7 @@
// Add this built-in operator as a candidate (VQ is 'volatile').
ParamTypes[0] = ArithmeticTypes[Left];
- ParamTypes[0].addVolatile();
+ ParamTypes[0] = Context.getVolatileType(ParamTypes[0]);
ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
}
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Sep 24 14:53:00 2009
@@ -1295,22 +1295,19 @@
TypeWithHandler(const QualType &type, CXXCatchStmt *statement)
: t(type), stmt(statement) {}
+ // An arbitrary order is fine as long as it places identical
+ // types next to each other.
bool operator<(const TypeWithHandler &y) const {
- if (t.getTypePtr() < y.t.getTypePtr())
+ if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr())
return true;
- else if (t.getTypePtr() > y.t.getTypePtr())
- return false;
- else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
- return true;
- else if (t.getCVRQualifiers() < y.t.getCVRQualifiers())
+ if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr())
return false;
else
return getTypeSpecStartLoc() < y.getTypeSpecStartLoc();
}
bool operator==(const TypeWithHandler& other) const {
- return t.getTypePtr() == other.t.getTypePtr()
- && t.getCVRQualifiers() == other.t.getCVRQualifiers();
+ return t == other.t;
}
QualType getQualType() const { return t; }
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Sep 24 14:53:00 2009
@@ -300,28 +300,30 @@
}
/// \brief Returns a completely-unqualified array type, capturing the
-/// qualifiers in CVRQuals.
+/// qualifiers in Quals.
///
/// \param Context the AST context in which the array type was built.
///
/// \param T a canonical type that may be an array type.
///
-/// \param CVRQuals will receive the set of const/volatile/restrict qualifiers
-/// that were applied to the element type of the array.
+/// \param Quals will receive the full set of qualifiers that were
+/// applied to the element type of the array.
///
/// \returns if \p T is an array type, the completely unqualified array type
/// that corresponds to T. Otherwise, returns T.
static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
- unsigned &CVRQuals) {
+ Qualifiers &Quals) {
assert(T->isCanonical() && "Only operates on canonical types");
if (!isa<ArrayType>(T)) {
- CVRQuals = T.getCVRQualifiers();
+ Quals = T.getQualifiers();
return T.getUnqualifiedType();
}
+ assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
+
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
QualType Elt = getUnqualifiedArrayType(Context, CAT->getElementType(),
- CVRQuals);
+ Quals);
if (Elt == CAT->getElementType())
return T;
@@ -331,7 +333,7 @@
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
QualType Elt = getUnqualifiedArrayType(Context, IAT->getElementType(),
- CVRQuals);
+ Quals);
if (Elt == IAT->getElementType())
return T;
@@ -340,7 +342,7 @@
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
QualType Elt = getUnqualifiedArrayType(Context, DSAT->getElementType(),
- CVRQuals);
+ Quals);
if (Elt == DSAT->getElementType())
return T;
@@ -387,9 +389,9 @@
// referred to by the reference) can be more cv-qualified than the
// transformed A.
if (TDF & TDF_ParamWithReferenceType) {
- unsigned ExtraQualsOnParam
- = Param.getCVRQualifiers() & ~Arg.getCVRQualifiers();
- Param.setCVRQualifiers(Param.getCVRQualifiers() & ~ExtraQualsOnParam);
+ Qualifiers Quals = Param.getQualifiers();
+ Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiers());
+ Param = Context.getQualifiedType(Param.getUnqualifiedType(), Quals);
}
// If the parameter type is not dependent, there is nothing to deduce.
@@ -418,10 +420,10 @@
// top level, so they can be matched with the qualifiers on the parameter.
// FIXME: address spaces, ObjC GC qualifiers
if (isa<ArrayType>(Arg)) {
- unsigned CVRQuals = 0;
- Arg = getUnqualifiedArrayType(Context, Arg, CVRQuals);
- if (CVRQuals) {
- Arg = Arg.getWithAdditionalQualifiers(CVRQuals);
+ Qualifiers Quals;
+ Arg = getUnqualifiedArrayType(Context, Arg, Quals);
+ if (Quals) {
+ Arg = Context.getQualifiedType(Arg, Quals);
RecanonicalizeArg = true;
}
}
@@ -437,8 +439,8 @@
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
- unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers();
- QualType DeducedType = Arg.getQualifiedType(Quals);
+ QualType DeducedType = Arg;
+ DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
if (RecanonicalizeArg)
DeducedType = Context.getCanonicalType(DeducedType);
@@ -2022,13 +2024,6 @@
T = SemaRef.Context.getCanonicalType(T);
switch (T->getTypeClass()) {
- case Type::ExtQual:
- MarkUsedTemplateParameters(SemaRef,
- QualType(cast<ExtQualType>(T)->getBaseType(), 0),
- OnlyDeduced,
- Used);
- break;
-
case Type::Pointer:
MarkUsedTemplateParameters(SemaRef,
cast<PointerType>(T)->getPointeeType(),
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Sep 24 14:53:00 2009
@@ -496,7 +496,7 @@
PredefinedExpr::ComputeName(getSema().Context, IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
- QualType ResTy = getSema().Context.CharTy.getQualifiedType(QualType::Const);
+ QualType ResTy = getSema().Context.CharTy.withConst();
ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI,
ArrayType::Normal, 0);
PredefinedExpr *PE =
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Sep 24 14:53:00 2009
@@ -312,7 +312,7 @@
// Enforce C99 6.7.3p2: "Types other than pointer types derived from object
// or incomplete types shall not be restrict-qualified." C++ also allows
// restrict-qualified references.
- if (TypeQuals & QualType::Restrict) {
+ if (TypeQuals & DeclSpec::TQ_restrict) {
if (Result->isPointerType() || Result->isReferenceType()) {
QualType EltTy = Result->isPointerType() ?
Result->getAs<PointerType>()->getPointeeType() :
@@ -324,13 +324,13 @@
Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_invalid_pointee)
<< EltTy << DS.getSourceRange();
- TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
+ TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
}
} else {
Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_not_pointer)
<< Result << DS.getSourceRange();
- TypeQuals &= ~QualType::Restrict; // Remove the restrict qualifier.
+ TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
}
}
@@ -340,12 +340,14 @@
if (Result->isFunctionType() && TypeQuals) {
// Get some location to point at, either the C or V location.
SourceLocation Loc;
- if (TypeQuals & QualType::Const)
+ if (TypeQuals & DeclSpec::TQ_const)
Loc = DS.getConstSpecLoc();
- else {
- assert((TypeQuals & QualType::Volatile) &&
- "Has CV quals but not C or V?");
+ else if (TypeQuals & DeclSpec::TQ_volatile)
Loc = DS.getVolatileSpecLoc();
+ else {
+ assert((TypeQuals & DeclSpec::TQ_restrict) &&
+ "Has CVR quals but not C, V, or R?");
+ Loc = DS.getRestrictSpecLoc();
}
Diag(Loc, diag::warn_typecheck_function_qualifiers)
<< Result << DS.getSourceRange();
@@ -359,12 +361,14 @@
// FIXME: Shouldn't we be checking SCS_typedef here?
if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
TypeQuals && Result->isReferenceType()) {
- TypeQuals &= ~QualType::Const;
- TypeQuals &= ~QualType::Volatile;
+ TypeQuals &= ~DeclSpec::TQ_const;
+ TypeQuals &= ~DeclSpec::TQ_volatile;
}
- Result = Result.getQualifiedType(TypeQuals);
+ Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
+ Result = Context.getQualifiedType(Result, Quals);
}
+
return Result;
}
@@ -399,23 +403,25 @@
return QualType();
}
+ Qualifiers Qs = Qualifiers::fromCVRMask(Quals);
+
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
- if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+ if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) {
Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
- Quals &= ~QualType::Restrict;
+ Qs.removeRestrict();
}
// Build the pointer type.
- return Context.getPointerType(T).getQualifiedType(Quals);
+ return Context.getQualifiedType(Context.getPointerType(T), Qs);
}
/// \brief Build a reference type.
///
/// \param T The type to which we'll be building a reference.
///
-/// \param Quals The cvr-qualifiers to be applied to the reference type.
+/// \param CVR The cvr-qualifiers to be applied to the reference type.
///
/// \param Loc The location of the entity whose type involves this
/// reference type or, if there is no such entity, the location of the
@@ -426,8 +432,9 @@
///
/// \returns A suitable reference type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
+QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR,
SourceLocation Loc, DeclarationName Entity) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
if (LValueRef) {
if (const RValueReferenceType *R = T->getAs<RValueReferenceType>()) {
// C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
@@ -435,8 +442,8 @@
// reference to cv TD" creates the type "lvalue reference to T".
// We use the qualifiers (restrict or none) of the original reference,
// not the new ones. This is consistent with GCC.
- return Context.getLValueReferenceType(R->getPointeeType()).
- getQualifiedType(T.getCVRQualifiers());
+ QualType LVRT = Context.getLValueReferenceType(R->getPointeeType());
+ return Context.getQualifiedType(LVRT, T.getQualifiers());
}
}
if (T->isReferenceType()) {
@@ -449,7 +456,7 @@
// typedef int& intref;
// typedef intref& intref2;
//
- // Parser::ParserDeclaratorInternal diagnoses the case where
+ // Parser::ParseDeclaratorInternal diagnoses the case where
// references are written directly; here, we handle the
// collapsing of references-to-references as described in C++
// DR 106 and amended by C++ DR 540.
@@ -466,10 +473,10 @@
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
- if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+ if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
- Quals &= ~QualType::Restrict;
+ Quals.removeRestrict();
}
// C++ [dcl.ref]p1:
@@ -481,13 +488,13 @@
// We diagnose extraneous cv-qualifiers for the non-typedef,
// non-template type argument case within the parser. Here, we just
// ignore any extraneous cv-qualifiers.
- Quals &= ~QualType::Const;
- Quals &= ~QualType::Volatile;
+ Quals.removeConst();
+ Quals.removeVolatile();
// Handle restrict on references.
if (LValueRef)
- return Context.getLValueReferenceType(T).getQualifiedType(Quals);
- return Context.getRValueReferenceType(T).getQualifiedType(Quals);
+ return Context.getQualifiedType(Context.getLValueReferenceType(T), Quals);
+ return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);
}
/// \brief Build an array type.
@@ -513,6 +520,7 @@
QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceRange Brackets, DeclarationName Entity) {
+
SourceLocation Loc = Brackets.getBegin();
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
@@ -706,15 +714,17 @@
///
/// \param T the type to which the member pointer refers.
/// \param Class the class type into which the member pointer points.
-/// \param Quals Qualifiers applied to the member pointer type
+/// \param CVR Qualifiers applied to the member pointer type
/// \param Loc the location where this type begins
/// \param Entity the name of the entity that will have this member pointer type
///
/// \returns a member pointer type, if successful, or a NULL type if there was
/// an error.
QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
- unsigned Quals, SourceLocation Loc,
+ unsigned CVR, SourceLocation Loc,
DeclarationName Entity) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (CheckDistantExceptionSpec(T)) {
@@ -744,13 +754,13 @@
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
- if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+ if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
<< T;
// FIXME: If we're doing this as part of template instantiation,
// we should return immediately.
- Quals &= ~QualType::Restrict;
+ Quals.removeRestrict();
}
if (!Class->isDependentType() && !Class->isRecordType()) {
@@ -758,15 +768,15 @@
return QualType();
}
- return Context.getMemberPointerType(T, Class.getTypePtr())
- .getQualifiedType(Quals);
+ return Context.getQualifiedType(
+ Context.getMemberPointerType(T, Class.getTypePtr()), Quals);
}
/// \brief Build a block pointer type.
///
/// \param T The type to which we'll be building a block pointer.
///
-/// \param Quals The cvr-qualifiers to be applied to the block pointer type.
+/// \param CVR The cvr-qualifiers to be applied to the block pointer type.
///
/// \param Loc The location of the entity whose type involves this
/// block pointer type or, if there is no such entity, the location of the
@@ -777,15 +787,16 @@
///
/// \returns A suitable block pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildBlockPointerType(QualType T, unsigned Quals,
+QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR,
SourceLocation Loc,
DeclarationName Entity) {
- if (!T.getTypePtr()->isFunctionType()) {
+ if (!T->isFunctionType()) {
Diag(Loc, diag::err_nonfunction_block_type);
return QualType();
}
- return Context.getBlockPointerType(T).getQualifiedType(Quals);
+ Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+ return Context.getQualifiedType(Context.getBlockPointerType(T), Quals);
}
QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) {
@@ -921,8 +932,9 @@
case DeclaratorChunk::BlockPointer:
if (ShouldBuildInfo) {
if (SourceTy->isFunctionType())
- SourceTy = Context.getBlockPointerType(SourceTy)
- .getQualifiedType(DeclType.Cls.TypeQuals);
+ SourceTy
+ = Context.getQualifiedType(Context.getBlockPointerType(SourceTy),
+ Qualifiers::fromCVRMask(DeclType.Cls.TypeQuals));
else
// If not function type Context::getBlockPointerType asserts,
// so just give up.
@@ -939,8 +951,8 @@
case DeclaratorChunk::Pointer:
//FIXME: Use ObjCObjectPointer for info when appropriate.
if (ShouldBuildInfo)
- SourceTy = Context.getPointerType(SourceTy)
- .getQualifiedType(DeclType.Ptr.TypeQuals);
+ SourceTy = Context.getQualifiedType(Context.getPointerType(SourceTy),
+ Qualifiers::fromCVRMask(DeclType.Ptr.TypeQuals));
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
@@ -957,14 +969,16 @@
}
T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
break;
- case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Reference: {
+ Qualifiers Quals;
+ if (DeclType.Ref.HasRestrict) Quals.addRestrict();
+
if (ShouldBuildInfo) {
if (DeclType.Ref.LValueRef)
SourceTy = Context.getLValueReferenceType(SourceTy);
else
SourceTy = Context.getRValueReferenceType(SourceTy);
- unsigned Quals = DeclType.Ref.HasRestrict ? QualType::Restrict : 0;
- SourceTy = SourceTy.getQualifiedType(Quals);
+ SourceTy = Context.getQualifiedType(SourceTy, Quals);
}
// Verify that we're not building a reference to pointer to function with
@@ -974,15 +988,15 @@
D.setInvalidType(true);
// Build the type anyway.
}
- T = BuildReferenceType(T, DeclType.Ref.LValueRef,
- DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
+ T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals,
DeclType.Loc, Name);
break;
+ }
case DeclaratorChunk::Array: {
if (ShouldBuildInfo)
// We just need to get an array type, the exact type doesn't matter.
SourceTy = Context.getIncompleteArrayType(SourceTy, ArrayType::Normal,
- DeclType.Arr.TypeQuals);
+ DeclType.Arr.TypeQuals);
// Verify that we're not building an array of pointers to function with
// exception specification.
@@ -1009,7 +1023,8 @@
ASM = ArrayType::Normal;
D.setInvalidType(true);
}
- T = BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
+ T = BuildArrayType(T, ASM, ArraySize,
+ Qualifiers::fromCVRMask(ATI.TypeQuals),
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
break;
}
@@ -1028,7 +1043,8 @@
}
SourceTy = Context.getFunctionType(SourceTy, ArgTys.data(),
ArgTys.size(),
- FTI.isVariadic, FTI.TypeQuals);
+ FTI.isVariadic,
+ FTI.TypeQuals);
}
// If the function declarator has a prototype (i.e. it is not () and
@@ -1132,7 +1148,7 @@
Param->setType(ArgTy);
} else {
// Reject, but continue to parse 'float(const void)'.
- if (ArgTy.getCVRQualifiers())
+ if (ArgTy.hasQualifiers())
Diag(DeclType.Loc, diag::err_void_param_qualified);
// Do not add 'void' to the ArgTys list.
@@ -1198,8 +1214,9 @@
if (ShouldBuildInfo) {
QualType cls = !ClsType.isNull() ? ClsType : Context.IntTy;
- SourceTy = Context.getMemberPointerType(SourceTy, cls.getTypePtr())
- .getQualifiedType(DeclType.Mem.TypeQuals);
+ SourceTy = Context.getQualifiedType(
+ Context.getMemberPointerType(SourceTy, cls.getTypePtr()),
+ Qualifiers::fromCVRMask(DeclType.Mem.TypeQuals));
}
if (!ClsType.isNull())
@@ -1479,7 +1496,7 @@
SubIsPointer = true;
}
bool SubIsClass = CanonicalSubT->isRecordType();
- CanonicalSubT.setCVRQualifiers(0);
+ CanonicalSubT = CanonicalSubT.getUnqualifiedType();
BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
@@ -1501,7 +1518,7 @@
continue;
}
}
- CanonicalSuperT.setCVRQualifiers(0);
+ CanonicalSuperT = CanonicalSuperT.getUnqualifiedType();
// If the types are the same, move on to the next type in the subset.
if (CanonicalSubT == CanonicalSuperT) {
Contained = true;
@@ -1633,6 +1650,7 @@
/// space for the type.
static void HandleAddressSpaceTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S){
+
// If this type is already address space qualified, reject it.
// Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
// for two or more different address spaces."
@@ -1664,10 +1682,10 @@
addrSpace.setIsSigned(false);
}
llvm::APSInt max(addrSpace.getBitWidth());
- max = QualType::MaxAddressSpace;
+ max = Qualifiers::MaxAddressSpace;
if (addrSpace > max) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
- << QualType::MaxAddressSpace << ASArgExpr->getSourceRange();
+ << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
return;
}
@@ -1679,7 +1697,7 @@
/// specified type. The attribute contains 1 argument, weak or strong.
static void HandleObjCGCTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S) {
- if (Type.getObjCGCAttr() != QualType::GCNone) {
+ if (Type.getObjCGCAttr() != Qualifiers::GCNone) {
S.Diag(Attr.getLoc(), diag::err_attribute_multiple_objc_gc);
return;
}
@@ -1690,15 +1708,15 @@
<< "objc_gc" << 1;
return;
}
- QualType::GCAttrTypes GCAttr;
+ Qualifiers::GC GCAttr;
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
return;
}
if (Attr.getParameterName()->isStr("weak"))
- GCAttr = QualType::Weak;
+ GCAttr = Qualifiers::Weak;
else if (Attr.getParameterName()->isStr("strong"))
- GCAttr = QualType::Strong;
+ GCAttr = Qualifiers::Strong;
else {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
<< "objc_gc" << Attr.getParameterName();
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Sep 24 14:53:00 2009
@@ -188,7 +188,7 @@
/// not permitted (e.g., qualifiers on reference or function types). This
/// is the right thing for template instantiation, but probably not for
/// other clients.
- QualType AddTypeQualifiers(QualType T, unsigned CVRQualifiers);
+ QualType AddTypeQualifiers(QualType T, Qualifiers Qs);
/// \brief Transform the given statement.
///
@@ -1935,13 +1935,16 @@
if (getDerived().AlreadyTransformed(T))
return T;
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T);
+
QualType Result;
- switch (T->getTypeClass()) {
+ switch (Ty->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
Result = getDerived().Transform##CLASS##Type( \
- static_cast<CLASS##Type*>(T.getTypePtr())); \
+ static_cast<const CLASS##Type*>(Ty)); \
break;
#include "clang/AST/TypeNodes.def"
}
@@ -1949,25 +1952,19 @@
if (Result.isNull() || T == Result)
return Result;
- return getDerived().AddTypeQualifiers(Result, T.getCVRQualifiers());
+ return getDerived().AddTypeQualifiers(Result, Qs);
}
template<typename Derived>
QualType
-TreeTransform<Derived>::AddTypeQualifiers(QualType T, unsigned CVRQualifiers) {
- if (CVRQualifiers && !T->isFunctionType() && !T->isReferenceType())
- return T.getWithAdditionalQualifiers(CVRQualifiers);
+TreeTransform<Derived>::AddTypeQualifiers(QualType T, Qualifiers Quals) {
+ if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType())
+ return SemaRef.Context.getQualifiedType(T, Quals);
return T;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformExtQualType(const ExtQualType *T) {
- // FIXME: Implement
- return QualType(T, 0);
-}
-
-template<typename Derived>
QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) {
// Nothing to do
return QualType(T, 0);
@@ -2076,7 +2073,7 @@
return getDerived().RebuildConstantArrayType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2103,7 +2100,7 @@
T->getSizeModifier(),
T->getSize(),
Size.takeAs<Expr>(),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -2122,7 +2119,7 @@
return getDerived().RebuildConstantArrayWithoutExprType(ElementType,
T->getSizeModifier(),
T->getSize(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2138,7 +2135,7 @@
return getDerived().RebuildIncompleteArrayType(ElementType,
T->getSizeModifier(),
- T->getIndexTypeQualifier());
+ T->getIndexTypeCVRQualifiers());
}
template<typename Derived>
@@ -2165,7 +2162,7 @@
return getDerived().RebuildVariableArrayType(ElementType,
T->getSizeModifier(),
move(Size),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -2193,7 +2190,7 @@
return getDerived().RebuildDependentSizedArrayType(ElementType,
T->getSizeModifier(),
move(Size),
- T->getIndexTypeQualifier(),
+ T->getIndexTypeCVRQualifiers(),
T->getBracketsRange());
}
@@ -4462,14 +4459,14 @@
template<typename Derived>
QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) {
- return SemaRef.BuildPointerType(PointeeType, 0,
+ return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
template<typename Derived>
QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) {
- return SemaRef.BuildBlockPointerType(PointeeType, 0,
+ return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4477,7 +4474,7 @@
template<typename Derived>
QualType
TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, true, 0,
+ return SemaRef.BuildReferenceType(ReferentType, true, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4485,7 +4482,7 @@
template<typename Derived>
QualType
TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) {
- return SemaRef.BuildReferenceType(ReferentType, false, 0,
+ return SemaRef.BuildReferenceType(ReferentType, false, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4493,7 +4490,7 @@
template<typename Derived>
QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
QualType ClassType) {
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0,
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(),
getDerived().getBaseLocation(),
getDerived().getBaseEntity());
}
@@ -4700,7 +4697,7 @@
QualType T) {
if (T->isDependentType() || T->isRecordType() ||
(SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
- assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here");
+ assert(!T.hasQualifiers() && "Can't get cv-qualifiers here");
return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
T.getTypePtr());
}
Modified: cfe/trunk/test/Sema/address_spaces.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/address_spaces.c?rev=82705&r1=82704&r2=82705&view=diff
==============================================================================
--- cfe/trunk/test/Sema/address_spaces.c (original)
+++ cfe/trunk/test/Sema/address_spaces.c Thu Sep 24 14:53:00 2009
@@ -33,6 +33,6 @@
__attribute__((address_space(256))) void * * const base = 0;
void * get_0(void) {
return base[0]; // expected-error {{illegal implicit cast between two pointers with different address spaces}} \
- expected-warning {{returning 'void __attribute__((address_space(256)))*' discards qualifiers, expected 'void *'}}
+ expected-warning {{returning 'void __attribute__((address_space(256))) *' discards qualifiers, expected 'void *'}}
}
More information about the cfe-commits
mailing list